How to route all traffic from one vm through other vm on OS X

0

1

Challenge: to get one Debian VM (Virtualbox) to route all its traffic through another Debian VM (Paralles), both hosted under OS X 10.11.5. I've tried for days, I hope you can help here.

Schema:

vm1 (Virtualbox) ---> ( OS X ) --> vm2 (Parallels) --> internet

This is what I have:

VM1 (the “client”):

  • Interface eth1 setup with Host-only Network under Virtualbox, gets ip address 192.168.56.103 with netmask 255.255.255.0

VM2 (the “router”):

  • Wifi card attached directly to the VM, interface wlan0 with ip 10.251.26.168, connected to internet. wlan0 will be my outgoing interface.

  • Interface eth0 setup as host-only under Parallels, gets ip address 10.37.129.6 with netmask 255.255.255.0.

On the host:

  • VM1 is connected to interface vboxnet0 with ip 192.168.56.1 VM2 is connected to interface vnic1 with ip 10.37.129.2

With this setup pinging the host from each VM and viceversa works perfectly well (on their respective networks).

What I’ve done so far:

Under the host OS X systems I enable ip forwarding and bridge both virtual interfaces together:

bash-3.2# sysctl -w net.inet.ip.forwarding=1
net.inet.ip.forwarding: 1 -> 1
bash-3.2# ifconfig bridge0 create
bash-3.2# ifconfig vnic1 down
bash-3.2# ifconfig vboxnet0 down
bash-3.2# ifconfig bridge0 up addm vnic1 addm vboxnet0
bash-3.2# ifconfig vnic1 up
bash-3.2# ifconfig vboxnet0 up
bash-3.2# ifconfig bridge0
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether ba:e8:56:14:5f:00 
    Configuration:
        id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
        maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
        root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
        ipfilter disabled flags 0x2
    member: vnic1 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 14 priority 0 path cost 0
    member: vboxnet0 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 12 priority 0 path cost 0
    Address cache:
    media: autoselect
    status: active
bash-3.2# ifconfig vnic1
vnic1: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether 00:1c:42:00:00:09 
    inet 10.37.129.2 netmask 0xffffff00 broadcast 10.37.129.255
    media: autoselect
    status: active
bash-3.2# ifconfig vboxnet0
vboxnet0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    ether 0a:00:27:00:00:00 
    inet 192.168.56.1 netmask 0xffffff00 broadcast 192.168.56.255

On VM1 (“client”) I add default gateway:

root@vm1:~# ip route del 0/0
root@vm1:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
  192.168.56.0    0.0.0.0         255.255.255.0   U     100    0        0 eth1
root@vm1:~# route add default gw 192.168.56.1
root@vm1:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
  0.0.0.0         192.168.56.1    0.0.0.0         UG    0      0        0 eth1
  192.168.56.0    0.0.0.0         255.255.255.0   U     100    0        0 eth1

On VM2 (“router”) I enable ip forwarding and setup nat:

root@vm2:~# sysctl -w net.ipv4.ip_forward = 1
root@vm2:~# iptables -t nat -A POSTROUTING --out-interface wlan0 -j MASQUERADE  
root@vm2:~# iptables -A FORWARD --in-interface eth0 -j ACCEPT

Now, after all this I can ping from VM1 to 192.168.56.1 and 10.37.129.2 (host-side IPs for the virtual network adapters vboxnet0 and vnic1 respectively) but I can’t ping 10.37.129.6. I have also failed so far to access the internet from VM1 through VM2 (from VM1 ping 8.8.8.8):

root@vm1:~# ping -c 1 192.168.56.1
PING 192.168.56.1 (192.168.56.1) 56(84) bytes of data.
64 bytes from 192.168.56.1: icmp_seq=1 ttl=64 time=1.54 ms

--- 192.168.56.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.543/1.543/1.543/0.000 ms

root@vm1:~# ping -c 1 10.37.129.2

PING 10.37.129.2 (10.37.129.2) 56(84) bytes of data.
64 bytes from 10.37.129.2: icmp_seq=1 ttl=64 time=0.208 ms

--- 10.37.129.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.208/0.208/0.208/0.000 ms

root@vm1:~# ping -c 1 10.37.129.6
PING 10.37.129.6 (10.37.129.6) 56(84) bytes of data.

--- 10.37.129.6 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

root@vm1:~# ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

So I can't get VM1 to route all its traffic through VM2... what am I missing??

