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 59a67b445c
rewrite with dataclasses
Adds 'managed' option and yaml support, renames env vars and can load profiles by name.
Closes #4.
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 rewrite with dataclasses 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