wormhole
A smart proxy that connects docker containers
Wormhole is a namespace-aware socket-activated tunneling proxy. It allows you
to securely connect ports together on different physical machines inside
docker containers. This allows for interesting things like connecting services
running on localhost inside the container namespace or creating on-demand
services that start when you connect to them.
But Why?
Containers give us the opportunity to move a whole bunch of complicated
distributed systems problems (orchestration, service discovery, configuration
management, and security) into the communication layer. They have the
potential to finally give us truly standard components
This isn't intended to be a production solution for container relationships.
Consider it an exploration of the above value. If you can create an
application container that talks to a single port to get a secure connection
to the database, many things get simpler. You don't have to configure the
application with the proper address. You don't have to set a secure password
for the database server. You can move the database without breaking the
application. You can add a second database and start load balancing.
Most importantly, standardizing the communication layer means that containers
are trivially sharable. Everyone who needs a mysql database container can
use the same one. No configuration of the container is necessary, you can just
drop it in and start using it.
Yes it is computationally more expensive to proxy connections, but consider:
- It is possible to accomplish many of the same things with sdn instead
of proxying
- This proxy could replace the proxies that many services already use
for load balancing or ssl termination.
Some people may feel that is inappropriate to proxy localhost connections this
way, that localhost traffic should always be local. The above principles can
be accomplished by using another well-known ip address. The one advantage of
the localhost approach is almost every application is configured to listen on
localhost out of the box so it makes container builds very easy.
Examples
Wormhole connects services together. The examples use the a wordpress
container and a mysql container as the canonical example of two things that
need to be connected.
Legend for diagrams

Proxy to the mysql in a local container

mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns tail docker-ns $mysql
mysql -u root -h 127.0.0.1
This requires a local install of mysql-client (ubuntu: apt-get install mysql-client).
Connect a local wp container to a local mysql container

app=`docker run -d wormhole/wordpress`
mysql=`docker run -d wormhole/mysql`
./wormhole create url :3306 docker-ns $app tail docker-ns $mysql
Create a local port that does the above on connection

./wormhole create url :80 trigger docker-run wormhole/wordpress \
child url :3306 trigger docker-run wormhole/mysql
Create a local port to talk to a remote mysql

mysql=`docker -H myserver run -d wormhole/mysql`
./wormhole create url :3306 remote myserver tail url :3306 docker-ns $mysql
The remote server must be running wormhole with the same key.secret
Do the above over an ipsec tunnel

mysql=`docker -H myserver run -d wormhole/mysql`
./wormhole create url :3306 tunnel myserver trigger url :3306 docker-ns $mysql
Create a local port that runs a remote mysql on connection

./wormhole create url :3306 trigger tunnel myserver trigger url :3306 docker-run wormhole/mysql
If the image has not been downloaded on 'myserver' then the initial
connection will timeout.
Create a local port that runs wp followed by the above

./wormhole create url :80 trigger docker-run wormhole/wordpress \
child url :3306 tunnel myserver trigger url :3306 docker-run wormhole/mysql
Forget all this proxy stuff and make an ipsec tunnel

./wormhole tunnel-create myserver
This command outputs a local and remote ip for the tunnel. Tunnels are
not deleted when wormholed is closed. To delete the tunnel:
./wormhole tunnel-delete myserver
Getting Started
To get started you will need to:
a) Create a secret key
sudo mkdir -p /etc/wormhole
cat /dev/urandom | tr -dc '0-9a-zA-Z' | head -c 32 | sudo tee /etc/wormhole/key.secret
sudo chmod 600 /etc/wormhole/key.secret
b) Run the daemon as root
sudo ./wormholed
The wormhole cli communicates with the daemon over port 9999. To verify it
is working:
./wormhole ping
Local Build and Test
Getting the source code:
go get github.com/vishvananda/wormhole
Building the binaries (will install go dependencies via go get):
make
Testing dependencies:
docker is required for functional tests
Unit Tests (functional tests use sudo):
make test-unit
Functional tests (requires root):
make test-functional # or sudo -E go test -v functional_test.go
Most of what wormhole does can be accomplished by hacking together various
tools like socat and iproute2.
Future Work
Wormhole could be extended to support unix socket proxying. It would also be
interesting to allow proxies from one type of socket to another a la socat.
Wormhole discovers existing tunnels when it starts, but it doesn't attempt
to cleanup if it finds a partial tunnel. This option could be added.
Namespace support should be upstreamed to kubernetes/proxy so we don't have
to maintain a fork.
Commands for list and tunnel-list should be added.
Wormhole could grow support for load balancing.
Traffic analysis and reporting could be added to the proxy layer.
Disclaimer
Wormhole is alpha quality code and, while efforts have been made to keep the
daemon secure, it must run as root and therefore offers a tempting attack
surface. It is not recommended to run this in production until it has been
more thouroughly vetted.