I’m running my containers with Podman in Rootless Mode on Alpine for about four months now. However, an annoying problem has haunted me ever since:
When a container was connected to more than one network, outgoing connections were not working correctly.
Consider a container connected to two bridge networks:
$ podman run --rm -it \
--network net1 \
--network net2 \
alpine /bin/ash
Inside the container, the two networks are connected correctly:
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth1@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP qlen 1000
inet 10.89.0.7/24 brd 10.89.0.255 scope global eth1
4: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP qlen 1000
inet 10.89.2.6/24 brd 10.89.2.255 scope global eth0
However, pinging a host on the internet only works using one of the two network interfaces:
# ping -I eth0 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=42 time=4.075 ms
# ping -I eth1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
...
2 packets transmitted, 0 packets received, 100% packet loss
The solution
The solution is quite simple: You will need to set net.ipv4.conf.all.rp_filter
to 2.
On my Alpine system, rp_filter was set to 1 by default. The setting controls the source path validation within the kernel’s IPv4 network stack. 1 means “strict”, whereas 2 means “loose”.
You can try the solution temporarily by running:
# sysctl -w net.ipv4.conf.all.rp_filter=2
To survive the next reboot, persist the setting by adding it to /etc/sysctl.conf
:
# echo "net.ipv4.conf.all.rp_filter=2" >> /etc/sysctl.conf
For more information, you can take a look at this article.