Playing around with LXC containers on a test system (as it seems like there have been a number of fixes and improvements there), it seems that IPv6 connectivity with the default bridge (truenasbr0) may be broken.
On a clean install, I verified the host has both IPv4 and IPv6 connectivity, and then I created an LXC using the Debian Trixie image. IPv4 in the container works by default. (It looks like TrueNAS runs dnsmasq behind the scenes to provide DHCP and DNS servers to the bridge.) IPv6 doesnât, because thereâs no default route in the container. Not a TrueNAS problem; the Debian LXC image is not configured to accept RAs by default.
But if I modify /etc/systemd/network/eth0.network in the container (the Debian LXC image uses systemd-networkd by default, which handles RAs internally) to set IPv6AcceptRA=true, I do get a default route, but still no IPv6 connectivity. I think this may be a TrueNAS bug, but havenât had time to dig into it yet.
Inside the container
root@test:/# ip addr show eth0
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:ea:2c:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.200.0.71/24 metric 1024 brd 172.200.0.255 scope global dynamic eth0
valid_lft 3573sec preferred_lft 3573sec
inet6 fd42:4c58:43ae:0:5054:ff:feea:2ce0/64 scope global mngtmpaddr noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:feea:2ce0/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
root@test:/# ip -6 route
fd42:4c58:43ae::/64 dev eth0 proto ra metric 1024 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default nhid 4048809722 via fe80::8024:f0ff:feb0:25e5 dev eth0 proto ra metric 1024 expires 1790sec pref medium
root@test:/# ping -c1 -4 google.com
PING google.com (142.251.210.206) 56(84) bytes of data.
64 bytes from pnorda-ak-in-f14.1e100.net (142.251.210.206): icmp_seq=1 ttl=115 time=10.7 ms
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.744/10.744/10.744/0.000 ms
root@test:/# ping -c1 -6 google.com
PING google.com (2607:f8b0:4009:811::200e) 56 data bytes
--- google.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
root@test:/# ping -c1 fe80::8024:f0ff:feb0:25e5
PING fe80::8024:f0ff:feb0:25e5 (fe80::8024:f0ff:feb0:25e5) 56 data bytes
64 bytes from fe80::8024:f0ff:feb0:25e5%eth0: icmp_seq=1 ttl=64 time=0.036 ms
--- fe80::8024:f0ff:feb0:25e5 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.036/0.036/0.036/0.000 ms
Outside the container
bcat@benchy:~$ ip addr show truenasbr0
7: truenasbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 82:24:f0:b0:25:e5 brd ff:ff:ff:ff:ff:ff
inet 172.200.0.1/24 brd 172.200.0.255 scope global truenasbr0
valid_lft forever preferred_lft forever
inet6 fd42:4c58:43ae:0:8024:f0ff:feb0:25e5/64 scope global dynamic mngtmpaddr proto kernel_ra
valid_lft forever preferred_lft forever
inet6 fd42:4c58:43ae::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::8024:f0ff:feb0:25e5/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
bcat@benchy:~$ sudo nft list ruleset
table inet truenas {
chain pstrt.truenasbr0 {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 172.200.0.0/24 ip daddr != 172.200.0.0/24 masquerade
ip6 saddr fd42:4c58:43ae::/64 ip6 daddr != fd42:4c58:43ae::/64 masquerade
}
chain fwd.truenasbr0 {
type filter hook forward priority filter; policy accept;
ip version 4 oifname "truenasbr0" accept
ip version 4 iifname "truenasbr0" accept
ip6 version 6 oifname "truenasbr0" accept
ip6 version 6 iifname "truenasbr0" accept
}
chain in.truenasbr0 {
type filter hook input priority filter; policy accept;
iifname "truenasbr0" tcp dport 53 accept
iifname "truenasbr0" udp dport 53 accept
iifname "truenasbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
iifname "truenasbr0" udp dport 67 accept
iifname "truenasbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-solicit, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
iifname "truenasbr0" udp dport 547 accept
}
chain out.truenasbr0 {
type filter hook output priority filter; policy accept;
oifname "truenasbr0" tcp sport 53 accept
oifname "truenasbr0" udp sport 53 accept
oifname "truenasbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
oifname "truenasbr0" udp sport 67 accept
oifname "truenasbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-solicit, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
oifname "truenasbr0" udp sport 547 accept
}
}
So the container receives an RA and gets an IPv6 gateway it can ping, but canât actually route through it. Unclear as yet why.
Edit: The IPv6 default route in the container also disappears after some time. Probably will have to get some pcaps to determine why (which may not be a tonight problem). Itâs possible this is just a network setup issue in the container, but since Iâm not doing anything fancy in there at all, Iâm still suspicious itâs a host issue.


