What do you do if you want to secure access to your Redis? Plain password authentication (i.e. the AUTH command) only gets you so far and in some cases you need something a little stronger. There are several ways you could go about that, such as firewalling your Redis or using spiped, but (post-Heartbleed) SSL is still one of my favorites. The following article explains how to set up a secure (read authenticated and encrypted) communication channel between your Redis client and server using stunnel. Naturally, this is the Do-It-Yourself hardcore approach, so if you want to have Redis and SSL without the heavy lifting, check out our plans and Redis clients that natively support SSL.
— Itamar
The following post had originally appeared on Benjamin Cane’s Blog on February 18th, 2014 at Sending redis traffic through an SSL tunnel with stunnel.
Lately if you have been paying attention to tech or even mainstream media you might have seen a few stories about data breaches. Sometimes these data breaches have allowed attackers to gather unencrypted passwords or credit card numbers. In the past these types of attacks still happened, but there was not as many attacks as today and when they happened they were kept secret. With more and more internet based services becoming part of peoples lives, there is even more targets for attackers who are looking to get sensitive data.
These attackers can often be quite crafty on the ways they get this data, many times they do it by gaining access to a database but another common place to capture and steal data is through unencrypted network traffic. There are many commonly used services that either do not support SSL encryption or that option is rarely used. Redis a distributed memory cache is a newer service that at this time does not support SSL connections. I’ve been using Redis lately on one of my side projects, but I keep finding myself limited by the lack of SSL encryption.
Redis has been designed for use within a trusted private network, and does not support SSL encrypted connections. While that is ok for many implementations, it does not lend well to cloud based implementations. While some cloud providers offer private networks, not all of them do. So if you want to run a Redis master on one server and your application on another, you have no choice but to leave that connection unencrypted. Leaving that sensitive traffic to be sent across the cloud providers network or even the general internet with no protection from someone with a network sniffer.
In this article I am going to show you how to secure your Redis connections with stunnel. This article should handle the SSL part of securing a connection but you should also follow the other recommendations in Redis Security.
The stunnel application is a SSL encryption wrapper that can tunnel unencrypted traffic (like redis) through a SSL encrypted tunnel to another server. While stunnel adds SSL encryption it does not guarantee 100% that the traffic will never be captured unencrypted. If an attacker was able to compromise either the server or client server they could capture unencrypted local traffic as it is being sent to stunnel.
In today’s article we will use stunnel to encrypt traffic from a client host to a server host. We will install stunnel on both the client andserver hosts and establish a tunnel that redirects localhost:6379
on client to the redis instance running on server.
We will first install redis and then setup stunnel to forward connections from external sources to the local redis instance.
To install redis we will use apt-get
root@server:~# apt-get install redis-server
After installation we only need to make one change to the redis configuration. For better security we will enable requirepass
which requires all clients to authenticate before being able to pull or put data from the redis instance.
root@server:~# vi /etc/redis/redis.conf
Find:
# requirepass foobared
Replace With:
requirepass <yourpass>
Example:
requirepass foobared
Upon installation redis-server
is started automatically, in order for our configuration changes to take effect we will need to restart the instance.
root@server:~# /etc/init.d/redis-server restart
Now that redis is installed and running we will install stunnel. For ease we will install stunnel with apt-get
as well.
root@server:~# apt-get install stunnel4
Unlike redis, stunnel doesn’t start on boot automatically. To start stunnel on boot we will need to edit the /etc/default/stunnel
file.
root@server:~# vi /etc/default/stunnel4
Find:
ENABLED=0
Replace With:
ENABLED=1
Like any other SSL protocol stunnel requires a certificate to use for client to server communication. While you could get a signed certificate from a certificate authority such as Verisign, since we are using this for internal purposes only we can create a self signed certificate.
First we will create a private key, I am using openssl
to create a 4096 bit RSA key. In my example I am using 4096 bit key as it adds more security than a 1024 or 2048 bit key.
root@server:~# openssl genrsa -out /etc/stunnel/key.pem 4096
Now that we generated a key we will now create a certificate. When generating the certificate we will be asked a series of questions; the answers provided are used to prove the validity of the certificate. The -days
flag specifies the number of days this certificate is valid for, you can modify this if you need to but 5 years should be good enough.
root@server:~# openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826
Since this is really only being used for internal communications there isn’t a right or wrong answer to these, but the below example can be used as a guide for answering the certificates question.
Example:
root@server:~# openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Arizona
Locality Name (eg, city) []:Phoenix
Organization Name (eg, company) [Internet Widgits Pty Ltd]:BenCane.com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:bencane.com
Email Address []:testing@example.com
We will combine both the key and certificate into a single file for stunnel to use. We will also change the file permissions to restrict who has access to read these key files.
root@server:~# cat /etc/stunnel/key.pem /etc/stunnel/cert.pem > /etc/stunnel/private.pem
root@server:~# chmod 640 /etc/stunnel/key.pem /etc/stunnel/cert.pem /etc/stunnel/private.pem
By default stunnel reads all *.conf
files in/etc/stunnel/
We will create a file named redis-server.conf
and place our configuration within it.
root@server:~# vi /etc/stunnel/redis-server.conf
Add:
cert = /etc/stunnel/private.pem
pid = /var/run/stunnel.pid
[redis]
accept = <yourexternalip>:6379
connect = 127.0.0.1:6379
Example:
cert = /etc/stunnel/private.pem
pid = /var/run/stunnel.pid
[redis]
accept = 10.0.3.65:6379
connect = 127.0.0.1:6379
By default redis listens to the localhost
IP 127.0.0.1
on port 6379
Our configuration has stunnel accept
connections on the external IP and forward the connections to the redis instance listening on 127.0.0.1:6379
After the configuration file is in place we will start stunnel.
root@server:/etc/stunnel# /etc/init.d/stunnel4 start
At this point the server host is setup and ready, and we need to setup the client server to initiate the SSL tunnel with stunnel.
For this example we will install redis-server
on the client as well; though this step is only to install the redis-cli
tool. Most likely you would not need to install redis-server
if you are using this setup for an application running on the client host; so keep in mind this part is optional.
root@client:~# apt-get install redis-server
By default redis starts on boot, however we do not want redis to be running on the client host. To disable redis from starting on boot we can use the update-rc.d
command.
root@client:~# /etc/init.d/redis-server stop
root@client:~# update-rc.d redis-server disable
Installing stunnel on the client is similar to the server installation, minus some configuration differences.
root@client:~# apt-get install stunnel4
To have stunnel start on boot we will need to edit the /etc/default/stunnel4
file.
root@client:~# vi /etc/default/stunnel4
Find:
ENABLED=0
Replace With:
ENABLED=1
In order to establish an SSL connection we will need the private.pem
file that we generated on the server host. You should always practice good certificate management with this key, if it was to fall into the wrong hands then the attacker could decrypt any SSL traffic that was previously captured
root@client:~# scp root@10.0.3.65:/etc/stunnel/private.pem /etc/stunnel/
root@client:~# chmod 640 /etc/stunnel/private.pem
The stunnel client configuration is very similar to the server configuration, to specify this stunnel instance is a client we will add client = yes
to the configuration.
root@client:~# vi /etc/stunnel/redis-client.conf
Add:
cert = /etc/stunnel/private.pem
client = yes
pid = /var/run/stunnel.pid
[redis]
accept = 127.0.0.1:6379
connect = <serverip>:6379
Example:
cert = /etc/stunnel/private.pem
client = yes
pid = /var/run/stunnel.pid
[redis]
accept = 127.0.0.1:6379
connect = 10.0.3.65:6379
On a client instance the accept
and connect
settings are reversed from the server configuration. This tells stunnel to listen locally on port 6379
and forward connections to the server host IP with port 6379
Once the configuration is in place we can start the stunnel service.
root@client:~# /etc/init.d/stunnel4 start
Now that both the server and client hosts have stunnel installed and a SSL tunnel established we can test this connection by using the redis-cli
command to connect to localhost on the client.
root@client:~# redis-cli -h localhost
redis localhost:6379> auth foobared
OK
The way this configuration works is when a client on the client host connects to port 6379
locally it will be forwarded through the SSL tunnel that stunnel has created with the server host and redirected to the redis instance running on server. To setup an application to call this instance you would simply install the application on the client host and have it connect to redis on localhost the same way my example showed.
This same setup could also be used for setting up Master/Slave replication in redis, however the Slave instance would need to listen to a port other than the default 6379
—
Benjamin Cane, a.k.a. @madflogo, is the founder of CloudRoutes and a Solutions Architect working on High & Continuous Availability systems in the financial services industry. He has been Administrating Linux and Unix systems for about 10+ years. You might find him writing and sharing stories about Linux, Unix, Python, DevOps, and other various Sysadmin-like things.
Visit Redis for more on Redis technologies.