In case it helps troubleshooting, I launched wireshark on vm2 ("the router") listening to all interfaces. When I ping 10.37.129.6 from vm1, I see the ARP requests "who was 10.37.129.6 Tell 10.37.129.2", the corresponding ARP reply and the subsequent ICMP originating from vm1's ip (192.168.56.101) so the OS X bridge must be working. But I don't seem to get the ping response back to vm1 neither I see it on wireshark. And when I ping 8.8.8.8 from vm1 I don't see anything in vm2's wireshark session.

Thanks a lot for your help.

Keyser Soze

Posted 2016-07-13T17:16:32.393

Reputation: 1

Try virtualbox forums, but I think what you're trying to do may be way too technical. These virtualboxes have a lot of low level limitations which will also depend on the peculiarities of the specific host and guest OS-s you're using. So if it doesn't work with Mac-Debian, it may work with Mac-Ubuntu, or Windows-Debian, etc. – None – 2016-07-14T12:16:36.870

Thanks for your comments Florian. My feeling is this should be os-independent, at the end of the day we are talking linux (debian) & freebsd (osx) which are excellent networking os. It's true the hypervisor technologies differ greatly but I'm constrained to to use both Virtualbox and Paralles. Anyway, I'll keep fiddling with the above setup and I'll also try NAT (instead of bridge) on the host side. – Keyser Soze – 2016-07-15T07:35:39.953

By the way, I just found this interesting (although old) post: http://www.tolaris.com/2012/05/16/using-host-networking-and-nat-with-virtualbox-v2-0/. I'll try this and report progress.

– Keyser Soze – 2016-07-15T08:53:55.467

Answers

0

I finally got it working :-)

My working solution involves:

  1. Parallels VM (the "router"): "host only" network, with the ip range defined by default by Parallels (I could change that in Parallels - Preferences - Network - Host Only). Setup nat with iptables with wlan0 (wifi) as the outbound interface.

  2. Virtualbox VM (the "client"): "bridge" network, using Parallel's virtual adapter vnic1 created for its "host only" network. I had to disable Virtualbox's dhcpserver so that the guest didn't get an undesired ip. I gave it an ip in the same range as the Parallel's vm. Set up default route to the "router".

Note: I could get Virtualbox to use Parallel's vnic1 in bridge mode. However, all my tests failed when trying to get Parallels to use Virtualbox's vboxnet0 interface or even OS X's bridge0 when I tried that. It seems Parallels only bridges physical adapters, not virtual.

And that's about it. Now, the details:

Parallel's VM - "the router" Using Parallel's default dhcpserver (no config needed unless you want to change the default ip/netmask info). We need to enable packet forwarding and setup nat with iptables.

root@router:~# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.37.129.7  netmask 255.255.192.0  broadcast 10.37.129.255                      
        ether 08:00:27:2a:20:8e  txqueuelen 1000  (Ethernet)
        RX packets 35  bytes 10016 (9.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 873  bytes 62313 (60.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
root@router:~# route -n
        Kernel IP routing table
        Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
        0.0.0.0         10.37.129.2    0.0.0.0         UG    100    0        0 eth0
        10.37.129.0     0.0.0.0        255.255.192.0   U     100    0        0 eth0
root@router:~# sysctl -w net.ipv4.ip_forward = 1
root@router:~# iptables -t nat -A POSTROUTING --out-interface wlan0 -j MASQUERADE  
root@router:~# iptables -A FORWARD --in-interface eth0 -j ACCEPT

Virtualbox vm ("the client"): Adapter 1 as bridge with vnic1 (note: you might need to run Parallel's vm first so that vnic1is created). I need to add the router's ip (10.37.129.7) as the default gateway:

root@client:/home/user# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:a2:10:ba  
          inet addr:10.37.129.9  Bcast:10.37.129.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1292 (1.2 KiB)  TX bytes:684 (684.0 B)
          Interrupt:19 Base address:0xd000 
root@host:/home/user# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.37.129.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
root@client:/home/user# route add default gw 10.37.129.7
root@client:/home/user# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.37.129.7     0.0.0.0         UG    0      0        0 eth0
10.37.129.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

And that's it. This got it working for me. Now I can access the internet from the client (Virtualbox) through a wireless card attached directly to the router (Parallels) without the host's (OS X) intervention.

Keyser Soze

Posted 2016-07-13T17:16:32.393

Reputation: 1