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