A Docker container that creates a virtual network gateway between GNS3 and your real network. It lets GNS3 virtual machines access the internet through your WiFi (or any other network interface) without needing a second physical network adapter.
GNS3 is a network simulator used for learning and testing network configurations. When you run virtual routers or PCs inside GNS3, they live in an isolated bubble - they can't reach the internet or your real network by default.
The normal solution is to connect GNS3's "Cloud" node to a real network adapter. But if your machine only has WiFi, this doesn't work out of the box - Linux WiFi drivers have a restriction that prevents them from being shared this way.
This container works around that restriction.
Think of it like a traffic relay station sitting between GNS3 and your WiFi:
-
Creates a fake network cable (
tap0) - a virtual Ethernet adapter that GNS3 can plug into, as if it were a real network port. -
Acts as a router - anything that arrives on the fake cable gets forwarded to your real WiFi (
wlan0), and replies come back the same way. -
Hides the GNS3 machines behind one address (NAT/masquerade) - to your router, all traffic looks like it's coming from your Linux machine, not from the individual GNS3 VMs.
-
Hands out IP addresses (DHCP via
dnsmasq) - GNS3 machines connected to the Cloud node automatically get an IP address in the192.168.222.xrange, just like a real DHCP server would. -
Handles IPv6 too (radvd) - sets
fd10:10:10::/64IPv6 prefix by default and advertises it inside GNS3, so VMs can also get working IPv6 addresses automatically. -
Cleans up after itself - when the container stops, it removes the virtual cable and all the routing rules it added, leaving your system exactly as it was.
- Docker and Docker Compose
- A Linux host (this uses Linux-specific kernel features)
- GNS3 installed and running on the same machine
- A working network connection (WiFi or wired -
wlan0by default)
docker compose up -dThen in GNS3, add a Cloud node to your topology and configure it to use the tap0 interface.
Edit these variables at the top of entrypoint.sh inside the Dockerfile:
| Variable | Default | Description |
|---|---|---|
WLAN_IF |
wlan0 |
Your real network interface |
TAP_IF |
tap0 |
The virtual interface GNS3 connects to |
SUBNET |
192.168.222 |
The IP range handed out to GNS3 machines |
IPV6PREFIX |
fd10:10:10 |
The IPv6 prefix advertised to GNS3 machines |
DNS |
8.8.8.8 |
DNS server advertised to GNS3 machines |
DNS6 |
2001:4860:4860::8888 |
IPv6 DNS server (Google) |
After changing any of these, rebuild the image:
docker compose up -d --build- dnsmasq - a lightweight DHCP server that hands out IP addresses to GNS3 machines
- radvd - a router advertisement daemon that handles IPv6 address assignment
- iptables / ip6tables - Linux firewall rules that forward traffic and apply NAT
In GNS3:
- Drag a Cloud node into your topology
- Right-click it and go to Configure
- Under TAP interfaces, add
tap0 - Connect your virtual router or PC to the Cloud node
The connected device should automatically receive an IP in the 192.168.222.x range and be able to reach the internet.
- The container uses
network_mode: hostandprivileged: truebecause it needs direct access to your host's network interfaces and kernel features (tun/tap, iptables). This is intentional and required. - If your WiFi interface is not
wlan0(check withip link), updateWLAN_IFaccordingly before building. - The container must be running before you start your GNS3 topology, otherwise
tap0won't exist yet.
If you want to attach a standalone QEMU VM directly to tap0 without GNS3, you can reuse the same interface the container creates:
sudo qemu-system-x86_64 \
-m 512 \
-drive file=your-disk.qcow2,if=virtio \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0 \
-nographicThe VM will get a DHCP lease from dnsmasq in the 192.168.222.x range and reach the internet through NAT on wlan0, same as any GNS3 node.
Note:
script=no,downscript=notells QEMU not to run/etc/qemu-ifupand/etc/qemu-ifdown- the container already owns thetap0lifecycle.
- Install QEMU
sudo pacman -S qemu-full edk2-aarch64- Download installer
mkdir -p ~/armvm
cd ~/armvm
wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.5.0-arm64-netinst.iso- Create disk
qemu-img create -f qcow2 debian-arm64.qcow2 30G- Run
gns3-wlan-bridgecontainer
docker compose up -d- Run installer in QEMU
qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-m 2048 \
-smp 4 \
-bios /usr/share/edk2/aarch64/QEMU_EFI.fd \
-drive file=debian-arm64.qcow2,if=virtio,format=qcow2 \
-drive file=debian-13.5.0-arm64-netinst.iso,media=cdrom,readonly=on,if=virtio \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0 \
-boot order=d \
-nographic- Boot installed VM
qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-m 2048 \
-smp 4 \
-bios /usr/share/edk2/aarch64/QEMU_EFI.fd \
-drive file=debian-arm64.qcow2,if=virtio,format=qcow2 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0 \
-boot order=d \
-nographic- Inside VM
su -
apt update
apt install sudo
usermod -aG sudo your_username
newgrp sudo- Install QEMU
sudo pacman -S qemu-system-arm- Download kernel
mkdir -p ~/armvm
cd ~/armvm
wget https://archive.debian.org/debian/dists/buster/main/installer-armhf/current/images/netboot/vmlinuz
wget https://archive.debian.org/debian/dists/buster/main/installer-armhf/current/images/netboot/initrd.gz- Create disk
qemu-img create -f qcow2 buster-armhf.qcow2 16G- Run
gns3-wlan-bridgecontainer
docker compose up -d- Run installer in QEMU
qemu-system-arm \
-M virt \
-cpu cortex-a15 \
-m 1024 \
-smp 2 \
-kernel vmlinuz \
-initrd initrd.gz \
-append "console=ttyAMA0" \
-drive file=buster-armhf.qcow2,if=none,id=hd0,format=qcow2 \
-device virtio-blk-device,drive=hd0 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-device,netdev=net0 \
-nographicDuring install:
- Set
archive.debian.orgas repository mirror - Choose
Continue without bootloaderafter grub install failure
- Copy files to VM filesystem
sudo modprobe nbd max_part=8
sudo qemu-nbd --connect=/dev/nbd0 buster-armhf.qcow2
ls /dev/nbd0*
sudo fsck -y /dev/nbd0p1
sudo mkdir -p /mnt/arm32
sudo mount /dev/nbd0p1 /mnt/arm32
cp /mnt/arm32/vmlinuz-4.19.0-21-armmp-lpae ./vmlinuz-boot
cp /mnt/arm32/initrd.img-4.19.0-21-armmp-lpae ./initrd-boot
sudo umount /mnt/arm32
sudo qemu-nbd --disconnect /dev/nbd0
- Boot installed VM
qemu-system-arm \
-M virt \
-cpu cortex-a15 \
-m 1024M \
-smp 2 \
-kernel ./vmlinuz-boot \
-initrd ./initrd-boot \
-append "root=/dev/vda2 console=ttyAMA0 rootwait" \
-drive file=buster-armhf.qcow2,if=none,id=hd0,format=qcow2 \
-device virtio-blk-device,drive=hd0 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-device,netdev=net0 \
-nographic- Inside VM
su -
apt update
apt install sudo
usermod -aG sudo your_username
newgrp sudo