You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Go to file
dadevel da6e84552b
make interface.public_key and peer.name optional
Thanks to @phromo for the hint.
2 years ago
.gitignore add setup script 3 years ago
LICENSE initial commit 4 years ago
README.md rewrite with dataclasses 2 years ago
setup.sh add setup script 3 years ago
wg-netns.py make interface.public_key and peer.name optional 2 years ago
wg-netns@.service rewrite with dataclasses 2 years ago

README.md

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 iproute2
  • wg 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