8d5b2c
socat tunnel for encrypted rsync SST
8d5b2c
====================================
8d5b2c
8d5b2c
`wsrep_sst_rsync_tunnel` is an extension of the rsync-based [SST](http://galeracluster.com/documentation-webpages/glossary.html#term-state-snapshot-transfer)
8d5b2c
implementation that ships with mariadb. Its purpose is to encrypt
8d5b2c
communication between the donor and the joiner during an SST.
8d5b2c
8d5b2c
Encryption is implemented by means of a socat tunnel, using OPENSSL
8d5b2c
addresses. It can be configured via the regular openssl flags exposed
8d5b2c
by socat.
8d5b2c
8d5b2c
8d5b2c
## How to configure the script
8d5b2c
8d5b2c
This SST script can configured by setting a few keys in your favorite
8d5b2c
mariadb option file in addition to the usual galera settings.
8d5b2c
8d5b2c
    [mysqld]
8d5b2c
    ...
8d5b2c
    bind_address=<node-name>
8d5b2c
    wsrep_sst_method=rsync_tunnel
8d5b2c
    ...
8d5b2c
    
8d5b2c
    [sst]
8d5b2c
    tca=/path/to/your/ca-file.crt
8d5b2c
    tcert=/path/to/node/certificate.crt
8d5b2c
    tkey=/path/to/node/key.key
8d5b2c
    sockopt=<openssl-address-options-as-per-socat-manual>
8d5b2c
8d5b2c
When a joiner node requests an SST, `wsrep_sst_rsync_tunnel` uses
8d5b2c
socat to listen to incoming SSL connections on port 4444 in lieu of
8d5b2c
the original rsync daemon. Received data will be forwarded to the
8d5b2c
rscynd daemon started locally to replicate the database.
8d5b2c
8d5b2c
When a donor node serves the SST, `wsrep_sst_rsync_tunnel` makes
8d5b2c
a series of rsync calls that target a locally started socat daemon.
8d5b2c
The daemon tunnels all rsync traffic into an encrypted SSL connection
8d5b2c
that targets the joiner's end of the socat tunnel.
8d5b2c
8d5b2c
Encryption parameters are specified under the `[sst]` group in the
8d5b2c
mariadb option file, where `tkey` and `tcert` are respectively the key
8d5b2c
and the certificate that are used by both sides of the socat tunnel.
8d5b2c
Each node typically has a different key and cert. Both key and
8d5b2c
certificate can be combined into a single PEM file and referenced by
8d5b2c
`tcert`. Option `tca` holds a list of the trusted signing
8d5b2c
certificates.
8d5b2c
8d5b2c
In case you need to tweak the creation of the SSL connection, you can
8d5b2c
pass valid socat options (as per socat manual) via the `sockopt` key.
8d5b2c
For debugging purpose, the exact socat command that is being executed
8d5b2c
shows up in the mariadb log file.
8d5b2c
8d5b2c
Note that socat verifies that the certificate's commonName matches
8d5b2c
that of the host that is being targeted. The target name comes from
8d5b2c
the value configured in `bind_address`, so it's important that it
8d5b2c
matches the certificate's commonName. An IP address can be used for
8d5b2c
`bind_address`, but you may get into trouble in case different
8d5b2c
hostnames resolve to the same IP (e.g. multiple networks per host).
8d5b2c
8d5b2c
8d5b2c
## Examples of use
8d5b2c
8d5b2c
Suppose you're running a 3-node galera cluster
8d5b2c
`node1.my.cluster`, `node2.my.cluster`, `node3.my.cluster`.
8d5b2c
8d5b2c
### Scenario: using self-signed certificates
8d5b2c
8d5b2c
On each node, create a key and a certificate, and bundle them into a
8d5b2c
single PEM file. For instance on `node1.my.cluster`:
8d5b2c
8d5b2c
    openssl genrsa -out /tls/mysql-$(hostname -f).key 2048
8d5b2c
    openssl req -new -key /tls/mysql-$(hostname -f).key -x509 -days 365000 -subj "/CN=$(hostname -f)" -out /tls/mysql-$(hostname -f).crt -batch
8d5b2c
    cat /tls/mysql-$(hostname -f).key /tls/mysql-$(hostname -f).crt > /tls/mysql.pem
8d5b2c
8d5b2c
Then, on each node, create a cafile that will contain all the certs to
8d5b2c
trust:
8d5b2c
8d5b2c
    for n in node1.my.cluster node2.my.cluster node3.my.cluster; do
8d5b2c
       ssh $n 'cat /tls/mysql-$(hostname -f).crt' >> /tls/all-mysql.crt
8d5b2c
    done
8d5b2c
8d5b2c
Once you have those two files on each host, you can configure the SST
8d5b2c
appropriately. For instance from `/etc/my.cnf.d/galera.cnf`:
8d5b2c
8d5b2c
    [mysqld]
8d5b2c
    ...
8d5b2c
    
8d5b2c
    [sst]
8d5b2c
    tca=/tls/all-mysql.crt
8d5b2c
    tcert=/tls/mysql.pem
8d5b2c
8d5b2c
### Scenario: using self-signed certificates, without verification
8d5b2c
8d5b2c
By default, when socat tries to establish a SSL connection to a peer,
8d5b2c
it also verifies that it can trust the peer's certificate. If for some
8d5b2c
reason you need to disable that feature, you can amend the previous
8d5b2c
configuration with a sockopt option:
8d5b2c
8d5b2c
    [mysqld]
8d5b2c
    ...
8d5b2c
    
8d5b2c
    [sst]
8d5b2c
    tca=/tls/all-mysql.crt
8d5b2c
    tcert=/tls/mysql.pem
8d5b2c
    sockopt="verify=0"
8d5b2c
8d5b2c
The associated sockopt value is passed to socat when
8d5b2c
the donor or the joiner configures his part of the tunnel.
8d5b2c
8d5b2c
Note: please do not do so in production, this is inherently insecure
8d5b2c
as you will not verify the identity of the peer you're connecting to!
8d5b2c
8d5b2c
### Scenario: using certificates from a CA
8d5b2c
8d5b2c
Suppose you have a FreeIPA service which generated a key file and a
8d5b2c
certificate file for the three galera nodes, respectively located at
8d5b2c
/tls/mysql.key and /tls/mysql.crt.
8d5b2c
8d5b2c
Assuming that the certificate for the FreeIPA server is available at
8d5b2c
/etc/ipa/ca.crt, you can configure you galera servers as follows:
8d5b2c
8d5b2c
    [sst]
8d5b2c
    tca=/etc/ipa/ca.crt
8d5b2c
    tcert=/tls/mysql.crt
8d5b2c
    tkey=/tls/mysql.key
8d5b2c
8d5b2c
## License
8d5b2c
8d5b2c
Copyright © 2017 [Damien Ciabrini](https://github.com/dciabrin).
8d5b2c
This work is derived from the original `wsrep_rsync_sst`, copyright
8d5b2c
© 2010-2014 [Codership Oy](https://github.com/codership).
8d5b2c
Released under the GNU GPLv2.