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
Alternative Tools
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.