0

I run OpenWrt in QEMU on Arch Linux 5.1.2 with virtual tap network. The tap0 device (placed in default br-lan subnet) cannot reach other (guest) subnets beside its own (e.g. by ping). This is suspicious and only happens in QEMU (deployed on real hardware the clients can access other subnets). Arch Linux as guest works properly though (in QEMU).

This might not be a bug in OpenWrt but a security feature but i cannot figure out what exactly. I mainly need it for LXC containers that have their own subnet each. For demonstration purpose (below) i will use a dummy ethernet adapter as "target" interface/subnet.

To see what i see i think the best approach will be to set up a minimal system that will be affected by the problem:

#!/bin/bash
if [[ ! $(cat /proc/net/dev |grep br0) ]]; then
    echo "Creating bridge"
     #Make sure nothing interferes with bridges
     #systemctl stop NetworkManager.service
     sysctl net.ipv4.ip_forward=1 >/dev/null 2>&1
     ip tuntap add tap0 mode tap user 1000
     ip tuntap add tap1 mode tap user 1000
     ip link set tap0 up
     ip link set tap1 up
     ip link add dev br0 type bridge
     ip link add dev br1 type bridge
     ip link set tap0 master br0
     ip link set tap1 master br1
     ip addr add 192.168.99.99/24 broadcast 192.168.99.255 dev br0
     ip addr add 192.168.10.1/24 broadcast 192.168.10.255 dev br1
     ip link set dev br0 up
     ip link set dev br1 up
     ip route add 192.168.2.0/24 dev br0
     iptables -t nat -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE
else
    echo "Removing bridge"
     ip tuntap del tap0 mode tap
     ip tuntap del tap1 mode tap
     ip link del dev br0 type bridge
     ip link del dev br1 type bridge
     sysctl net.ipv4.ip_forward=0 >/dev/null 2>&1
     iptables -t nat -D POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE
     #systemctl start NetworkManager.service
fi
  • Start QEMU:
#!/bin/bash
image=/tmp/openwrt-18.06.2-x86-64-combined-ext4.img
qemu="qemu-system-x86_64 \
-enable-kvm \
-cpu max \
-smp 4 \
-m 1G \
-boot c \
-drive id=disk0,if=none,format=raw,file=${image} \
-device virtio-blk-pci,drive=disk0 \
-device virtio-net,netdev=tap0 \
-device virtio-net,netdev=tap1 \
-netdev tap,id=tap0,ifname=tap0,script=no,downscript=no \
-netdev tap,id=tap1,ifname=tap1,script=no,downscript=no \
-serial mon:stdio \
-device qxl-vga \
-device piix3-usb-uhci \
-device usb-tablet \
"
${qemu}
echo -e "\n\033[1;35mBack at host!\033[0m\n"
  • Press (Enter) on the OpenWrt text (not gfx) console and copy&paste:
uci set network.lan.ipaddr='192.168.99.1'
uci set network.lan.broadcast='192.168.99.255'
uci set network.wan.proto='static'
uci set network.wan.ipaddr='192.168.10.100'
uci set network.wan.netmask='255.255.255.0'
uci set network.wan.broadcast='192.168.10.255'
uci set network.wan.gateway='192.168.10.1'
uci set network.wan.dns='208.67.222.222'
uci commit
service network restart
opkg update
opkg install ip-full nano less-wide grep xz strace tar wget kmod-dummy ca-certificates
opkg find coreutils* |awk {'print $1}'| xargs opkg install --force-overwrite
opkg find procps-ng* |awk {'print $1}'| xargs opkg install --force-overwrite
ip addr add 192.168.2.1/24 broadcast 192.168.2.255 dev dummy0
ip link set dev dummy0 up
  • Do some testing:
  • On guest side:
ping -I 192.168.99.1 192.168.99.99 (ok)
ping -I 192.168.99.1 192.168.2.1 (ok)
ping -I 192.168.2.1 192.168.99.1 (ok)
ping -I 192.168.2.1 192.168.99.99 (failed)
- Do these when pinging from host:
tcpdump -n -i any -v (who-has 192.168.2.1 tell 192.168.99.99)
tcpdump -n -i br-lan -v (who-has 192.168.2.1 tell 192.168.99.99)
tcpdump -n -i dummy0 -v (nothing...)
  • On host side:
ping -I 192.168.99.99 192.168.99.1 (ok)
ping -I 192.168.99.99 192.168.2.1 (failed)

The interface/subnet (192.168.2.1) is not reachable (from tap device) nor can it connect to the host bridge (192.168.99.99). I've checked/changed several values like 'arp_ignore' and 'rp_filter' but to no avail:

for i in /proc/sys/net/ipv4/conf/dummy0/*; do echo "${i} "$(cat ${i}); done

As mentioned above, this only happens in QEMU with OpenWrt and i have no clue why. I already flushed/cleaned all iptables/chains/rules, set all policies to ACCEPT, deleted all interfaces and created them manually (eth0, dummy0, bridges, eth1), checked routes and ARP entries and enabled promiscuous mode. Everything's looking good, but it doesn't work. Somehow OpenWrt doesn't like that virtual adapter. There are no 'martian' packets (if you enable that logging mode).

Any idea what's wrong here?

1 Answer 1

0

ip route add 192.168.2.0/24 dev br0

That's not correct. It has to be sent to a client behind the bridge not just the bridge (br0). That's somewhat confusing as the ARP packets are visible nevertheless on the whole subnet behind the bridge.

The correct command is:

ip route add 192.168.2.0/24 dev br0 via 192.168.99.1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .