Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Mininet network to test WireGuard peer and endpoint-to-endpoint MTU issues
#!/usr/bin/env python3
import subprocess
import tempfile
from import Mininet
from mininet.cli import CLI
from mininet.log import setLogLevel, info
basePort = 50000
tunnelIdx = 0
def wireguardKeypair():
privkeyGen =
["/usr/bin/env", "wg", "genkey"],
pubkeyGen =
["/usr/bin/env", "wg", "pubkey"],
return (
def wireguardTunnel(hostA, hostAIP, tunnelIPA, hostB, hostBIP, tunnelIPB, allowedIPsA=None, allowedIPsB=None):
global tunnelIdx
for host in [hostA, hostB]:
if not hasattr(host, "wireguardTunnels"):
setattr(host, "wireguardTunnels", {})
hostA.wireguardTunnels[tunnelIdx] = {
"keypair": wireguardKeypair(),
"listenPort": basePort + tunnelIdx,
"tunnelIP": tunnelIPA,
"endpointIP": hostAIP,
"allowedIPs": allowedIPsA if allowedIPsA is not None else [f"{tunnelIPB}/32"],
hostB.wireguardTunnels[tunnelIdx] = {
"keypair": wireguardKeypair(),
"listenPort": basePort + tunnelIdx,
"tunnelIP": tunnelIPB,
"endpointIP": hostBIP,
"allowedIPs": allowedIPsB if allowedIPsB is not None else [f"{tunnelIPA}/32"],
for host, peer in [(hostA, hostB), (hostB, hostA)]:
tunnel = host.wireguardTunnels[tunnelIdx]
peerTunnel = peer.wireguardTunnels[tunnelIdx]
host.cmd(f"ip link add wg{tunnelIdx} type wireguard")
host.cmd(f"ip link set wg{tunnelIdx} up")
host.cmd(f"ip address add {tunnel['tunnelIP']}/32 dev wg{tunnelIdx}")
with tempfile.NamedTemporaryFile() as privkeyFile:
host.cmd(f"wg set wg{tunnelIdx} private-key {}")
host.cmd(f"wg set wg{tunnelIdx} listen-port {tunnel['listenPort']}")
host.cmd(("wg set wg{} peer {} endpoint {}:{} {} "
+ "persistent-keepalive 10").format(
" ".join([f"allowed-ips {ip}" for ip in tunnel["allowedIPs"]])
host.cmd(f"ip route add {peerTunnel['tunnelIP']} dev wg{tunnelIdx} src {tunnel['tunnelIP']}")
tunnelIdx += 1
return tunnelIdx - 1
net = Mininet(topo=None, build=False)
info("*** Add switches\n")
s1 = net.addSwitch("s1", failMode="standalone")
s2 = net.addSwitch("s2", failMode="standalone")
s3 = net.addSwitch("s3", failMode="standalone")
s4 = net.addSwitch("s4", failMode="standalone")
info("*** Add hosts\n")
h1 = net.addHost("h1", ip="")
h2 = net.addHost("h2", ip="")
h3 = net.addHost("h3", ip="")
h4 = net.addHost("h4", ip="")
h5 = net.addHost("h5", ip="")
# Manually assign v6 addresses, as mininet does not support IPv6
v6Links = []
def v6Link(link, addr):
global v6Links
v6Links += [(link.intf1, addr)]
# Connect h1 to h2
v6Link(net.addLink(h1, s1), "fd00:0:0:0::1/64")
v6Link(net.addLink(h2, s1), "fd00:0:0:0::2/64")
# Connect h2 to h3
v6Link(net.addLink(h2, s2, params1={"ip": ""}), "fd00:0:0:1::1/64")
v6Link(net.addLink(h3, s2), "fd00:0:0:1::2/64")
# Connect h3 to h4
v6Link(net.addLink(h3, s3, params1={"ip": ""}), "fd00:0:0:2::1/64")
v6Link(net.addLink(h4, s3), "fd00:0:0:2::2/64")
# Connect h4 to h5
net.addLink(h4, s4, params1={"ip": ""})
net.addLink(h5, s4)
info("*** Starting network\n")
# Install all of the IPv6 addresses
for intf, v6addr in v6Links:
intf.node.cmd(f"ip -6 addr add {v6addr} dev {}")
for host in [h1, h2, h3, h4, h5]:
host.cmd("sysctl net.ipv4.ipfrag_low_thresh=0")
host.cmd("sysctl net.ipv4.ipfrag_high_thresh=0")
host.cmd("sysctl net.ipv4.ip_forward=1")
host.cmd("sysctl net.ipv6.ipfrag_low_thresh=0")
host.cmd("sysctl net.ipv6.ipfrag_high_thresh=0")
host.cmd("sysctl net.ipv6.conf.all.forwarding=1")
# Populate regular L3 routing tables (done manually here, tedious but
# works)
h1.cmd("ip route add via")
h1.cmd("ip -6 route add fd00:0:0:1::/64 via fd00:0:0:0::2")
h1.cmd("ip route add via")
h1.cmd("ip -6 route add fd00:0:0:2::/64 via fd00:0:0:0::2")
h1.cmd("ip route add via")
h1.cmd("ip -6 route add fd00:0:0:3::/64 via fd00:0:0:0::2")
h2.cmd("ip route add via")
h2.cmd("ip -6 route add fd00:0:0:2::/64 via fd00:0:0:1::2")
h2.cmd("ip route add via")
h2.cmd("ip -6 route add fd00:0:0:3::/64 via fd00:0:0:1::2")
h3.cmd("ip route add via")
h3.cmd("ip -6 route add fd00:0:0:0::/64 via fd00:0:0:1::1")
h3.cmd("ip route add via")
h3.cmd("ip -6 route add fd00:0:0:3::/64 via fd00:0:0:2::2")
h4.cmd("ip route add via")
h4.cmd("ip -6 route add fd00:0:0:0::/64 via fd00:0:0:2::1")
h4.cmd("ip route add via")
h4.cmd("ip -6 route add fd00:0:0:1::/64 via fd00:0:0:2::1")
h1h4Tunnel = wireguardTunnel(
h1, "fd00:0:0:0::1", "",
h4, "fd00:0:0:2::2", "",
allowedIPsA = ["", ""],
h1.cmd(f"ip route add dev wg{h1h4Tunnel}")
h5.cmd("ip route add via")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment