Lots of server tools were made for private hosting. Behind your firewall, nobody knows you are naked. But, in 2013, it's Cloud time, everybody got its own naked virtual server, flavored with some SAAS. Some major services, like memcached recently got its authenticated version, REST ones can be easily proxified, but others, with classical sockets, remain unauthenticated : patching protocols is painful. UDP services don't like authentication, just use them in localhost, and forget mutualized hosting, LXC is now trendy. Mutualized hosting is like the subway, just use a light container like Velib (parisian bike as a service). TCP services can easily handle some authentication. With a persistent connection, it's easier, it's just a simple FSM (Finite State Machine), first give some credentials, and switch from not authenticated state to authenticated state. Mysql can do it, so you can. If you like standards, use SASL, and don't bother, just handle PLAIN authentication, nobody can beat shared secret or SSL for security. SSL is also a secret weapon, it replaces a classical socket with a secured none. SSL is a protocol which handles protocols. SSL can use authentication with certificates, and magically add authentication without modifying the guest protocol. SSL authentication is hard to use with public users, and you have to buy certificates. Inside your hosting solution, it's easier, you own the certificate authority, sign certificates for the servers and the clients. OpenVPN is a good example of certificate authentication. SSL is a complex beast, anything you do without understanding it can cause drama. Easy-RSA provides simple tools to handle certificates with good practices. Stunnel provides a simple proxy for adding SSL communication to any client or server. Don't try to handle broken or weak solutions, just use the best : if you own client and server side, you are the king of your mountain!
Here is samples for authenticating Carbon service, from Graphite project.
In a trusted computer, build your own PKI.
git clone git://github.com/OpenVPN/easy-rsa.git cd easy-rsa/easy-rsa/2.0/
Edit vars file, and sets informations about your country, company...
source vars ./build-ca
CA private key is the weakest link in your security chain, be careful. Build a server certificate
And some clients
.key files are private keys, be kind with them, .crt and .csr are public.
Stunnel is an old beast, born when inetd still ruled servers, but don't be afraid, it's still the best tool. Watch for HAproxy 1.5, it will handles SSL, and challenge Stunnel the elder.
Use a simple config file, with contemporary settings, no compatibility tricks. Here is a server config for wrapping Carbon server.
# vim:ft=dosini sslVersion = SSLv3 #public cert = /opt/graphite/ssl/carbon.crt #private key = /opt/graphite/ssl/carbon.key chroot = /var/lib/stunnel4/ setuid = stunnel4 setgid = stunnel4 ; PID is created inside the chroot jail pid = /stunnel4.pid socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 # This enables the mutual authentication verify = 2 # public CA, for client validation CAfile = /opt/graphite/ssl/ca.crt compression = zlib #debug = 5 output=/var/log/stunnel.log # Some cargo cult settings options = NO_SSLv2 options = SINGLE_ECDH_USE options = SINGLE_DH_USE [carbons] # the public port accept = 2103 # server just listen localhost connect = 127.0.0.1:2003
Client side is quite similar:
# vim:ft=dosini sslVersion = SSLv3 cert = client1.crt key = client1.key #setuid = stunnel4 #setgid = stunnel4 pid = /tmp/stunnel.pid socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 CAfile = ca.crt debug = 5 foreground = yes options = NO_SSLv2 options = SINGLE_ECDH_USE options = SINGLE_DH_USE [carbons] client = yes accept = 2003 connect = my.public.server.com:2103
It's just a test from a mac, no chown, no pid, no detach. If I connect my telnet to localhost:2003, the real server behind ssl answers. Client checks that the server certificate is signed with my own trusted authority, no risk of man in the middle with a forged certificate.
SSL can revoke certificates, just read the documentation.
Python and SSL
In this example, I don't want to modify the server side, Graphite stack is a bit messy and large, and I fear Twisted code, so, stunnel wraps graphite as a black box. But client side, it's easier, carbon protocol is dummy, and gstatsd, a python gevent Statsd clone is easy to hack.
Python handles SSL nicely, just like gevent.
#!/usr/bin/env python import socket import ssl import time s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_sock = ssl.wrap_socket(s, certfile="./client1.crt", keyfile="./client1.key", ca_certs="./ca.crt", ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_REQUIRED) ssl_sock.connect(('my.public.server.com', 2103)) now = int(time.time()) ssl_sock.write("local.test.toto 22 %d\n" % now)
You build a socket, wrap it with ssl (and your client certificates), and use it like a plain old socket.
The patch for Gstasd is as simple as this example.
I don't fear patching any Statsd clone (em ruby, nodejs, go ...), ssl is a standard, and Openssl is almost universal.
Http is not the only way to proxying stuff, like obfuscurity suggests with its backstop.
Ssl can already be used as a proxy instead of http.
Keep it simple, secure.