Stunnel in DAB appliances

From Proxmox VE
Jump to: navigation, search

Why stunnel

Sometimes it is necessary to use a SSH Wrapper - stunnel4 / stunnel3 - for example if we have a server with a MySQL daemon on it that needs to have some databases accessed from another server's MySQL client.

Pre-requisites and Asumptions

For the sake of simplicity, I assume that both are OpenVZ DAB generated appliances having host names Remote-DB-Host (SERVER) and Data-Accessing-Host (CLIENT). We further assume that each host has it's own MySQL daemon running on the normal port 3306. We need to enable a MySQL client on the Data-Accessing-Host to access a MySQL DB in the Remote-DB-Host in a secure manner (SSH Wrapped). Let us assume the following for reference:

Remote-DB-Host - SERVER

IP: 192.168.5.15
MySQL Server Port: 3306
To be configured Incoming SSH MySQL Port: 3320

Data-Accessing-Host - CLIENT

IP: 192.168.5.45
MySQL Server Port: 3306
To be configured MySQL Client Access Port: 3310
To be configured MySQL Client SSH Outgoing Port: 3320
(same as Remote-DB-Host's Incoming SSH Port)

Installation

On both hosts' (SERVER and CLIENT) console, execute:

apt-get install stunnel

If all goes well, you will get stunnel v4 installed. The following is a sample output during the install:

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  stunnel4
Suggested packages:
  logcheck-database
The following NEW packages will be installed:
  stunnel stunnel4
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 151kB of archives.
After this operation, 434kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://ftp.debian.org lenny/main stunnel4 3:4.22-2 [141kB]
Get:2 http://ftp.debian.org lenny/main stunnel 3:4.22-2 [10.2kB]
Fetched 151kB in 3s (45.6kB/s)
Selecting previously deselected package stunnel4.
(Reading database ... 19375 files and directories currently installed.)
Unpacking stunnel4 (from .../stunnel4_3%3a4.22-2_i386.deb) ...
Selecting previously deselected package stunnel.
Unpacking stunnel (from .../stunnel_3%3a4.22-2_all.deb) ...
Processing triggers for man-db ...
Setting up stunnel4 (3:4.22-2) ...
Warning: The home dir /var/run/stunnel4 you specified can't be accessed: No such file or directory
Adding system user `stunnel4' (UID 104) ...
Adding new group `stunnel4' (GID 109) ...
Adding new user `stunnel4' (UID 104) with group `stunnel4' ...
Not creating home directory `/var/run/stunnel4'.
Setting up stunnel (3:4.22-2) ...

The installed version of stunnel can be obtained from: # dpkg -l 'stunnel*'

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name           Version        Description
+++-==============-==============-============================================
ii  stunnel        3:4.22-2       dummy upgrade package
ii  stunnel4       3:4.22-2       Universal SSL tunnel for network daemons

PEM Cerificate generation

The PEM certificate should by default exist as /etc/stunnel/stunnel.pem It must be generated on the SERVER and is optional on the CLIENT. The default certificate generation template (edit as needed) is at:

/usr/share/doc/stunnel4/examples/stunnel.cnf

The following normal method of certificate generation hangs (Ctrl-C to exit) on DAB appliances:

make-ssl-cert /usr/share/doc/stunnel4/examples/stunnel.cnf /etc/stunnel/stunnel.pem

Hence we will have to revert to it's equivalent:

openssl req -new -x509 -days 365 -nodes \
  -config /usr/share/doc/stunnel4/examples/stunnel.cnf \
  -out stunnel.pem \
  -keyout /etc/stunnel/stunnel.key

or the equivalent default:

cd /etc/stunnel
openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.key

In order to prevent hacking, the name of the stunnel.pem file is hashed using:

/usr/lib/ssl/misc/c_hash /etc/stunnel/stunnel.pem

This will result in some output like (yours will be different):

e56d2502.0 => /etc/stunnel/stunnel.pem

This should be the file name given to the link stored in /etc/ssl/certs/ folder like:

ln -s /etc/stunnel/stunnel.pem /etc/ssl/certs/e56d2502.0

or better still, if the /etc/stunnel/stunnel.pem file itself is renamed so.

On attempting to use stunnel, you will get the following error:

Wrong permissions on /etc/stunnel/stunnel.pem

This remedied by fixing the permission thus:

chmod 600 /etc/stunnel/stunnel.pem

A file named /etc/stunnel/stunnel.rnd will now have been created. This is the seed for the random number generator.

Server Configuration

We edit the /etc/stunnel/stunnel.conf file in the SERVER and comment out or delete every line leaving only the following in it:

; Certificate/key is needed in server mode and optional in client mode
cert = /etc/ssl/certs/stunnel.pem
;cert = /etc/stunnel/stunnel.pem
key = /etc/stunnel/stunnel.key
sslVersion = SSLv3
chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
; PID is created inside chroot jail
pid = /stunnel4.pid

; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1

; Service-level configuration

[mysqld]
accept  = 3320
connect = 3306

Client Configuration

We edit the /etc/stunnel/stunnel.conf file in the SERVER and comment out or delete every line leaving only the following in it:

; Certificate/key is needed in server mode and optional in client mode
cert = /etc/stunnel/stunnel.pem

sslVersion = SSLv3
chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
; PID is created inside chroot jail
pid = /stunnel4.pid
 
; Some performance tunings
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
 
; Use it for client mode
client = yes

; Service-level configuration

[mysqld]
accept  = 3310
connect = 192.168.5.15:3320

Note the presence of the client = yes line in the client config above.

SERVER and CLIENT stunnel Usage

We now edit /etc/default/stunnel4 making:

ENABLED=1

so that we may run stunnel as a service with default parameters set in the /etc/stunnel/stunnel.conf file.

We now start the stunnel with:

/etc/init.d/stunnel4 start

To stop it:

/etc/init.d/stunnel4 stop

The generic syntax is:

Usage: /etc/init.d/stunnel4 {start|stop|force-reload|restart}

We check the status with:

ps aux | grep 'stunnel*'

We should get something like this:

root     25454  0.0  0.0   3860   436 pts/0    S    08:13   0:00 stunnel4 stunnel.conf
root     25455  0.0  0.0   3860   436 pts/0    S    08:13   0:00 stunnel4 stunnel.conf
root     25456  0.0  0.0   3860   436 pts/0    S    08:13   0:00 stunnel4 stunnel.conf
root     25457  0.0  0.0   3860   436 pts/0    S    08:13   0:00 stunnel4 stunnel.conf
root     25458  0.0  0.0   3860   436 pts/0    S    08:13   0:00 stunnel4 stunnel.conf
stunnel4 25460  0.0  0.0   3936   988 ?        Ss   08:13   0:00 stunnel4 stunnel.conf
root     25464  0.0  0.0   1724   548 pts/0    S+   08:13   0:00 grep stunnel

SSH MySQL Client Access

Create a MySQL user (say remoteuser) in the SERVER machine with localhost access and a password and permissions to the databases needed.

On the CLIENT machine we can connect to the MySQL daemon on the SERVER, using:

mysql -h 192.168.5.45 --port=3310 -u remoteuser -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1005
Server version: 5.0.51a-24+lenny3 (Debian)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

and disconnect with:

mysql> exit
Bye

If we use localhost instead of the IP (192.168.5.45) in the above mysql connect string, we will get an error like:

inetd mode must define a remote host or an executable

This is peculiar to the OpenVZ Debian template since the localhost is mapped to 127.0.0.1 and not the LAN IP of 192.168.5.45 in the /etc/hosts file as the current LAN IP comes from the OpenVZ template config file at boot time only.

AutoRun At Startup

When stunnel4 is installed, it gets into the startup runlevel X scripts in /etc/rcX.d folders. This was automatically done by the install scripts using:

update-rc.d stunnel4 defaults 20

This does not work well atleast in OpenVZ containers. Hence we remove these runlevel symlinks and run them from the container's action scripts.

update-rc.d -f stunnel4 remove

On the Hardware Node where the container's (eg., assume VEID as 101) config files are stored, viz., /etc/vz/conf/ folder, we create two files as below:

  • /etc/vz/conf/101.start
#!/bin/bash
/etc/init.d/stunnel4 restart
  • /etc/vz/conf/101.stop
#!/bin/bash
/etc/init.d/stunnel4 stop

We use restart instead of start in 101.start file as it may already have been started. We then restart the container.

Updated Autostart for "insserv" based containers

With the use of LSB tags in insserv instead of update-rc startup scripting, the above 101.start and 101.stop type files are not necessary and stunnel will not autostart anymore using this method. The error (# dmesg | tail) states that /proc is not mounted as yet.

The following procedure will enable stunnel to autostart:

  • Create /etc/init.d/autostart having:
#!/bin/sh
/etc/init.d/stunnel4 start
  • Make it executable:
chmod +x /etc/init.d/autostart
  • Place a SymLink in the Auto Startup folder
cd /etc/rcS.d
ln -s ../init.d/autostart /etc/rcS.d/S98autostart
  • Refresh the startup script list:
dpkg-reconfigure insserv sysv-rc
  • Reboot the container

Documentation and Links