I need to disbale reverse path filtering in linux to set net.ipv4.conf.default.rp_filter to 0(net.ipv4.conf.default.rp_filter = 2)
now I like to know how to make above settings active so reverse path filtering is disabled do I need to restart sysctl or some thing, Can anyone please tell this I tried like above but when I ran the sysctl -system I get this
net.ipv4.conf.default.rp_filter = 2 sysctl: setting key "net.ipv4.conf.all.rp_filter": Invalid argument
why this invalid argument message and I tried changing it to net.ipv4.conf.default.rp_filter = 0 but it still printing sysctl -system as
net.ipv4.conf.default.rp_filter = 2 along with message
1 Answer 1
There are a few things you’ve confused,
First, it’s sysctl —system not sysctl -system to reload your configuration files; but that may just be a typo in the question.
Second, when you use sysctl -w to change any setting, that -w means writing in the «write instead of readout»-sense, not in the «write to file»-sense. It would only affect the currently active configuration, and it wouldn’t be saved anywhere.
So when you run sysctl —system to reload the system configurationfiles, you undo your prior sysctl -w action.
Third, you’re presumably trying to change the effective rp_filter value on your system, but the default part of the net.ipv4.conf.default.rp_filter key, means it affects the default value for any unnamed network device that gets created after this point.
Presumably, your network device already exists, which means it already has its own personal rp_filter setting, and it doesn’t care about the default anymore. If your network device is called eth0 , then net.ipv4.conf.eth0.rp_filter is likely the value you actually wanted to change (with sysctl -w or, by writing that into one of the /etc/sysctl.d/*.conf -style configuration files and then rebooting or reloading the —system ).
In addition to the default and eth0 (or whatever yours is called), there is also an all version; which is like a wildcard that affects all the existing variants (eg: eth0 , eth1 and eth2 ). When your sysctl configuration is loaded during bootup, the networkdevices may or may not exist yet at the time your sysctl configuration is parsed, so it could easily vary if eth0 does or does not exist yet at that time. If it did exist already then the eth0 and all variants would result in the desired affect and the default variant would not. If however the device didn’t exist yet, then it’s actually the other way around, and default is the one which would work as intended.
To be sure, just change them all/both; in your /etc/sysctl.conf or /etc/sysctl.d/*.conf files.
Ok, so since you’re using a virtual networking device tun0 , which gets created later on, going for the default key actually wasn’t a mistake.
The main thing still holds though, you do not want to use both sysctl -w and sysctl —system together, as the later undoes what the former did.
It sounds like you either want something like:
sysctl -w net.ipv4.conf.default.rp_filter=0 ; sysctl -w net.ipv4.conf.tun0.rp_filter=0 ;
echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter ; echo 0 > /proc/sys/net/ipv4/conf/tun0/rp_filter ;
Or alternatively, use the .conf files; then you can use —system to reload them.
Disable rp_filter on unix
Sometimes in a more complicated network setups you want to disable rp_filtering.
For a good explanation of what rp_filter is and why it is enabled see this excellent slashroot article here.
I came across a situation where one box had two NICs:
# grep -Ev '^#.*$' /etc/network/interfaces auto lo iface lo inet loopback auto eth1 iface eth1 inet static address 192.168.11.8 netmask 255.255.255.0 gateway 192.168.11.254 dns-nameservers 192.168.11.4 auto eth2 iface eth2 inet static address 192.168.100.41 netmask 255.255.255.0 up route add default gw 192.168.100.254
From another box that was in the same 192.168.11.0/24 range I could only access this machine over its 192.168.11.8 ip address. When I tried a ping, curl, wget, ssh, telnet or whatever to 192.168.100.41 I got nothing.
A tcpdump on this box showed that packets on the 192.168.100.41 interface were received but my machine had trouble sending the return packets causing the above described behaviour. You get; Nothing.
And whenever I tried to access this box from a machine in the 192.168.100.0/24 network I got the same behaviour but with the 192.168.11.8 ip.
The routing table on this box looks like the following:
# ip route 192.168.11.0/24 dev eth1 proto kernel scope link src 192.168.11.8 192.168.100.0/24 dev eth2 proto kernel scope link src 192.168.100.41 default via 192.168.100.254 dev eth2 default via 192.168.11.254 dev eth1 metric 100
Since you cannot have two default routes the kernel tries to sent packets back over the wrong interface.
I solved this by disabling reverse path filtering.
To get your current kernel configuration run:
To enable rp_filtering (persisted up until the next reboot)
sysctl -w net.ipv4.conf.all.rp_filter=1 sysctl -w net.ipv4.conf.default.rp_filter=1 sysctl -w net.ipv4.conf.lo.rp_filter=1 # Replace eth1 and eth2 with your interface names sysctl -w net.ipv4.conf.eth2.rp_filter=1 sysctl -w net.ipv4.conf.eth1.rp_filter=1
To disable rp_filtering (persisted up until the next reboot)
sysctl -w net.ipv4.conf.all.rp_filter=0 sysctl -w net.ipv4.conf.default.rp_filter=0 sysctl -w net.ipv4.conf.lo.rp_filter=0 # Replace eth1 and eth2 with your interface names sysctl -w net.ipv4.conf.eth2.rp_filter=0 sysctl -w net.ipv4.conf.eth1.rp_filter=0
If you want to disable rp_filtering permanently create a file 90-disable-rp_filter.conf inside /etc/sysctl.d with the following contents:
# cat /etc/sysctl.d/90-disable-rp_filter.conf net.ipv4.conf.all.rp_filter=0 net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.lo.rp_filter=0 net.ipv4.conf.eth2.rp_filter=0 net.ipv4.conf.eth1.rp_filter=0
RP Filter and Multicast receiving in Linux
The rp_filter technology is a useful tool for enhancing the security and protection of servers that receive UDP multicast traffic, particularly for servers with multiple network interfaces. When configuring servers to receive UDP multicast traffic, there are two options available: configuring system routing for multicast groups or modifying the rp_filter setting.
Configure strict mode for RP filter
To modify the rp_filter setting, add the following lines to the /etc/sysctl.conf file:
net.ipv4.conf.eth0.rp_filter = 2
Note that eth0 should be replaced with the name of the interface being used. To apply the changes, either restart the system or execute the following command:
RP Filter values
There are three possible values for the rp_filter parameter in Linux:
- 0 — disables the rp_filter feature altogether
- 1 — default setting and enables strict reverse path filtering. In this mode, the kernel checks whether incoming packets arrive on the expected interface according to the routing table, and drops packets that do not
- 2 — this setting enables loose reverse path filtering. This mode is less strict than strict reverse path filtering and allows packets to arrive on other interfaces, provided that they can be routed back to the source address on the interface from which they were received
The choice of rp_filter setting depends on the specific network configuration and security requirements of the system. It is important to select the appropriate setting to ensure optimal security and performance of the network.
Disable reverse path filtering from Linux kernel space
Within a Linux kernel module, I need to disable rp_filter in some way. This would typically be possible from user-space via a couple of simple sysctl calls :
sysctl net.ipv4.conf.all.rp_filter=0 sysctl net.ipv4.conf.[ifname].rp_filter=0
How can I achieve the same result from kernel space? My first idea is that I probably need to write into the relative proc files. If so, what is the proper way to do this?
Nope. I believe there should be some API somewhere to do this without hacking.. Basically I’d just need to know where the rp_filter flag is intercepted within the kernel, and from there follow the calls path
I’ve checked. you can’t access it directly, as it’s defined static in the module. it’s not exported. There are few exported functions, you can check if they allow access to that.
1 Answer 1
I’m looking at the implementation of sysctl in the kernel, and I’ve found that doing a sysctl is just the same as writing a value to a file in the /proc filesystem.
In your case you just want to do the equivalent of:
echo 0 >/proc/sys/net/ipv4/conf/all/rp_filter
Here is a rough code sample, based on what I see in the kernel code I am reading just now:
struct vfsmount *mnt; struct file *file; ssize_t result; char *pathname = "sys/net/ipv4/conf/all/rp_filter"; int flags = O_WRONLY; mnt = task_active_pid_ns(current)->proc_mnt; file = file_open_root(mnt->mnt_root, mnt, pathname, flags); result = PTR_ERR(file); if (IS_ERR(file)) < // oops, something bad happened >else < char *buffer = "\0"; result = kernel_write(file, buffer, 1, 0); // last 2 args are 'count' and 'pos' if (result < 0) < // oops, something else bad happened >> fput(file);
This is just a rough sample, so you will have to do your own research and testing to get it working. Good luck!