Cannot turn off net.ipv4.conf.*.rp_filter no matter what's in /etc/sysctl.conf

I’m using Ubuntu 22.04/20.04 and LXD from Snap store.

I use LXD containers for complex routing running routing software on my containers.

To support some kind of routing, we need to turn off net.ipv4.conf.*.rp_filter, which is set to 2 by default on Ubuntu.

I tried removing /etc/sysctl.d/10-network-security.conf and adding /etc/sysctl.d/99-router.conf specifying net.ipv4.conf.all.rp_filter=0 and net.ipv4.conf.default.rp_filter=0, on the containers and the LXD hosts, rebooting the LXD hosts.

However, no matter I’ve done, individual settings (for example net.ipv4.conf.eth0.rp_filter) are forced to be 2 on the containers.

This way, routing in my network is broken, and I cannot find a way to work around, except setting the value on every interface on every container, which is prohibitive where I have hundreds of network interfaces.

How to turn off net.ipv4.conf.*.rp_filter by default on LXD reliably?

There seems to be a bug were LXD doesn’t obey to the default configuration key when creating the device. A possible workaround is to directly set the interface (as well as all) config:

cat << EOF > /etc/sysctl.d/99-router.conf
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.eth0.rp_filter=0
EOF

I was about to fill a bug against LXD but on second thought, I think it’s a simple limitation of how things are. During the instance boot, LXD configures/inserts the NIC into the instance well before the /etc/sysctl.d/*.conf keys are applied by the corresponding systemd service. By the time the overridden rp_filter keys are set, the NIC has already be configured so the default doesn’t apply to it. Hence the need to specify the rp_filter for each NIC (and the all one).

@amikhalitsyn does that ^ sounds accurate to you?

Does this mean Ubuntu-shipped kernel by default enables rp_filter (independent of sysctl.d/sysctl.conf)?

@amikhalitsyn could it be that the NIC is created in the host so then gets the default value from it before being moved into the instance?

1 Like

I found that, with systemd, wildcard sysctl is possible and there exists a line in /lib/sysctl.d/50-default.conf:

net.ipv4.conf.*.rp_filter = 2

I’ve missed this setting because I thought that everything is in /etc/ and never thought of wildcards.

I added the following into /etc/sysctl.d/99-router.conf:

net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.*.rp_filter=0

Apply with systemctl restart systemd-sysctl.service.

Hope this helps someone.

1 Like

yes, we create veth device on the host and then attach it to the container (in func (d *lxc) deviceAttachNIC). So, I can guess that changing net.ipv4.conf.default.rp_filter to be 0 can help.

so it was effectively the conflict between configurattion in /lib/sysctl.d/50-default.conf and /etc/sysctl.d/99-router.conf, right?

Did you try setting this via the supported LXD sysctl instance settings?

https://documentation.ubuntu.com/lxd/en/latest/reference/instance_options/#instance-miscellaneous:linux.sysctl.*

E.g.

lxc config set <instance> linux.sysctl.net.ipv4.conf.all.rp_filter=0

Although this may still not work as the guest OS, for example Ubuntu, may reset them during boot.

I ran into this today, not associated with LXD. The above is helpful, but there’s one more key detail. From sysctl.d(5):

The settings configured with sysctl.d files will be applied early on boot. The network interface-specific options will also be applied individually for each network interface as it shows up in the system. (More specifically, net.ipv4.conf.*, net.ipv6.conf.*, net.ipv4.neigh.* and net.ipv6.neigh.*).

So the globbed sysctls you found are applied /individually/ when e.g. eth0 was added. That will override the .defaults that you set.

I’ve filed Bug #2065439 “default globbed sysctls override linux defaults” : Bugs : systemd package : Ubuntu suggesting that systemd not ship network sysctls with globs.

Ah thanks for the extra info, this is interesting indeed.