Build the lab yourself
Two VyOS VMs, an "internet" router and a host at each site. Put ./vyos (from the Packets That Never Come Back lesson's get-vyos.sh) next to these files, run docker compose up -d --build and ./hosts-setup.sh, then on each router apply the base configuration, generate a key pair, and configure wg0 with your own keys.
# Needs ./vyos (from the tcpdump-and-vyos lesson's get-vyos.sh). Then: docker compose up -d --build && ./hosts-setup.sh
name: vyos-wireguard-lab
x-linux: &linux
build:
dockerfile_inline: |
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends iproute2 iputils-ping traceroute tcpdump
CMD ["sleep", "infinity"]
privileged: true
x-vyos: &vyos
build:
context: .
dockerfile_inline: |
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends qemu-system-x86 iproute2 socat
COPY start-vyos.sh /usr/local/bin/start-vyos.sh
CMD ["/usr/local/bin/start-vyos.sh"]
cap_add: [NET_ADMIN]
devices: ["/dev/net/tun:/dev/net/tun"]
volumes: ["./vyos:/vyos:ro"]
services:
r1:
<<: *vyos
environment: { VYOS_MEM: "1536", VYOS_SMP: "1", VM_ID: "01" }
networks: { wan-a: { interface_name: eth0 }, lan-a: { interface_name: eth1 } }
r2:
<<: *vyos
environment: { VYOS_MEM: "1536", VYOS_SMP: "1", VM_ID: "02" }
networks: { wan-b: { interface_name: eth0 }, lan-b: { interface_name: eth1 } }
inet:
<<: *linux
networks: { wan-a: { interface_name: eth0 }, wan-b: { interface_name: eth1 } }
hosta:
<<: *linux
networks: { lan-a: { interface_name: eth0 } }
hostb:
<<: *linux
networks: { lan-b: { interface_name: eth0 } }
networks:
wan-a: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:70::/64" }] } }
wan-b: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:71::/64" }] } }
lan-a: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:72::/64" }] } }
lan-b: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:73::/64" }] } }- Lines 21–28: Two sites' routers.
- Lines 29–37: The internet in between, and a host per site.
#!/bin/sh
# The "internet" router knows only the two WAN links; each host sits on its site's LAN.
cd "$(dirname "$0")"
x() { docker compose exec -T "$@"; }
for c in inet hosta hostb; do x $c sh -c 'sysctl -qw net.ipv6.conf.all.disable_ipv6=1'; done
x inet sh -c 'sysctl -qw net.ipv4.ip_forward=1; ip addr add 203.0.113.1/30 dev eth0; ip addr add 198.51.100.1/30 dev eth1'
x hosta sh -c 'ip addr add 10.1.0.10/24 dev eth0; ip route replace default via 10.1.0.1'
x hostb sh -c 'ip addr add 10.2.0.10/24 dev eth0; ip route replace default via 10.2.0.1'
echo hosts ready- Line 6: The internet: only the two WAN links, no route to private space.
- Lines 7–8: A host at each site.
Where next
- Setting up VyOS with NATPrerequisite · Beginner · 45 min
A VyOS router with a NAT interface for a private LAN and a public interface for a routed public subnet: plain routing, source NAT, port forwarding and the forward firewall that NAT isn't. Every output comes from a real VyOS lab.
- Packets That Never Come BackAlso covers MTU · Intermediate · 75 min
Advanced packet capture with tcpdump, and how to find where packets die on a VyOS network: missing NAT and return routes, asymmetric routing through a stateful firewall, and MTU black holes, all diagnosed on a real VyOS router.
- Office gateway: DHCP, DNS and VRRP on VyOSAlso in Office & branch networks · Beginner · 40 min
Two VyOS routers serving one office LAN: VRRP for a gateway that survives a router failure, DHCP with split pools and a printer reservation, and DNS forwarding. Then a real failover, the DNS outage it exposed, and the fix.
- Zone-based firewall on VyOSAlso in Office & branch networks · Intermediate · 35 min
Rebuild the NAT lesson's router with a zone-based firewall: WAN, LAN, a DMZ and the router itself, with one ruleset per direction. Includes the missing-return-traffic mistake, post-NAT matching, and a full test matrix.