0

I'm encountering a very odd situation with Hypriot OS.

Network configuration:

+--------+  +------+-----+------+  +---------------------+  +-------+
+ laptop +--+ eth0 + br0 + eth1 +--+ router @ 10.98.76.1 +--+ tower +
+--------+  +------+-----+------+  +---------------------+  +-------+
                         |
                         +-------+     +----------------------+
                         + wlan0 +-----+ router @ 192.168.0.1 +
                         +-------+     +----------------------+

I'm effectively trying to have a Raspberry Pi act as a man-in-the-middle between my laptop and my router. I have eth0 and eth1 attached to a bridge (br0) which gets created upon boot. eth0, eth1, and br0 are all within a network namespace called "foo". wlan0 is the main contender in the default namespace--docker is disabled for now, whereas it would typically create a docker0 bridge in the default namespace.

I am pushing eth0 and eth1 to a different network namespace in order to ensure wlan0 can run an ssh client, and only wlan0 is running said client--I don't want the hard-wired interfaces to use the ssh client under any conditions.

I am using 'device-init.yaml' (part of device-init) in order to kick off my network configuration script.

My network configuration script is as follows:

# Create a new namespace for the ethernet devices
ip netns add foo

# Create the bridge in the foo namespace and bring it up
ip netns exec foo ip link add name br0 type bridge
ip netns exec foo ip link set dev br0 up

# Bring down the ethernet devices
ip link set dev eth0 down
ip link set dev eth1 down

# Move the eth0/eth1 devices to the foo namespace
ip link set dev eth0 netns foo
ip link set dev eth1 netns foo

# Add the eth0/eth1 devices to the bridge
ip netns exec foo ip link set dev eth0 master br0
ip netns exec foo ip link set dev eth1 master br0

# Enable promiscuous mode
ip netns exec foo ip link set eth0 promisc on
ip netns exec foo ip link set eth1 promisc on

# Bring up the adapters within the foo namespace
ip netns exec foo ip link set dev lo up
ip netns exec foo ip link set dev eth0 up
ip netns exec foo ip link set dev eth1 up

# List the devices for posterity
netnsout=$(ip netns exec foo ip a)

echo "- Done running ip commands. Result: $netnsout"

Once the boot-up is complete I can ping my laptop from my tower, and my tower from my laptop without any issue. I can also obtain an IP address on my laptop without issue--the bridge is acting as it should, allowing traffic to flow through it.

Problem: I cannot run dhclient on eth1, eth0, or br0 and reach any entity within the network from the Raspberry Pi.

The code I run to obtain an IP address on eth1:

$ ip netns exec foo dhclient eth1

The results after running dhclient:

$ ip netns exec foo ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
    inet6 fe80::60fc:16ff:fe9a:2e26/64 scope link
       valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether b8:27:eb:9e:8d:63 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::ba27:ebff:fe9e:8d63/64 scope link
       valid_lft forever preferred_lft forever
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
    inet 10.98.76.11/24 brd 10.98.76.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::2e0:4cff:fe36:1efb/64 scope link
       valid_lft forever preferred_lft forever

eth1 is configured with the appropriate IP address.

If I then ping anything I receive "Destination Host Unreachable":

$ ip netns exec foo ping 10.98.76.1 (or .44 for laptop, .55 for tower)

Also, at this point I have no external access on wlan0. I can get to the wireless router and to other machines on the wireless network, but can't seem to poke outwards to the internet.

For reference, here are more details: The arp table:

$ ip netns exec foo arp
Address        HWtype  HWaddress      Flags Mask  Iface
10.98.76.1             (incomplete)               eth1

The routes:

$ ip netns exec foo ip route show all
default via 10.98.76.1 dev eth1
10.98.76.0/24 dev eth1  proto kernel  scope link  src 10.98.76.11

I then bring the bridge down:

$ ip netns exec foo ip link set dev br0 down
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether b8:27:eb:9e:8d:63 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::ba27:ebff:fe9e:8d63/64 scope link
       valid_lft forever preferred_lft forever
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether 00:e0:4c:36:1e:fb brd ff:ff:ff:ff:ff:ff
    inet 10.98.76.11/24 brd 10.98.76.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::2e0:4cff:fe36:1efb/64 scope link
       valid_lft forever preferred_lft forever

But I still receive "Destination Host Unreachable" when attempting to ping the router or tower. At this point, because the bridge is down I obviously can't do anything from my laptop.

If I then delete the bridge, I can ping everything on the network as expected:

$ ip netns exec foo ip link delete dev br0
PING 10.98.76.1 (10.98.76.1) 56(84) bytes of data.
64 bytes from 10.98.76.1: icmp_seq=1 ttl=127 time=1.71 ms
64 bytes from 10.98.76.1: icmp_seq=2 ttl=127 time=0.894 ms
64 bytes from 10.98.76.1: icmp_seq=3 ttl=127 time=0.873 ms

At this point I'm stumped. The exact same setup worked on Raspbian, but won't work on Hypriot. The following gitter does look almost identical to my situation, however I don't have the duplicated devices: https://gitter.im/hypriot/talk/archives/2016/06/02

Other things I've tried that yield no results: - Turning eth0 and eth1 promisc off - Turning br0 promisc on - Creating a custom resolv.conf in /etc/netns/foo/resolv.conf - arping (see below)

$ ip netns exec foo arping -A -I eth1 10.98.76.11
ARPING 10.98.76.11
Timeout
Timeout
Timeout
Timeout
Timeout

My main goal is to have eth1 on the Raspberry Pi take on the same IP and MAC as my laptop. While doing so, it should still pass traffic inwards to my laptop and respect any dhcp requests my laptop may have, etc. I am eventually going to attempt to setup a vpn tunnel between my Raspberry Pi and the tower, and would still require the packets to make it through the Raspberry Pi into my laptop, but this will come after I get the bridge/devices to work properly.

To re-iterate: this does work on Raspbian, which is what is really stumping me. Please let me know if more information is required such as running services (nothing other than the defaults for Hypriot, granted I did disable docker), etc.

Update

Based on the answer from wiebel I was able to fix the issue which isn't resolvable in the first place. I don't know how/why it works on Raspbian as it really shouldn't be working.

I'll post the work around/proper way of doing what I want below in the event that it may prove useful to a future overflower:

# Ensure the traffic we send to the laptop goes through the right device
ip netns exec foo route add 10.98.76.44 dev eth0

# Enable forwarding on both devices
ip netns exec foo sysctl net.ipv4.conf.eth0.forwarding=1
ip netns exec foo sysctl net.ipv4.conf.eth1.forwarding=1

# Enable arp proxying on both devices
ip netns exec foo sysctl net.ipv4.conf.eth0.proxy_arp=1
ip netns exec foo sysctl net.ipv4.conf.eth1.proxy_arp=1

# Reload
ip netns exec foo sysctl --system

# Flush arp
ip netns exec foo -s -s neigh flush all

# Aggressively flush arp (the one above would do it, but this seems to be quick and thorough):
ip netns exec foo ip link set arp off dev eth0
ip netns exec foo ip link set arp off dev eth1
ip netns exec foo ip link set arp on dev eth0
ip netns exec foo ip link set arp on dev eth1

Once the above is run, I can get to/from all devices on the network without issue.

0

Once a interface is member in a bridge you can't assign an IP address to the interface itself, you need to setup the address to the bridge.bridge-stp-howto

  • Your answer sent me in the right direction I believe. I need to determine how/why it works on Raspbian first. Then I'll dig into having a pseudo-bridge like this article suggests: lartc.org/howto/lartc.bridging.proxy-arp.html Ultimately, I need the Pi to be "invisible" so to speak--eth0 can take on the IP / MAC of the router, and eth1 can take on the IP / MAC of the laptop. Is this possible with a pseudo bridge, arp proxy, and ip forwarding? – Jim Hume Jun 8 '17 at 14:46

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.