You are not logged in.
I'm attempting to implement NAT between my physical interface and QEMU taps (although for now only tap0). I've gotten to a point where I think it should work, but it doesn't, and I'm not sure where the error in my thinking is.
I've attempted to give the VM eth0 interface IP 10.0.0.2 and the host tap0 interface 10.0.0.1. Here are the commands I've used so far on the host:
# Create tap0
ip tuntap add tap0 mode tap
# Add 10.0.0.1 address to tap0
ip a add 10.0.0.1/24 dev tap0
# Bring up tap0
ip l set tap0 up
# Enable NAT according to https://wiki.archlinux.org/title/Internet_sharing#Enable_NAT
sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i tap0 -o eno1 -j ACCEPT
Then, on the guest (spawned with -device e1000,mac=someaddress -net tap,ifname=tap0,script=no,downscript=no) I've executed this:
route add -host 10.0.0.1 dev eth0
route add default gw 10.0.0.1
ip a a 10.0.0.2/24 dev eth0
ip route get 10.0.0.1 results in 10.0.0.1 dev eth0 src 10.0.0.2 on the guest and local 10.0.0.1 dev lo table local src 10.0.0.1 uid 0 on the host.
ip route get 10.0.0.2 results in local 10.0.0.2 dev lo src 10.0.0.2 on the guest and 10.0.0.2 dev tap0 src 10.0.0.1 uid 0 on the host.
On the host:
# iptables -nvL
Chain INPUT (policy ACCEPT 30080 packets, 38M bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- tap0 eno1 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 20228 packets, 2390K bytes)
pkts bytes target prot opt in out source destination
# iptables -nvL -t nat
Chain PREROUTING (policy ACCEPT 20 packets, 1119 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 20 packets, 1119 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 212 packets, 13712 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 212 packets, 13712 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * eno1 0.0.0.0/0 0.0.0.0/0
which I interpret as the rules not being hit at all.
Pinging the other address from either side results in a Destination Host Unreachable error.
Pinging 10.0.0.2 on the host makes tshark -i tap0 report
tap0macaddress → Broadcast ARP 42 Who has 10.0.0.2? Tell 10.0.0.1
What I don't understand, and don't know how to further debug, is why the two interfaces cannot reach each other.
Last edited by origrio (2022-04-10 20:52:36)
Offline
Sorry - this setup makes no sense to me and will not work.
Networking with virtual machines is usually divided into four main types:
- Bridged: The VMs are visible in the network of the host (behaving like additional boxes on the network)
- NAT: The VMs can talk to each other and the host inside their own network - the host acts as a NAT router for external access.
- Host-Only: The VMs can only talk to each other and the host inside their own network.
- Internal/Isolated: The VMs can only talk to each other inside their own network.
Because you gave your VM an address in the same network as the host - what type do you want to achieve?
Offline
I want to put the VMs behind a NAT and let them reach the WAN, just like a regular, physical router would. What I tried above was to get the VM to reach the gateway on the host (10.0.0.1), not actually connect to the host itself (although in this case, that is probably the same thing), just like I can ping a physical router from a device on its LAN.
As a side note, my host's physical interface has an address in 192.168.1.0/24, not 10.0.0.0/24. The VM is only in the same space when it comes to the virtual network.
Offline
Ah - my mistake. I completely misinterpreted your setup.
Offline
(spawned with -device e1000,mac=someaddress -net tap,ifname=tap0,script=no,downscript=no)
Are you sure this is correct? According to the Wiki it should be "-netdev tap...".
Offline
-net is apparently a legacy option. Nevertheless, -device e1000,mac=someaddress -net tap,id=tap0,script=no,downscript=no gives exactly the same behavior.
Offline
Nevermind. The part I assume you referenced implies that the two parameters need to have matching IDs (netdev=network0 for -device and id=network0 for -netdev in the article). Matching these (in my case -device e1000,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no) makes the ping go through.
Thanks for your help!
Offline