Tunneling OpenVPN through stunnel

Continuing my string of posts on trying to get OpenVPN working through China’s Great Firewall… and a recent (and unexpected but much appreciated) report that TCP & UDP ports are blocked quickly, I’m now looking at getting OpenVPN to work with stunnel.

My assumption is that the GFW is detecting the OpenVPN packets, since they’re not pure SSL, and then blocking the IP & port combination. (Yay for packet inspection.) So, right now, I’m thinking use stunnel to wrap the OpenVPN packets in a pure SSL connection. Of course, performance is going to suffer, since we’re now triple layering TCP (first layer: stunnel, second layer: OpenVPN, third layer: the actual web browsing).

But that’s enough theory, onwards to the setup:

The first thing to do was to get stunnel on both my server and laptop. Server was easy – since I’m using Fedora, it was simply yum install stunnel, and it was done. Laptop was a tad more difficult – I had to get the Windows version from the stunnel site, and then install it. (My friend’s laptop is going to be a bit harder, since it’s running OS X, but rudix has a stunnel package, so I’m hoping it’s easier than having to install the Mac OS X dev tools and having to compile the stunnel code.)

Next, I setup stunnel on the server side:

1. Get the certificates setup

Stunnel runs everything over SSL. SSL requires certificates. We don’t have certificates. Therefore, we have to create them:
openssl req -new -x509 -days 3650 -nodes -out /etc/stunnel/stunnel.pem -keyout /etc/stunnel/stunnel.pem

This dumps the newly generated cert into the /etc/stunnel directory, where we’ll…

2. Create the conf files

For some strange strange reason, Fedora doesn’t come with a set of default config files. I have no clue why. So I had to create a barebones conf file:

cert = /etc/stunnel/stunnel.pem
pid = /var/run/stunnel.pid
output = /var/log/stunnel


The important thing to note here is that the IP address of the OpenVPN server needs to be specified – OpenVPN listens on a specific IP address. (YOu can verify this by looking at the output of netstat -nlp|grep openvpn). I tried using, but the OpenVPN client kept on failing to connect.

Regarding the choice of port number, I ‘randomly’ chose the port number from another tutorial about installing stunnel on CentOS. In theory, we should be running this on port 443 since (I’m hoping) the GFW expects SSL over that port. But with this primarily being a test, the next step was to:

3. Poke a hole in the firewall for stunnel

Again, it was pretty simple, given that I’ve had to mess around with iptables a lot in the past few days: iptables -A INPUT -p tcp --dport 4948 -j ACCEPT was enough to get a single port punched through. (Again, replace the dport with the correct port, whatever you’re using.)

4. Make stunnel start on boot

Again, stunnel is weird and doesn’t come with an init or systemd script. So the easy way around this is just to add a single line to the crontab. It should be possible to do this as a normal user (since we’re not touching the first 1024 ports, Linux should allow it), but I just did it in root’s crontab – start editing it with crontab -e, and add:

@reboot stunnel /etc/stunnel/stunnel.conf

That’s it for the server. Next, we look at the client:

stunnel on Windows is a bit of a strange beast. By default it comes with two config files – one named stunnel.conf, and the other named stunnel.cnf. However, poking at the files revealed that stunnel.cnf was simply used to generate a certificate during the install. Which we didn’t actually need, since we’re running in client mode. The upside is that we now only need to bother with one file: stunnel.conf

The easiest way to get at the config file is to find stunnel in your Start menu, right click on the “Edit stunnel.conf” link and select “Run as administrator”.

stunnel nicely installs a set of useful shortcuts in its start menu folder

stunnel nicely installs a set of useful shortcuts in its start menu folder

I only had to add 4 lines:

client = yes
accept =
connect = ip.add.re.ss:4948

And that was all that was needed to be done to get stunnel configured. However, OpenVPN needs to be configured to use the new port. Thankfully, this just means that all the connection profiles with random ports that I created can be replaced with a single line: remote localhost 31337.  (Assuming that you’re using OpenVPN over TCP instead of UDP.)

And that’s that.


Because this is more a trial run than anything else, I didn’t do much optimization and securing. However, two documents popped up in my Google searches but were not immediately useful: this, while being aimed at Debian users, has some interesting stuff on optimization (particularly the TCP_NODELAY options that look useful), and this, which has a bunch of stuff on using client certificates for authentication – something which is good to prevent MitM attacks (which might be used), so I’ll be looking into getting that running sometime later.


  1. #1 by John Mc Q on January 1, 2013 - 10:32 pm

    Hi! Thanks a lot for the hints.
    I have been running a personal vpn for months and now the new enforced policies are heavily disrupting its functioning. This is especially true for Beijing and China Unicom. I’m expecting the policy to be soon expanded nationwide.

    MitM attacks do occur. From time to time I see certificate warnings with unexpected data in the certificate details. Therefore a certificate challenge based authentication is desirable.

    Using a VPN over socks seems a good idea. The only issue is that by encrypting the all the communication the Great Firewall will notice a 100% encrypted traffic, which is unrealistic in normal life patterns. The Great Firewall caps encrypted connections to 3-60Kb/s max speed, drops 30% of packets most of the times and often kills (resets) the connection. A “persistance” mode is therefore advised to avoid information leackage (i.e. only allow outgoing connections for the socks/vpn ip).

    This makes real life internet browsing very hard and will have an impact on small business that relies on home-level internet packages.

  2. #2 by Kyle Lexmond on January 2, 2013 - 2:22 pm

    All pretty good points and information there. Bit worrying about the probable future expansion nation wide, and the MitM attacks. I wonder if they’re going to move to a policy where systems bought in China will come pre-installed with an extra trusted root certificate owned by the government, and HTTPS connections will be terminated at the router, inspected and resigned with the government cert. Enterprises are doing this, it’s not too much of a stretch to think that this would be used, considering that HTTPS is currently not inspected.

    Re the throttling encrypted connections bit, that’s interesting – is throttling still done if the other unencrypted connections are made? My main justification for setting up OpenVPN was that some sites and FaceTime/Skype would be restricted and I’d want to use them, but with reports of FaceTime & Skype not being blocked makes me wonder if using Firefox + FoxyProxy for specific sites might be a good way around the firewall that wouldn’t face degradation of speeds.

    I’m not too worried about information leakage, only being able to (fairly reliably) access blocked sites.

    And now that you mention home-level internet packages… any news if business/uni internet access are facing similar/less/more restrictions? There has been very little information published that I’ve found on the restrictions on the varying classifications of connections.

  3. #3 by John Mc Q on January 21, 2013 - 12:40 am

    Thanks for your reply Kyle.
    Yes I also can foresee this is the ultimate target. After all we have to remember that what bothers a government is the majority of the people. If a handful of individuals do not comply with the regulations and mind their own business, they are likely ignored.

    Re throttling, this only applies to SSL connections. It does not affect unencrypted traffic, either it being concurrent or subsequent. Local Chinese connections are always at highest speed allowed by the internet package.

    My main use of SSL tunnels is to access google.com. As simple as that. If you are in China and do not use a SSL tunnel you will find how terrible using Google is. The government provides huge disincentives to use it (it seems as Google is run by a Windows 95 server – lags, packet drops, timeouts, truncated searches, invalid links…)
    Speed degradation is not terrible for browsing, but is impossible to watch any kind of movie. You can set Foxyproxy to whitelist only *google.com/* and use the normal connection for loading other websites’ content.

    Skype is not restricted. It has never been. You can freely use it. Just remind to save your setup package as within China you are forced to use the government-approved Skype version should you need to re-download it from skype.com.

    Yes, I confirm you that home-level internet packages have more restrictive censorship than business-level ones. For instance connecting to overseas websites often takes ages (and several timeouts) during evenings with home packages. At the office, instead, performance is very good and I can use my openvpn connection still nowadays. At home, you know, it is automatically blocked now.

    There are also differences between cities and providers. Unicom is told to be more restrictive as it is a private company (49%). Stakeholders’ interest has never been freedom, just money – and they want to secure the business licence for operating in China. Big cities and sensitive provinces also have more restrictive policies (with Beijing being the worst).

    Look at the positive side: the Chinese government provides you a valid incentive to study the Chinese language when you are in China! Once you can manage it fluently, you may not feel the need for overseas websites any more. China’s intranet is huge and well populated! 😀

  4. #4 by Gao on June 23, 2013 - 1:22 am

    Interesting, we did the same thing for access the OpenVPN via Great Firewall.

  5. #5 by Zach on July 3, 2017 - 1:29 pm

    Any idea if this also prevents the TLS within TLS detection I’ve heard the GFW is able to do now? (I’d guess not, unless it’s somehow padding packets)

  6. #6 by Kyle Lexmond on July 4, 2017 - 11:22 am

    TLS within TLS would be an interesting thing to detect. I haven’t heard anything like that, but would hazard that the GFW would detect it because the TLS setup is pretty regular, and can be easily pattern matched. (eg look for TLS packets of size X, followed by size Y and then Z.)

    So no, it wouldn’t be likely to help without further modifications.

(will not be published)