I just run pfsense in a virtualbox on the dual-nic box - in addition to standard router/firewall functions, I can play with enhanced security functions with much ease. Other solutions I have tried include free Sophos UTM-9 software appliance, zeroshell, m0n0wall, endian and family. Manually reimplementing all the functions provided by FOSS router/firewalls would be interesting and exhausting.
--- Supratim Sanyal, W1XMT 39.19151 N, 77.23432 W
On Sep 19, 2021, at 2:58 PM, Charlie Turner <chturne@gmail.com> wrote:
Hi, My goal is to have a virtual networking infrastructure, with one dual-NIC machine acting as a gateway. One of its NICs is connected to the private LAN, and provides a DHCP service, the other NIC is connected to the "upstream", and provides Internet service.
I start by creating a bridge to connect the private NIC of the gateway, to the virtual clients that will join the network later on,
┌──── │ ip link add name br0 type bridge │ ip addr add 10.42.0.1/24 dev br0 # this is the network ID of the =private= interface, inside the host │ ip link set br0 up └────
To experiment with what works, I did the following
┌──── │ IFACE=br0 │ dnsmasq --dhcp-match=set:efi-x86_64,option:client-arch,7 --dhcp-boot=tag:efi-x86_64,syslinux.efi --dhcp-boot=lpxelinux.0 \ │ --dhcp-range=10.42.0.10,10.42.0.100 --dhcp-script=/bin/echo \ │ --enable-tftp=$IFACE \ │ --tftp-root=/mnt/tmp/boots/tftp \ │ --log-queries=extra --conf-file=/dev/null --interface=$IFACE └────
And then spin up a test machine, connected to the `br0'. It uses the interface `tap15', which is created like so,
┌──── │ ip tuntap add mode tap tap15 │ ip link set tap15 up │ ip link set tap15 master br0 └────
┌──── │ qemu-system-x86_64 \ │ -machine pc-q35-6.0,accel=kvm \ │ -m 1024 -smp 2,sockets=2,cores=1,threads=1 \ │ -hda dut_disk0.qcow2 \ │ -chardev file,id=logfile,path=dut-log-525400112200-193528-19092021.log \ │ -chardev socket,id=foo,path=/run/salad_socks/machine0.socket,server=on,wait=off,logfile=dut-log-525400112200-193528-19092021.log \ │ -device pci-serial,chardev=foo \ │ -netdev tap,id=net0,ifname=tap15,script=no,downscript=no \ │ -device virtio-net-pci,netdev=net0,bootindex=1,mac=52:54:00:11:22:00 \ │ -vga virtio └────
This works fine. Now, I'd like to go a step further and run the `dnsmasq' inside a VM, not on my host. It will be listening to the `private' interface I described above.
For the host-side of the private NIC interface, I create a tap device, like before,
┌──── │ ip tuntap add mode tap tap0 │ ip link set tap0 up │ ip link set tap0 master br0 └────
With this setup out of the way, I start the dual-NIC gateway machine,
┌──── │ qemu-system-x86_64 \ │ -hda $DISK_FILE \ │ -boot c \ │ -device virtio-net-pci,romfile=,netdev=net0 \ │ -device virtio-net-pci,romfile=,netdev=net1 \ │ `# Simulate the plugged in "upstream" cable with user-mode networking` \ │ -netdev user,id=net0,hostfwd=tcp::60022-:22,hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:8000,hostfwd=tcp::2375-:2375 \ │ `# And now the unplugged one with, with TAP networks` \ │ -netdev tap,id=net1,ifname=tap0,script=no,downscript=no \ # this is interface dnsmasq will listen on │ $BOOT_MODE \ │ -m 4G \ │ -display sdl \ │ -enable-kvm \ │ -serial stdio └────
This VM has a pre-configured "disk file", that will launch a dnsmasq server, listening on the net1 interface.
I try the above experiment again, this time the dnsmasq instance is listening from within a VM, not on the `br0' interface, but rather, on `tap0', which is plugged into the bridge,
┌──── │ qemu-system-x86_64 \ │ -machine pc-q35-6.0,accel=kvm \ │ -m 1024 -smp 2,sockets=2,cores=1,threads=1 \ │ -hda dut_disk0.qcow2 \ │ -chardev file,id=logfile,path=dut-log-525400112200-193528-19092021.log \ │ -chardev socket,id=foo,path=/run/salad_socks/machine0.socket,server=on,wait=off,logfile=dut-log-525400112200-193528-19092021.log \ │ -device pci-serial,chardev=foo \ │ -netdev tap,id=net0,ifname=tap15,script=no,downscript=no \ │ -device virtio-net-pci,netdev=net0,bootindex=1,mac=52:54:00:11:22:00 \ │ -vga virtio └────
When this machine boots, by monitoring the bridge, I can see the BOOTP requests on the `br0' interface using `tcpdump',
┌──── │ # tcpdump -i br0 -nN │ tcpdump: verbose output suppressed, use -v[v]... for full protocol decode │ listening on br0, link-type EN10MB (Ethernet), snapshot length 262144 bytes │ 18:47:53.882429 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:11:22:01, length 397 │ 18:47:54.924377 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:11:22:01, length 397 │ 18:47:56.956663 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:11:22:01, length 397 │ 18:48:01.021086 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:11:22:01, length 397 └────
But, nothing responds to it, and so the boot fails. I was expecting that the `dnsmasq' listening on `tap0', which is also connected to the `br0', would see these requests, and send a BOOTP response.
During research, I found that "When you junction interfaces into a bridge, you no longer use the individual interfaces but the entire bridge as an interface. You probably need to change your DHCP server to listen on br0 instead of tap0." <https://superuser.com/a/419612/291744>
Unfortunately, I can't ask QEMU to assign one of the interfaces to be `br0', rather than `tap0'. Changing the gateway invocation to,
┌──── │ qemu-system-x86_64 \ │ -hda $DISK_FILE \ │ -boot c \ │ -device virtio-net-pci,romfile=,netdev=net0 \ │ -device virtio-net-pci,romfile=,netdev=net1 \ │ `# Simulate the plugged in "upstream" cable with user-mode networking` \ │ -netdev user,id=net0,hostfwd=tcp::60022-:22,hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:8000,hostfwd=tcp::2375-:2375 \ │ `# And now the unplugged one with, with TAP networks` \ │ -netdev tap,id=net1,ifname=br0,script=no,downscript=no \ │ $BOOT_MODE \ │ -m 4G \ │ -display sdl \ │ -enable-kvm \ │ -serial stdio └────
(Note, `net1''s `ifname' is now specified as `br0', not `tap0')
This unfortunately fails with
┌──── │ qemu-system-x86_64: -netdev tap,id=net1,ifname=br0,script=no,downscript=no: could not configure /dev/net/tun (br0): Invalid argument └────
And I'm stuck at this point, how can I have the gateway's private NIC respond to DHCP requests on the bridge?
Thanks for reading!
B.R. Charles.
|