feat: added support for running the VPN router on a host with Docker Community Edition.
Release / release (push) Successful in 1m8s

This commit is contained in:
slawek committed 2026-10-23 13:17:32 +02:00
1 parent 66fcd69d40
commit 2e0cee10ac
10 files changed
+279 -1

No files matched your search

+59 -1
View File
@@ -6,6 +6,7 @@ A Debian package that configures a Linux host or virtual machine as a VPN router
- road-warrior (P2S) access using IKEv2 EAP-TLS, with a bundled certificate authority
- optional WireGuard endpoint
- routing and NAT for a protected subnet, TCP MSS clamping, and UFW firewall rules
- firewall rules for the ports Docker publishes, when Docker is installed
Nothing in the package is specific to a cloud provider. It is built on the external and
internal NIC names, and a `mode` setting says how much of the rest you are supplying and
@@ -28,6 +29,10 @@ service that applies it.
systemctl restart vpn-router-setup apply it
```
If the host runs Docker, the recommended order is Docker first and the package second. The
package secures the ports Docker publishes when it finds the Docker service; the steps for a
host that already runs Docker, and for installing Docker later, are under [Docker](#docker).
### By hand
```sh
@@ -108,6 +113,8 @@ must have the type shown below; an unknown section or setting is an error.
| `wireguard` | `enabled` | boolean | `false` | WireGuard endpoint |
| `wireguard` | `address` | string | | Address and prefix for `wg0`, for example `192.168.200.1/24` |
| `wireguard` | `listen_port` | integer | `51820` | UDP port |
| `docker` | `mode` | string | `auto` | `auto` secures Docker when its service is installed, `on` requires it, `off` removes the rules |
| `docker` | `exposed_ports` | list | | TCP ports and port ranges (`8000:8100`) reachable from the external interface; at most 15, a range counting as two |
A minimal site-to-site configuration in `auto` mode:
@@ -153,6 +160,56 @@ interface does not exist the service stops and says so. In `interfaces` and `aut
the internal gateway is taken from the routing table, falling back to the first host
address of the connected subnet with a warning when the routing table has nothing to say.
## Docker
Docker publishes container ports in its own firewall rules, which bypass UFW and can expose
ports on the external interface. Docker evaluates the `DOCKER-USER` chain before its own
rules, so the package filters there. With `docker.mode` set to `auto`, the package secures
Docker when `docker.service` is installed, and does nothing otherwise.
### On a host that already runs Docker
Installing Docker first is the recommended order. After installing the package:
1. Set `general.platform` in `/etc/vpn-router/vpn-router.json`. While it is `none`, nothing is
configured, the Docker rules included.
2. List the TCP ports the running containers must expose to the internet, for example
`"docker": { "exposed_ports": ["443"] }`. The default is none: once the rules are applied,
every published port that is not listed is unreachable from the external interface, and
remains reachable through the IPsec tunnel.
3. Apply the configuration with `systemctl restart vpn-router-setup`. Docker is running, so
this also restarts `vpn-router-docker`, which installs the rules.
4. Check the result:
```sh
iptables -S DOCKER-USER # "-j VPN-ROUTER-DOCKER" is the first rule
iptables -S VPN-ROUTER-DOCKER # the rules of the external interface
```
### When Docker is installed after the package
The Docker rules are not applied when Docker starts for the first time, so run
`systemctl restart vpn-router-setup` after installing Docker, then check as above. A reboot or a
restart of Docker applies them as well.
The rules sit in their own chain, `VPN-ROUTER-DOCKER`, entered by one jump at the top of
`DOCKER-USER`; other rules in `DOCKER-USER` are left alone. For traffic that arrives on the
external interface, in this order:
1. IPsec protected traffic is accepted.
2. TCP to the ports in `docker.exposed_ports` is accepted; none by default.
3. Packets of established and related connections are accepted.
4. Everything else is dropped.
Traffic from every other interface, including the internal one and the Docker bridges, is
not affected. The rules cover IPv4 only.
The `vpn-router-docker` service applies the rules after `docker.service` starts and removes
them when Docker stops, so restarting Docker restores them. `systemctl restart
vpn-router-setup` applies a changed configuration while Docker runs. With `docker.mode` set to
`on`, the service fails when Docker is not installed or its daemon is not running; with
`off` it removes the rules.
## Applying changes
```sh
@@ -256,7 +313,8 @@ modules shipped with the package; the configuration file accepts any module inst
## Removal
`apt-get remove` terminates the tunnels and takes `wg-quick@wg0` down, but leaves the
`apt-get remove` stops `vpn-router-docker`, which removes the Docker rules. It terminates the
tunnels and takes `wg-quick@wg0` down, but leaves the
configuration in place. `strongswan` is left enabled, since it is a shared service that
may be in use by something else.