Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TUN/TAP-based virtual bridge for GNS3 cloud and standalone QEMU connectivity over WLAN

Lab

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.

The problem it solves

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.

How it works

Think of it like a traffic relay station sitting between GNS3 and your WiFi:

  1. Creates a fake network cable (tap0) - a virtual Ethernet adapter that GNS3 can plug into, as if it were a real network port.

  2. 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.

  3. 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.

  4. Hands out IP addresses (DHCP via dnsmasq) - GNS3 machines connected to the Cloud node automatically get an IP address in the 192.168.222.x range, just like a real DHCP server would.

  5. Handles IPv6 too (radvd) - sets fd10:10:10::/64 IPv6 prefix by default and advertises it inside GNS3, so VMs can also get working IPv6 addresses automatically.

  6. 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.

Requirements

  • 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 - wlan0 by default)

Quick start

docker compose up -d

Then in GNS3, add a Cloud node to your topology and configure it to use the tap0 interface.

Configuration

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

What runs inside the container

  • 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

How the GNS3 side is set up

In GNS3:

  1. Drag a Cloud node into your topology
  2. Right-click it and go to Configure
  3. Under TAP interfaces, add tap0
  4. 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.

Notes

  • The container uses network_mode: host and privileged: true because 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 with ip link), update WLAN_IF accordingly before building.
  • The container must be running before you start your GNS3 topology, otherwise tap0 won't exist yet.

Usage with QEMU

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 \
  -nographic

The 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=no tells QEMU not to run /etc/qemu-ifup and /etc/qemu-ifdown - the container already owns the tap0 lifecycle.

Example setup with Debian ARM64

  • 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-bridge container
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

Example setup with Debian ARM32

  • 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-bridge container
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 \
  -nographic

During install:

  1. Set archive.debian.org as repository mirror
  2. Choose Continue without bootloader after 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

About

GNS3 connectivity with your real network over WLAN using a TUN/TAP-based virtual bridge

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages