Adds 'managed' option and yaml support, renames env vars and can load profiles by name. Closes #4.
4.3 KiB
wg-netns
wg-quick with support for Linux network namespaces. A simple Python script that implements the steps described at wireguard.com/netns.
Setup
Requirements:
- Python 3.7 or newer
ip
from iproute2wg
from wireguard-tools- optional: pyyaml python package for configuration files in YAML format, otherwise only JSON is supported
Installation:
git clone --depth 1 https://github.com/dadevel/wg-netns.git
sudo ./wg-netns/setup.sh
Usage
First, create a configuration profile. JSON and YAML file formats are supported.
Minimal JSON example:
{
"name": "ns-example",
"interfaces": [
{
"name": "wg-example",
"address": ["10.10.10.192/32", "fc00:dead:beef::192/128"],
"private-key": "4bvaEZHI...",
"peers": [
{
"public-key": "bELgMXGt...",
"endpoint": "vpn.example.com:51820",
"allowed-ips": ["0.0.0.0/0", "::/0"]
}
]
}
]
}
Full YAML example:
# name of the network namespace
name: ns-example
# if false, the netns itself won't be created or deleted, just the interfaces inside it
managed: true
# list of dns servers, if empty dns servers from default netns will be used
dns-server: [10.10.10.1, 10.10.10.2]
# shell hooks, e.g. to set firewall rules
pre-up: echo pre-up
post-up: echo post-up
pre-own: echo pre-down
post-down: echo post-down
# list of wireguard interfaces inside the netns
interfaces:
# interface name, required
- name: wg-site-a
# list of ip addresses, at least one entry required
address:
- 10.10.11.172/32
- fc00:dead:beef:1::172/128
private-key: nFkQQjN+...
# optional settings
listen-port: 51821
fwmark: 21
mtu: 1420
# list of wireguard peers
peers:
# public key is required
- public-key: Kx+wpJpj...
# optional settings
preshared-key: 5daskLoW...
endpoint: a.example.com:51821
persistent-keepalive: 25
# list of ips the peer is allowed to use, at least one entry required
allowed-ips:
- 10.10.11.0/24
- fc00:dead:beef:1::/64
# by default the networks specified in 'allowed-ips' are routed over the interface, 'routes' can be used to overwrite this behaivor
routes:
- 10.10.11.0/24
- fc00:dead:beef:1::/64
- name: wg-site-b
address:
- 10.10.12.172/32
- fc00:dead:beef:2::172/128
private-key: guYPuE3X...
listen-port: 51822
fwmark: 22
peers:
- public-key: NvZMoyrg...
preshared-key: cFQuyIX/...
endpoint: b.example.com:51822
persistent-keepalive: 25
allowed-ips:
- 10.10.12.0/24
- fc00:dead:beef:2::/64
Now it's time to setup your new network namespace and all associated wireguard interfaces.
wg-netns up ./example.yaml
Profiles stored under /etc/wireguard/
can be referenced by their name.
wg-netns up example
You can verify the success with a combination of ip
and wg
.
ip netns exec ns-example wg show
Or you can spawn a shell inside the netns.
ip netns exec ns-example bash -i
Or connect a container to it.
podman run -it --rm --network ns:/run/netns/ns-example alpine wget -O - https://ipinfo.io
Or do whatever else you want.
System Service
You can find a wg-quick@.service
equivalent at wg-netns@.service.
Place your profile in /etc/wireguard/
, e.g. example.json
, then start the service.
systemctl start wg-netns@example.service
Port Forwarding
With socat
you can forward TCP traffic from outside a network namespace to a port inside a network namespace.
socat tcp-listen:$OUTSIDE_PORT,reuseaddr,fork "exec:ip netns exec $NETNS_NAME socat stdio 'tcp-connect:$INSIDE_PORT',nofork"
Example: All connections to port 1234/tcp in the main/default netns are forwarded to port 5678/tcp in the ns-example namespace.
# terminal 1, create netns and start http server inside
wg-netns up ns-example
echo 'Hello from ns-example!' > ./hello.txt
ip netns exec ns-example python3 -m http.server 5678
# terminal 2, setup port forwarding
socat tcp-listen:1234,reuseaddr,fork "exec:ip netns exec ns-example socat stdio 'tcp-connect:127.0.0.1:5678',nofork"
# terminal 3, test access
curl http://127.0.0.1:1234/hello.txt