Simple PoC wireguard tunnel connecting containers on two hosts.
Creates wireguard tunnel between two hosts. For testing purposes, starts Docker containers on each host to allow a test connection from containers on the two
hosts via wireguard tunnel. Note, that wireguard has masterless architecture, the terms server
and client
are used below for intuition.
git clone https://github.com/dav23r/wgtunnel
cd wgtunnel
go build .
At this point target binary ./tunnel
is created. It should be run with superuser privileges since it creates network devices via netlink
.
On both server and the client docker
client and runtime and kernel implementation of wireguard
should be present.
dav23r@dav23r-NUC7i3DNKE:~$ sudo ./tunnel
<Wireguard Tunnel>
Deploying server side of the tunnel
Interface exists: wg-tunnel, deleting to recreate
Interface added
Successfully applied server endpoint configuration
On client, run specifying ip of server where deployment was made:
$ ./tunnel iIL0sJR2ZJOT4CBqm42/WVKGVcqk8xyGNIzoUNMQzDo= 0GRr3dTNsUdfnreeXgAbaKS17xqHU3hfxdyGIngb1nA= <public ip of server>
Nginx started on 10.0.0.1:8080, to test run on the client:
$ curl 10.0.0.1:8080
Issue ^-C to tear down the setup
This deploys wireguard server side configuration and starts Nginx contrainer. It spits back tokens for client side of utility which should be fed to
./tunnel
. Pay attention that novel tokens are generated on each invocation meaning that you can set up client with only recent tokens.
<public ip of server>
should changed into HOST A
's ip address on the network over which wireguard will tunnel traffic. You should leave the program
running for the tunnel and container to work. Interrupting it shuts down the container gracefully.
[dav23r@lenovo-e495 tunnel]$ sudo ./tunnel iIL0sJR2ZJOT4CBqm42/WVKGVcqk8xyGNIzoUNMQzDo= 0GRr3dTNsUdfnreeXgAbaKS17xqHU3hfxdyGIngb1nA= 192.168.88.153
[sudo] password for dav23r:
<Wireguard Tunnel>
Deploying client side of the tunnel
Interface exists: wg-tunnel, deleting to recreate
Interface added
Successfully applied client endpoint configuration
Starting curl container
Client curl image started successfully, to test, run on other terminal:
$ docker exec -it curlContainer curl 10.0.0.1:8080
Issue ^-C to tear down the setup
Now it's time to run the utility on the client host. ./tunnel
needs to be provided tokens from generated by the server and server's ip address
(for wireguard tunnel). An image containing curl
is started as a container. You should leave the program running for the tunnel and container to work.
Interrupting it shuts down the container gracefully.
Finally, run curl
from the container connectng getting index.html
from Nginx on the other container via wireguard tunnel:
[dav23r@lenovo-e495 tunnel]$ docker exec -it curlContainer curl 10.0.0.1:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
- It would have been nicer if containers to be deployed on both hosts were pluggable, say from the environment variables.
- Currenlty wireguard interfaces on hosts are created in main netns meaning that connection from Docker host is masqueraded on the wireguard interface. It would have been nicer if interfaces were moved inside container netns, but Docker doesn't support that naitively.
- Rememember the aforementioned tokens? Well, one of the is actually a private key for client. Both key pairs are generated on the server side and are distributed in that crude manner. Abstracting secrets generation/distribution would have been nicer.
- Some more..