Stunnel is a tool that allows one to encapsulate existing protocols in a secure tunnel. This is similar to how one can do port forwarding with ssh. In addition to preventing the tunnel from being eavesdropped upon, it can also require that both ends be authenticated (i.e. each side can only connect if it proves who it is). The following is a tutorial to secure an example service on port 123 on Windows using stunnel.
On both machines:
- Download the stunnel installer from this site and install it.
- Download OpenSSL from this site and copy it somewhere on your machine (i.e. put it in %ProgramFiles%\OpenSSL or somewhere convenient). Get the latest version you can find. You need openssl.exe, libeay32.dll, libssl32.dll, zlib1.dll, etc.
- Get a reasonable OpenSSL.cnf from somewhere, for example this site. Save it to where you put OpenSSL.
On the server machine that has an unsecured service that you want to secure with stunnel:
- Make a directory to contain stunnel configuration files.
- cd to the directory that contains OpenSSL.
- Run:
openssl req -config openssl.cnf -new -newkey rsa:1024 -days 3650 -nodes -x509 -keyout "<dir you made>\stunnel.server.pem" -out "<dir you made>\stunnel.server.pem" - Answer the questions that it prompts you with. The data you enter will be stored in the certificate files you're making (and it'll be displayed in stunnel when you make connections with stunnel), so it is useful to make this text descriptive.
- In the directory that you created, create a stunnel.server.conf file with these contents:
cert = <full path to stunnel.server.pem file in the dir you made>
; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
verify = 3
CAfile = <full path to stunnel.client.pem in the dir you made>
[myservice]
accept=124
connect=123The full paths must not be quoted and must not contain spaces. You may have to specify short-filenames like C:\docume~1\SomeUs~1\MyDocu~1\stunnel.client.pem, etc.
- Make sure to block port 123 using your firewall so that no one can directly talk to the unencrypted service directly. Also, make sure to open up port 124 which is the port that stunnel will listen on.
On the client machine that will connect to the server over the tunnel:
- Make a directory to contain stunnel configuration files.
- cd to the directory that contains OpenSSL.
- Run:
openssl req -config openssl.cnf -new -newkey rsa:1024 -days 3650 -nodes -x509 -keyout "<dir you made>\stunnel.client.pem" -out "<dir you made>\stunnel.client.pem" - Answer the questions that it prompts you with.
- In the directory that you created, create a stunnel.client.conf file with these contents:
cert = <full path to stunnel.client.pem file in the dir you made>
; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1verify = 3
CAfile = <full path to stunnel.server.pem in the dir you made>
; Use it for client mode
client = yes[myservice]
; this accept should be local only
accept = 127.0.0.1:123
connect = <hostname or IP addr of server machine>:124Again, the full paths must not be quoted or have spaces.
- Securely copy the stunnel.server.pem file you created on the other machine to this machine, and put it in the directory you created on this machine.
- Start stunnel.exe on the client with:
"%ProgramFiles%\stunnel\stunnel.exe" <full path to stunnel.client.conf>
Again, the full path must not be quoted or have spaces.
On the server machine:
- Securely copy the stunnel.client.pem file you created to the server machine and put it in the directory you created on that server machine.
- Start stunnel.exe on the server with:
"%ProgramFiles%\stunnel\stunnel.exe" <full path to stunnel.server.conf>
Again, the full path must not be quoted or have spaces.
Now everything is setup, so on the client machine you can just connect to localhost:123 and you'll really be connected to port 123 on the server machine, all via stunnel connections.
Explanations
- By using verify=3 and specifying the CAfile options, it causes the server to validate the client and the client to validate the server. Only if they know each other (have each other's .pem files) is a connection made.
- Once you block port 123 on the server with your firewall, the only exposed port is port 124 on the server and it only allows encrypted communication with known clients.
- The way connecting works is your real client software connects to localhost:123. That is the 'client' instance of stunnel which connects to server:124 over an encrypted channel. Then the 'server' instance of stunnel connects unencrypted to server:123 (which is really on the same machine as the server).
Security Best Practices
- When running stunnel on the server, run it as a low-privileged user (i.e. non-Administrator).
- Configure the Windows Firewall to only allow connections to the stunnel server from specific IP addresses, if possible.
- When you don't need the tunnel up, don't run the stunnel server process.