1

I am trying to set up an OpenVPN connection with a Layer2 ethernet bridge to bridge two LANs. ARP responses do not seem to being generated correctly...

Please note I want to create a full Layer2 bridge, so that all traffic, including broadcast packets, can be relayed. I will use ebtables and other methods to block DHCP, etc.

Netork Topology

We have two LANs (we'll call them LAN1 and LAN2) at different physical locations. Each LAN is a standard residential network on a consumer-grade internet connection.

------------     ---------     ----------    ------------------------
* Internet * --> * Modem * --> * Router * -> * Switches and Clients *
------------     ---------     ----------    ------------------------

On each network, we've built a Linux server, designed to act as a backup fileserver and VPN bridge. The servers, called Thing1 (on LAN1) and Thing2 (on LAN2) are client devices.

LAN1 uses 192.168.110.0/24

  • Router1 (ASUS RT-AC68U) as DHCP server and internet gateway at 192.168.110.254
  • Various switches and client PCs, phones, TVs, etc.
  • Thing1 (OpenVPN server) connected at 192.168.110.250

LAN2 uses 192.168.111.0/24

  • Router2 (ASUS RT-AC66U) as DHCP server and internet gateway at 192.168.111.254
  • Various switches and client PCs, phones, TVs, etc.
  • Thing2 (OpenVPN server) connected at 192.168.111.250

Configuration

Each of the OpenVPN machines (Thing1 and Thing2) has OpenVPN installed and running. The connection has been created successfully.

On each server, we create our tap and bridge using a bridge-start script. I've trimmed it here...

bridge-start

echo 1 > /proc/sys/net/ipv4/ip_forward
br="br0"
tap="tap0"
eth="enp2s0"

#obtain the Hardware Mac address of the physical ethernet interface
eth_hw_mac=`ifconfig $eth | grep 'HWaddr' | cut -d' ' -f9`

for t in $tap; do
    ip tuntap add dev $t mode tap
done

brctl addbr $br
brctl addif $br $eth

for t in $tap; do
    brctl addif $br $t
done

for t in $tap; do
    ifconfig $t 0.0.0.0 promisc up
done

ifconfig $eth 0.0.0.0 promisc up
ifconfig $br hw ether $eth_hw_mac

dhclient $br

# Load ebtables rules to block DHCP traffic across the bridge.
ebtables -A INPUT -i tap0 -p ipv4 --ip-proto udp --ip-dport 67:68 -j DROP
ebtables -A INPUT -i tap0 -p ipv4 --ip-proto udp --ip-sport 67:68 -j DROP
ebtables -A FORWARD -o tap0 -p ipv4 --ip-proto udp --ip-dport 67:68 -j DROP
ebtables -A FORWARD -o tap0 -p ipv4 --ip-proto udp --ip-sport 67:68 -j DROP

The only difference is that on Thing2, the tap interface is named tap1, rather than tap0.

Relevant ifconfig on Thing1 (192.168.110.250)

br0       Link encap:Ethernet  HWaddr b8:ae:ed:fc:4a:4f
          inet addr:192.168.110.250  Bcast:192.168.110.255  Mask:255.255.255.0
          inet6 addr: fe80::baae:edff:fefc:4a4f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:560719 errors:0 dropped:0 overruns:0 frame:0
          TX packets:271873 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:120753983 (120.7 MB)  TX bytes:72273308 (72.2 MB)

enp2s0    Link encap:Ethernet  HWaddr b8:ae:ed:fc:4a:4f
          inet6 addr: fe80::baae:edff:fefc:4a4f/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:525244 errors:0 dropped:68 overruns:0 frame:0
          TX packets:548223 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:142488031 (142.4 MB)  TX bytes:129824161 (129.8 MB)

tap0      Link encap:Ethernet  HWaddr c6:5d:10:17:5c:b9
          inet6 addr: fe80::c45d:10ff:fe17:5cb9/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:240521 errors:0 dropped:0 overruns:0 frame:0
          TX packets:238686 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:49398722 (49.3 MB)  TX bytes:47097224 (47.0 MB)

Relevant ifconfig on Thing2 (192.168.111.250)

br0       Link encap:Ethernet  HWaddr f4:4d:30:08:f1:e5
          inet addr:192.168.111.250  Bcast:192.168.111.255  Mask:255.255.255.0
          inet6 addr: fe80::f64d:30ff:fe08:f1e5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1049729 errors:0 dropped:0 overruns:0 frame:0
          TX packets:757240 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5142387727 (5.1 GB)  TX bytes:302576425 (302.5 MB)

enp2s0    Link encap:Ethernet  HWaddr f4:4d:30:08:f1:e5
          inet6 addr: fe80::f64d:30ff:fe08:f1e5/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:7254547 errors:0 dropped:389 overruns:0 frame:0
          TX packets:3661240 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6092825279 (6.0 GB)  TX bytes:1214754910 (1.2 GB)

tap1      Link encap:Ethernet  HWaddr 46:6f:ee:61:de:b2
          inet addr:192.168.110.1  Bcast:192.168.110.255  Mask:255.255.255.0
          inet6 addr: fe80::446f:eeff:fe61:deb2/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:233278 errors:0 dropped:0 overruns:0 frame:0
          TX packets:294344 errors:0 dropped:46711 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:46740438 (46.7 MB)  TX bytes:129353655 (129.3 MB)

Relevant lines from OpenVPN server.conf on Thing1 (192.168.110.250)

port 1194
proto udp
dev tap0
topology subnet
ifconfig-pool-persist ipp.txt
server-bridge 192.168.110.250 255.255.255.0 192.168.110.1 192.168.110.10
client-to-client
keepalive 10 120
persist-key
persist-tun

Route table on Thing1

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         router.asus.com 0.0.0.0         UG    0      0        0 br0
192.168.110.0   *               255.255.255.0   U     0      0        0 br0
192.168.111.0   192.168.111.250 255.255.255.0   UG    0      0        0 tap0
192.168.111.250 *               255.255.255.255 UH    0      0        0 tap0

Route table on Thing2

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         router.asus.com 0.0.0.0         UG    0      0        0 br0
192.168.110.0   192.168.110.250 255.255.255.0   UG    0      0        0 tap1
192.168.110.250 *               255.255.255.255 UH    0      0        0 tap1
192.168.111.0   *               255.255.255.0   U     0      0        0 br0

Problem

I attempt to ping .111.250 from .110.250, but the ARP resolution never happens...

ping 192.168.111.250

PING 192.168.111.250 (192.168.111.250) 56(84) bytes of data.
From 192.168.110.250 icmp_seq=1 Destination Host Unreachable
From 192.168.110.250 icmp_seq=2 Destination Host Unreachable
From 192.168.110.250 icmp_seq=3 Destination Host Unreachable

Doing a tcpdump on .110.250's tap while the ping is happening...

tcpdump -i tap0 -en | grep "ARP"

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:43:08.283935 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:43:08.300129 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:43:08.300181 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:43:09.300441 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:43:09.300493 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:43:10.302120 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:43:10.302170 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:43:11.300760 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:43:11.300810 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:43:12.300762 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:43:12.300815 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28

This sequence repeats for each ping attempt.

Meanwhile, on .111.250's tap1 (which has IP 192.168.110.1)...

tcpdump -i tap1 -en | grep "ARP"

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
15:49:47.315913 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:49:47.813360 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:49:47.830572 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:49:48.314726 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:49:48.812622 46:6f:ee:61:de:b2 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.110.250 tell 192.168.110.1, length 28
15:49:48.832273 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28

If we look at .111.250's br0 (which actually has 192.168.111.250)...

tcpdump -i br0 -en | grep "ARP"

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:53:49.969025 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:53:50.341753 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28
15:53:50.968877 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:53:51.341336 b8:ae:ed:fc:4a:4f > 46:6f:ee:61:de:b2, ethertype ARP (0x0806), length 42: Reply 192.168.110.250 is-at b8:ae:ed:fc:4a:4f, length 28

But at the physical ethernet adapter...

tcpdump -i enp2s0 -en | grep "ARP"

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp2s0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:56:13.344685 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28
15:56:14.344167 c6:5d:10:17:5c:b9 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.111.250 tell 192.168.110.250, length 28

As far as I understand, Thing2's br0, which has address 192.168.111.250 should be sending a reply something like...

f4:4d:30:08:f1:e5 > c6:5d:10:17:5c:b9, ethertype ARP (0x0806), length 42: Reply 192.168.111.250 is-at f4:4d:30:08:f1:e5, length 28

I don't know that this will fix everything that's broken, or if I'm missing something very obvious. Feel free to make any suggestions which you think would move me in the right direction.

2

The problem is that you are trying to bridge two different IP subnets, which does not work. One IP subnet consists of a single broadcast domain, and now you are trying to set up two different IP subnets in a single broadcast domain (bridge over the VPN).

What happens during the ping is that your 192.168.111.250 sends ARP request to 192.168.110.250, which will not answer it because the request comes from an IP address outside of its subnet 192.168.110.0/24.

Another issue in your configuration is that you have defined an IP address both to your br0 device, which is the bridge device, and the tapX device, which is part of the bridge.

You should only assign an IP address to the bridge device.

You need to redesign your networking concept so that you use a single IP subnet over your bridge if you really want a full L2 networking solution.

2
  • In that case, would setting a /16 netmask on the bridges and taps alleviate the issue? – Jonathan Preston Sep 30 '16 at 2:20
  • Yes, that would make it a single broadcast domain, covering all IP addresses from 192.168.0.0 to 192.168.255.255. However, if the network would get this many devices in the end, it would not work reliably due to excessive broadcast traffic. You might want to use /23 or 255.255.254.0 netmask, which covers 192.168.111.0 to 192.168.112.255. – Tero Kilkanen Sep 30 '16 at 6:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.