bsdpot/pot

[BUG] Pot should run ip6addrctl on jail startup

grembo opened this issue · 0 comments

Describe the bug
(Usually?) pot installations are based on ipv4, but without calling ip6addrctl, the default address selection policy uses IPv6 in case a domain has an AAAA record. This makes some tools chose the wrong protocol.

To Reproduce
Create a pot that is based on /tmp/tinirc, jexec into the running jail, then:

root@long_jail_name:/ # host www.google.com                                (1)
www.google.com has address 142.251.36.196
www.google.com has IPv6 address 2a00:1450:4016:809::2004
root@long_jail_name:/ # ping www.google.com                                (2)
ping: UDP connect: No route to host
root@long_jail_name:/ # ping -4 www.google.com                             (3)
PING www.google.com (142.250.184.196): 56 data bytes
64 bytes from 142.250.184.196: icmp_seq=0 ttl=59 time=5.146 ms
^C
root@long_jail_name:/ # service ip6addrctl start                           (4)
root@long_jail_name:/ # ping www.google.com                                (5)
PING www.google.com (142.250.184.196): 56 data bytes
64 bytes from 142.250.184.196: icmp_seq=0 ttl=59 time=5.164 ms
^C
  1. The hostname lookup of www.google.com shows that it has both IN A and IN AAAA records.
  2. Pinging www.google.com selects IPv6, which is not configured in the pot to have any routes to the outside world and therefore fails.
  3. Pinging with an explicit protocol specification works as expected.
  4. Running the ip6addrctl rc script configured the default of preferring IPv4.
  5. Now ping works as expected (prefer IPv4).

Expected behavior
Expect 5. from above to work by default (prefer IPv4 in an IPv4 based pot).

Additional context
Fixing this should be fairly straightforward. The general question of course is how much of these things should be done by pot itself and which things should be done by the container's payload (some customized script).

Either way, in this case the fix is fairly simple - either call service ip6addrctl start like above, or do what /etc/rc.d/ip6addrctl would do in /tmp/tinirc:

if sysctl -n kern.features.inet6 >/dev/null 2>&1; then
	${IP6ADDRCTL_CMD} flush >/dev/null 2>&1
	cat <<EOT | ${IP6ADDRCTL_CMD} install /dev/stdin
	::1/128          50      0
	::/0             40      1
	::ffff:0:0/96   100      4
	2002::/16        30      2
	2001::/32         5      5
	fc00::/7          3     13
	::/96             1      3
	fec0::/10         1     11
	3ffe::/16         1     12
EOT
fi

Maybe calling service ip6addrctl start (but not stopping in case that didn't work), might be some good real-world middle-ground solution, as it would allow less-stripped down images to override the default (by changing the ip6addrctl_policy in rc.conf), while those who create really stripped-down images (without /etc/rc.d) could still setup things in their own scriptwork as they want.