I have two nodes in a Docker Swarm cluster. One of those nodes has an OpenVPN client connection to a VPN provider on interface tun0
. My goals are,
- Any services assigned to this node exclusively use the VPN connection
- No leaks (i.e., DNS or other traffic)
- If the VPN disconnects, all traffic gets dropped
- Allow service discovery and connections to other containers in the Swarm
For DNS, I have added a dns
entry to /etc/docker/daemon.json
that uses the VPN provider's DNS servers that are only accessible through the VPN.
Here are the iptable rules I have come up with:
iptables -I DOCKER-USER 1 -o tun0 -j ACCEPT
iptables -I DOCKER-USER 2 -i tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I DOCKER-USER 3 -j DROP
The resulting DOCKER-USER
chain looks like this:
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * tun0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- tun0 * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
From basic tests like running nslookup
and curl
with the VPN connection on and off these rules seem to work, but I have very little experience with iptables. Is this the correct way of doing this?
Best Answer
IPtables is linear and it reads the rules from top to bottom until it reaches a ACCEPT, REJECT, or DROP target, and then it stops reading the rules. In your case, you want to have
iptables -I DOCKER-USER -j DROP
as the very last rule in your chain, otherwise every packet will be dropped. Also, there is no need for the RETURN rule at the end, because IPtables will stop reading rules once it reaches the DROP rule right above it. Those IPtables rules with tun0 look fine, but makes sure you have these rules as well:For good practice, make sure you accept all loopback traffic, which will never reach the internet nor will it leave the machine:
Let's go through your requirements one-by-one:
You would not use IPtables to do this. Run these commnds on the servers:
I think OpenVPN typically uses 10.8.0.0/16, so the default gateway would probably be 10.8.0.1 or something like that. IProute2 (ip command) is built into the kernel, just like IPtables.
You should first redirect all traffic through the VPN by putting this in your OpenVPN's server config:
This makes the clients put all of their traffic through the VPN, even DNS and such. If the OpenVPN server goes down, the internet will stop working on the clients.
See step 2
I believe OpenVPN does this by default. I am able to ping/arp from one client to other clients that are on the OpenVPN server. You should definitely be able to access services that are on other clients.
I hope this answers your questions!