Packets not received when running IPv6 through a bridge

5

2

I have a setup with two network interface: eth0 and tap0, bridged by br0

bridge name     bridge id               STP enabled     interfaces
br0             8000.************       no              eth0
                                                        tap0

Neither eth0 nor tap0 have an IP address besides eth0's local IPv6 one:

2: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet6 fe80::XXXX:XXXX:XXXX:XXXX/64 scope link 
       valid_lft forever preferred_lft forever
41: tap0: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc fq_codel master br0 state DOWN group default qlen 100
    link/ether YY:YY:YY:YY:YY:YY brd ff:ff:ff:ff:ff:ff

The bridge, however, has a static IPv4 address and a statelessly configured IPv6 address. Because I need this stateless IPv6 address to be configured if it were for eth0, I configured the MAC of tap0 to be larger than that of eth0 (thus, brctl will choose eth0 MAC as the br0 MAC). As a result, the IP address that br0 assignes itself is the same that eth0 would choose without any other interfaces.

Note that privacy extensions are disabled (on all as well as any specific interfaces).

So br0 looks like this:

42: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 192.168.X.Y/24 brd 192.168.X.255 scope global br0
        valid_lft forever preferred_lft forever
    inet6 ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ/64 scope global 
        valid_lft 7123sec preferred_lft 3523sec
    inet6 fe80::ZZZZ:ZZZZ:ZZZZ:ZZZZ/64 scope link 
       valid_lft forever preferred_lft forever

So there's one public and one local IPv6 address and the public one matches the MAC (as it is chosen by stateless). When I now send ICMPv6 packets, I do not receive a reply:

PING google.com(2a00:1450:4001:80e::1008) 56 data bytes
^C
--- google.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms

However, when checking with tcpdump, I see packets being sent and replies arriving between the server and my IP, i.e. I actually see the reply in the packet dump and it is addressed to the IPv6 address of br0. I have tried to specify each interface with ping6 -I <interface> without success.

So right now I am out of ideas: I send out packets, receive a reply on the correct address but still the system seems to be dropping it rather than accepting it. Why does it discard them? Can this be debugged?

Edit: I do have IPv6 routes, running ip -6 route yields:

XXXX:XXX:XXXX:XXXX::/64 dev br0  proto kernel  metric 256  expires 6997sec
fe80::/64 dev br0  proto kernel  metric 256 
fe80::/64 dev eth0  proto kernel  metric 256 
default via fe80::XXX:XXXX:XXXX:XXXX dev br0  proto ra  metric 1024  expires 1597sec

The first line is my ISP-assigned prefix as reported in my router (Fritz Box) and that seems correct as this should be my local network (am I correct?), so I don't need a gateway. The other two are link-local addresses so fine again.

The last route now is what should be interesting, right? The IP I find there seems to match my router. I can ping it, but only if specifying the interface, i.e. running ping6 <ip> yields:

connect: Invalid argument

But ping6 -I br0 <ip> works:

PING <ip>(<ip>) from <myip> br0: 56 data bytes
64 bytes from <ip> icmp_seq=1 ttl=64 time=0.534 ms
64 bytes from <ip> icmp_seq=2 ttl=64 time=0.393 ms
64 bytes from <ip> icmp_seq=3 ttl=64 time=0.350 ms
64 bytes from <ip> icmp_seq=4 ttl=64 time=0.369 ms
^C
--- <ip> ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.350/0.411/0.534/0.075 ms

Of course, <ip> is the routers IP, i.e. the fe80::... address from above. I cannot find the point in my routers configuration where it tells me this address, however, I do find its Unique Local Address (ULA) and it starts with fd80:: but besides that is identical, so I am pretty confident that that's my routers IPv6 address.

However: I can look up my routers IPs using nslookup -query=AAAA fritz.box which yields two responses: The ULA (fd00::...) and the ISP-assigned IPv6 address within the prefix (2a02:...) with the same suffix (I'm guessing it chooses this by using SLAAC with its MAC). What does not appear here is the IP that starts with fe00:... which is entered in the route.

Maybe someone has an explanation for this weird behavior...

javex

Posted 2014-12-08T11:42:24.457

Reputation: 469

Got an ipv6 route? ip -6 route show You may have needed to enable RA reception on the bridge (among many other things) – None – 2014-12-09T05:04:39.320

Answers

1

I cannot say that I could track the problem to its roots but at least I found a "hack" to make it work. I had to make sure that my bridge actually took the MAC from my eth0 interface and not the randomly assigned tap0 MAC. To make sure that happens, you only need to make sure that your tap0 address is larger than that of eth0:

/usr/bin/openvpn --mktun --dev tap0
ip link set dev tap0 down
ip link set dev tap0 address 5a:c0:02:9e:ae:3c
ip link set dev tap0 up

Now creating the bridge will choose eth0's MAC which then will configure correctly for SLAAC. I don't exactly get why it works this way, but now even port forwarding works fine and everything seems okay.

The routes now seem set up correctly as well as I can reach external and internal systems.

javex

Posted 2014-12-08T11:42:24.457

Reputation: 469

0

Did you remember to enable ipv6 forwarding in /etc/sysctl.conf?

Change the line

 #net.ipv6.conf.all.forwarding=1

to

 net.ipv6.conf.all.forwarding=1

which, however, disables stateless autoconfiguration.

MariusMatutiae

Posted 2014-12-08T11:42:24.457

Reputation: 41 321

Do I really need IP forwarding for bridges? Those two seem different to be, because the bridge just passes ethernet frames to the right device based on the MAC but IP forwarding works on a higher layer, doesn't it? – javex – 2014-12-12T11:42:20.340

@javex you absolutely need forwarding for bridges, be they IPv4 or IPv6. This is is a security feature which allows packets to pass from ,say, tap0 to eth. It has nothing to do with networking: in fact iti is controlled by sysctl, not by brctl. – MariusMatutiae – 2014-12-12T11:58:38.430

I have now got it work without IP forwarding. It still seems weird to me that you say it is required because that would only apply if there were multiple IPs but I have a single IP on the br0 interface. What should be forwarded here? Since it works without, I assume forwarding applies to something different, e.g. NAT – javex – 2014-12-18T12:41:09.810

@javex ip forwarding is required to move packets from tap0 to eth0. – MariusMatutiae – 2014-12-18T12:42:58.820