Linux rp_filter Explained: Fix Asymmetric Routing Packet Drops 2026

Linux rp_filter Explained: Fix Asymmetric Routing and Multi-NIC Packet Drops

A Linux server can receive a packet on the correct network interface and still silently discard it before your application ever sees it.

The interface is up.

The IP address is correct.

The firewall appears to allow the connection.

tcpdump confirms that packets are arriving.

Yet SSH, HTTPS, database connections, monitoring traffic, or another service never responds correctly.

On multi-homed Linux servers, one possible cause is reverse path filtering, controlled by the kernel parameter:

net.ipv4.conf.*.rp_filter

rp_filter is a source-validation mechanism. Instead of simply accepting an incoming IPv4 packet because it arrived at a valid local address, Linux can check whether the packet’s source address makes sense according to the kernel’s routing information.

That is valuable for reducing source-address spoofing.

But strict reverse-path validation can conflict with legitimate asymmetric routing, multiple gateways, policy routing, multiple NICs, VPNs, and complex multi-homed networks.

This guide explains exactly how Linux rp_filter works, the differences between values 0, 1, and 2, how to diagnose reverse-path filtering without blindly disabling it, and how it interacts with policy routing and multi-NIC servers.

What Is Linux rp_filter?

rp_filter stands for reverse path filtering.

The parameter belongs to Linux’s IPv4 networking configuration:

net.ipv4.conf.INTERFACE.rp_filter

You can inspect the global value with:

sysctl net.ipv4.conf.all.rp_filter

and the default applied to relevant interfaces with:

sysctl net.ipv4.conf.default.rp_filter

You can also inspect a specific interface:

sysctl net.ipv4.conf.enp1s0.rp_filter

The <a href=”https://docs.kernel.org/networking/ip-sysctl.html” target=”_blank” rel=”noopener”>official Linux kernel IP sysctl documentation</a> defines three modes:

0 = No source validation
1 = Strict reverse-path validation
2 = Loose reverse-path validation

The difference between these values is fundamental.


How Reverse Path Filtering Works

Imagine that a packet arrives:

Source:      203.0.113.50
Destination: 192.168.10.20
Interface:   enp2s0

Without reverse-path validation, Linux can continue processing the packet according to the normal networking stack.

With rp_filter enabled, Linux performs a source-validation check.

Conceptually, Linux asks:

If I needed to send traffic toward 203.0.113.50, what route would my forwarding information base consider valid?

In strict mode, the incoming interface matters strongly.

The Linux kernel documentation states that in strict mode an incoming packet is tested against the FIB, and the check fails when the incoming interface is not the best reverse path. Failed packets are discarded.

This is why the feature can affect multi-homed systems.

If you are already seeing Linux choose an unexpected outbound interface, first read CorgiNetwork’s <a href=”https://corginetwork.com/linux-traffic-uses-wrong-interface/“>Linux Traffic Uses the Wrong Interface</a> guide because an incorrect routing decision can directly influence reverse-path validation.


Understanding rp_filter=0

The first mode is:

rp_filter = 0

This means:

No reverse-path source validation

The kernel does not perform this particular reverse-path filtering test.

This can accommodate complex routing topologies, but disabling source validation has security implications.

Therefore, this should not be your first troubleshooting command:

sudo sysctl -w net.ipv4.conf.all.rp_filter=0

Doing so may make a symptom disappear without proving why it happened.

The better approach is:

Observe
   ↓
Inspect routes
   ↓
Reproduce reverse lookup
   ↓
Confirm asymmetric path
   ↓
Choose appropriate rp_filter behavior

Understanding rp_filter=1: Strict Mode

Strict mode is:

rp_filter = 1

Suppose a packet arrives on:

enp2s0

from:

203.0.113.50

Linux checks the route toward that source.

Imagine:

ip route get 203.0.113.50

returns:

203.0.113.50 via 192.168.10.1 dev enp1s0

The packet arrived through:

enp2s0

but Linux considers:

enp1s0

the best reverse path.

In strict mode, that mismatch can cause source validation to fail.

Conceptually:

Packet arrives
     ↓
   enp2s0
     ↓
Source = 203.0.113.50
     ↓
Reverse route lookup
     ↓
Best path = enp1s0
     ↓
enp2s0 ≠ enp1s0
     ↓
Validation fails

The Linux kernel describes strict mode precisely in these terms: if the incoming interface is not the best reverse path according to the FIB, the packet fails the check.


Understanding rp_filter=2: Loose Mode

Loose mode is:

rp_filter = 2

The question changes.

Instead of requiring:

Is this incoming interface the best reverse path?

Linux effectively checks whether the source is reachable through any interface according to the routing information.

If the source address has a valid route somewhere, the reverse-path test can succeed.

The kernel documentation explicitly recommends loose mode when asymmetric routing or other complicated routing is required.

This distinction is critical:

STRICT MODE

Source reachable through THIS expected path?
               ↓
              YES
               ↓
            Accept


LOOSE MODE

Source reachable through ANY interface?
               ↓
              YES
               ↓
            Accept

Loose mode preserves source validation while accommodating more complicated paths.


rp_filter 0 vs 1 vs 2

A concise comparison:

Value Mode Behavior
0 Disabled No rp_filter source validation
1 Strict Incoming interface must satisfy the strict reverse-path test
2 Loose Source must be reachable through an interface

The Linux kernel notes that strict reverse-path validation is useful against source-address spoofing, while loose mode is appropriate when asymmetric or complicated routing is intentionally used.

That means the correct choice depends on the network architecture.


Why Multi-NIC Linux Servers Can Trigger the Problem

Consider:

                    Internet
                       |
              +--------+--------+
              |                 |
          Gateway A         Gateway B
              |                 |
           enp1s0            enp2s0
              \                 /
               \               /
                Linux Server

Addresses:

enp1s0 → 192.168.10.20
enp2s0 → 10.20.30.20

Now suppose an incoming connection reaches:

10.20.30.20

through:

enp2s0

but the main routing table contains:

default via 192.168.10.1 dev enp1s0

A reverse lookup toward the remote client may therefore prefer:

enp1s0

instead of:

enp2s0

Strict reverse-path filtering can see that as invalid.

This is one reason multi-NIC problems should not be diagnosed by changing sysctl parameters first.

The underlying routing architecture matters.

If each source IP should use its corresponding gateway, see CorgiNetwork’s <a href=”https://corginetwork.com/netplan-multiple-default-routes-policy-routing/“>Netplan Multiple Default Routes and Policy Routing Guide</a>.


Asymmetric Routing Explained

In symmetric routing, traffic conceptually follows:

Client
   |
   | request
   v
Gateway B
   |
   v
enp2s0
   |
Linux
   |
   v
enp2s0
   |
   v
Gateway B
   |
   | response
   v
Client

But an asymmetric path could look like:

REQUEST

Client
   ↓
Gateway B
   ↓
enp2s0
   ↓
Linux


RESPONSE

Linux
   ↓
enp1s0
   ↓
Gateway A
   ↓
Client

Asymmetric routing is not inherently invalid.

There are legitimate architectures where forward and reverse paths differ.

The problem is that strict source validation, stateful firewalls, NAT, upstream anti-spoofing systems, and other controls may expect more symmetric behavior.

The kernel documentation specifically identifies asymmetric routing as a case where loose reverse-path validation can be appropriate.


Symptoms of an rp_filter Problem

Possible symptoms include:

  • tcpdump sees incoming packets but the application does not;
  • SSH works through one interface but fails through another;
  • the secondary IP is reachable only from certain networks;
  • adding a second default gateway causes connections to fail;
  • policy routing appears correct but packets still disappear;
  • multi-homed services work only when one NIC is disabled;
  • connections fail after a route change;
  • packets arrive but no expected response leaves.

None of these symptoms proves rp_filter is responsible.

They merely justify investigating it.


Step 1: Check the Current Values

Start with:

sysctl net.ipv4.conf.all.rp_filter

Then:

sysctl net.ipv4.conf.default.rp_filter

Now inspect every relevant interface:

sysctl net.ipv4.conf.enp1s0.rp_filter
sysctl net.ipv4.conf.enp2s0.rp_filter

You can display all matching values:

sysctl -a 2>/dev/null | grep '\.rp_filter'

This matters because the kernel documentation specifies that the maximum value from the all and interface-specific rp_filter settings is used for source validation on an interface.

That detail causes many troubleshooting mistakes.


Why Changing Only the Interface May Not Work

Suppose:

net.ipv4.conf.all.rp_filter = 1

and:

net.ipv4.conf.enp2s0.rp_filter = 0

You might assume reverse-path filtering is disabled on enp2s0.

But the kernel documentation says the maximum value between the relevant all and interface setting is used.

Therefore, always inspect both scopes before concluding that a change is active.


Step 2: Inspect the Actual Routing Tables

Run:

ip route

Then:

ip rule

Then:

ip route show table all

Linux supports multiple routing tables, and those additional tables become especially important with policy routing. The ip-route(8) documentation notes that multiple routing tables come into play when policy routing is used.

External reference: <a href=”https://man7.org/linux/man-pages/man8/ip-route.8.html” target=”_blank” rel=”noopener”>Linux ip-route(8) manual</a>.

Do not assume the visible default route in the main table tells the entire story.


Step 3: Reproduce the Reverse Lookup

Suppose tcpdump shows an incoming packet from:

203.0.113.50

on:

enp2s0

Ask Linux how it routes toward that source:

ip route get 203.0.113.50

Possible result:

203.0.113.50 via 192.168.10.1 dev enp1s0

Now you have something important:

Incoming interface = enp2s0

Best route toward source = enp1s0

That is exactly the type of topology that deserves investigation when strict reverse-path filtering is enabled.

The ip route get command supports detailed route lookups including source, incoming interface, output interface, packet mark, protocol, and ports.


Test the Incoming Interface Explicitly

For deeper diagnostics, ip route get also accepts an incoming interface.

For example:

ip route get 203.0.113.50 iif enp2s0

The exact lookup you need depends on the topology, but this capability is useful because Linux routing decisions can involve more than destination addresses.

The <a href=”https://man7.org/linux/man-pages/man8/ip-route.8.html” target=”_blank” rel=”noopener”>ip-route manual</a> documents from, iif, oif, mark, ipproto, sport, and dport as route-lookup inputs.


Step 4: Capture the Packet

Run:

sudo tcpdump -ni enp2s0 host 203.0.113.50

Suppose you see:

203.0.113.50.52140 > 10.20.30.20.443: Flags [S]

repeated several times.

The packet definitely reaches the interface.

Now capture across all interfaces:

sudo tcpdump -ni any host 203.0.113.50

Ask:

Does the SYN arrive?

Does Linux generate a SYN-ACK?

Does the SYN-ACK leave?

Does the client respond?

For packet-level troubleshooting beyond tcpdump, use CorgiNetwork’s <a href=”https://corginetwork.com/wireshark-explained/“>Wireshark Explained</a> guide.


Step 5: Confirm the Service Is Actually Listening

Before blaming the kernel, run:

ss -lntp

Suppose you expect HTTPS on:

10.20.30.20:443

but the service listens only on:

192.168.10.20:443

That is not an rp_filter problem.

Likewise, if:

0.0.0.0:443

is listening, investigate the next layer.

Good troubleshooting eliminates simpler explanations before changing security-related kernel parameters.


Step 6: Check the Firewall

Inspect nftables:

sudo nft list ruleset

or the firewall framework used by your distribution.

A packet can be visible in tcpdump but still be rejected later in the network stack.

CorgiNetwork’s <a href=”https://corginetwork.com/firewalls-explained/“>Firewalls Explained</a> guide covers the relationship between interfaces, addresses, protocols, connection state and filtering.

Do not disable the firewall and rp_filter simultaneously.

If connectivity suddenly works, you will not know which change mattered.


rp_filter and Policy Routing

Now consider a more advanced configuration:

192.168.10.20
      ↓
Table 100
      ↓
Gateway A


10.20.30.20
      ↓
Table 200
      ↓
Gateway B

Linux policy routing uses rules to determine which routing table should be consulted.

Inspect them with:

ip rule

The ip utility exposes rule specifically for managing the routing policy database.

Then inspect:

ip route show table 100
ip route show table 200

If policy routing correctly establishes the expected reverse path, you may be able to preserve stronger source validation rather than weakening rp_filter.

That is why routing should usually be corrected before filtering is relaxed.

For a complete Ubuntu implementation, use the published CorgiNetwork guide:

<a href=”https://corginetwork.com/netplan-multiple-default-routes-policy-routing/“>Netplan Multiple Default Routes: Ubuntu Policy Routing and Two-NIC Servers</a>.


Policy Routing Can Be the Real Fix

Imagine this configuration:

Packet arrives on enp2s0
Source: 203.0.113.50

Main table:

default via Gateway A dev enp1s0

Without appropriate policy routing:

Reverse lookup
      ↓
enp1s0

But if your architecture requires traffic associated with the second path to use a separate routing table, policy routing may produce a route consistent with that design.

The important lesson is:

Do not treat rp_filter as a substitute for correct routing.

Sometimes strict validation exposes a routing configuration that was already inconsistent.


rp_filter and fwmark-Based Routing

Advanced Linux configurations can route packets using firewall marks.

The kernel provides:

net.ipv4.conf.*.src_valid_mark

The official documentation explains that when src_valid_mark=1, a packet’s fwmark is included in the reverse-path route lookup. This allows rp_filter to function with configurations that use marks for routing in both directions.

This is particularly relevant to:

  • transparent proxies;
  • advanced policy routing;
  • multi-WAN systems;
  • nftables marking;
  • specialized gateways.

Do not modify src_valid_mark unless your routing architecture actually uses packet marks.


Loose Mode vs Disabling rp_filter

Administrators sometimes jump directly from:

rp_filter = 1

to:

rp_filter = 0

But loose mode exists:

rp_filter = 2

and can be a better fit for legitimate asymmetric routing.

Conceptually:

Strict
   ↓
Must satisfy strict reverse path


Loose
   ↓
Source must be reachable somewhere


Disabled
   ↓
No rp_filter validation

The kernel documentation explicitly identifies loose mode as appropriate for asymmetric or complicated routing.

Red Hat’s security documentation likewise describes values 0, 1, and 2, and cautions against simply disabling reverse-path validation without another source-validation mechanism where it is needed.

External reference: <a href=”https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/security_guide/sec-securing_network_access” target=”_blank” rel=”noopener”>Red Hat Reverse Path Forwarding documentation</a>.


Temporarily Testing Loose Mode

If your investigation demonstrates that legitimate asymmetric routing conflicts with strict validation, you can perform a controlled test.

For example:

sudo sysctl -w net.ipv4.conf.all.rp_filter=2

and, depending on the existing settings:

sudo sysctl -w net.ipv4.conf.enp2s0.rp_filter=2

Then immediately repeat the same packet test.

Do not change five networking parameters at once.

Use:

Baseline test
     ↓
One controlled change
     ↓
Repeat identical test
     ↓
Compare packet capture

If the previously failing connection begins working, you now have evidence supporting the hypothesis.

You still need to decide whether loose mode is the correct production design.


Do Not Test by Disabling Every Security Control

This is poor troubleshooting:

systemctl stop firewalld
sysctl -w net.ipv4.conf.all.rp_filter=0
# disable security group
# disable ACL

If connectivity works afterward, you have learned almost nothing.

Instead:

Test firewall
      ↓
Test routing
      ↓
Test rp_filter
      ↓
Test upstream path

Change one relevant variable at a time.


Making rp_filter Changes Persistent

A runtime command such as:

sudo sysctl -w net.ipv4.conf.all.rp_filter=2

does not by itself provide a maintainable permanent configuration.

On systems using sysctl.d, you can create an appropriately named configuration file, for example:

/etc/sysctl.d/90-multihoming.conf

A configuration might contain values chosen for your topology, such as:

# Reverse-path filtering for intentionally asymmetric multi-homed routing.
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2

Then load the appropriate sysctl configuration according to your distribution’s management practices.

Before making it permanent, document why loose mode is required.

A future administrator should not find:

rp_filter = 2

without knowing which routing architecture depends on it.


Verify After Reboot

After rebooting during an appropriate maintenance window:

sysctl net.ipv4.conf.all.rp_filter

Then:

sysctl net.ipv4.conf.default.rp_filter

and:

sysctl net.ipv4.conf.enp1s0.rp_filter
sysctl net.ipv4.conf.enp2s0.rp_filter

Also verify:

ip rule
ip route show table all

Persistent reverse-path settings are useless if the routing configuration they were designed for did not load correctly.


rp_filter vs arp_filter

These two kernel settings have similar names but solve completely different problems.

rp_filter

Concerned with:

Incoming IP packet
       ↓
Source address
       ↓
Reverse route validation

arp_filter

Concerned with:

ARP request
      ↓
Which interface should answer?

The kernel documentation says arp_filter=1 can be used with multiple interfaces on the same subnet and relies on source-based routing to decide whether an interface should answer an ARP request.

If your problem is that the wrong NIC/MAC answers ARP requests, use CorgiNetwork’s:

<a href=”https://corginetwork.com/linux-arp-flux-multiple-nics-same-subnetpolicy-routing/“>Linux ARP Flux: Multiple NICs on the Same Subnet</a>.

Do not change rp_filter to solve an ARP-layer problem.


rp_filter vs ARP Flux

A useful distinction:

ARP FLUX

Who answers:
"Who has this IPv4 address?"

          ↓

Layer 2 / neighbor resolution behavior

versus:

REVERSE PATH FILTERING

Packet has already arrived

          ↓

Does this source make sense
according to routing?

They can occur on the same multi-homed server, which is why confusing them is easy.

The correct troubleshooting order is often:

ARP / neighbor resolution
        ↓
Incoming interface
        ↓
Reverse-path validation
        ↓
Routing
        ↓
Firewall
        ↓
Application

rp_filter vs Firewall Drops

Suppose tcpdump sees:

SYN → server

but the application never sees the connection.

Several mechanisms could be responsible:

rp_filter
firewall
policy routing
application binding
security software

Inspect the firewall rather than assuming rp_filter.

For example:

sudo nft list ruleset

Then inspect system logs where appropriate.

A strong diagnosis identifies the exact layer responsible for the drop.


Practical Example: Two ISP Connections

Consider a Linux server with:

ISP A
  |
enp1s0
192.0.2.10
  |
Linux
  |
enp2s0
198.51.100.10
  |
ISP B

An Internet client reaches:

198.51.100.10

through ISP B.

But the server’s ordinary default route points to ISP A.

Without suitable routing policy:

Packet arrives via ISP B
          ↓
       enp2s0
          ↓
Linux checks route to source
          ↓
Main table says ISP A
          ↓
       enp1s0

With strict reverse-path validation, this topology can cause incoming traffic to fail validation.

Potential solutions depend on the design:

  • correct source-based policy routing;
  • use loose reverse-path validation where asymmetry is intentional;
  • redesign the routing architecture;
  • use appropriate multi-WAN routing.

Simply disabling validation is not necessarily the correct solution.


Practical Example: Management NIC + Production NIC

Suppose:

enp1s0
10.10.10.20
Management network

enp2s0
172.16.20.20
Production network

The management network should be reachable only through:

10.10.10.1

while production traffic uses:

172.16.20.1

If both interfaces depend on one global default route, the reverse route for management clients may point through the production NIC.

Instead of weakening rp_filter, a cleaner architecture may be:

Management source/network
        ↓
Management routing table


Production source/network
        ↓
Production routing table

CorgiNetwork’s <a href=”https://corginetwork.com/netplan-multiple-default-routes-policy-routing/“>Netplan Policy Routing Guide</a> demonstrates this type of separation on Ubuntu.


Practical Example: Packet Arrives but SSH Fails

Suppose:

sudo tcpdump -ni enp2s0 tcp port 22

shows:

client → SYN → server
client → SYN → server
client → SYN → server

but:

ss -lntp | grep ':22'

confirms SSH is listening.

Now check:

sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.enp2s0.rp_filter

Then:

ip route get CLIENT_IP

If:

Incoming = enp2s0
Reverse route = enp1s0
Strict rp_filter = active

you have a strong hypothesis worth testing.

That is much better than immediately editing /etc/ssh/sshd_config.


Use Netcat to Separate Routing from Application Problems

If SSH or HTTPS fails, test the actual port:

nc -vz SERVER_IP 22

or:

nc -vz SERVER_IP 443

CorgiNetwork’s <a href=”https://corginetwork.com/netcat-explained/“>Netcat Explained</a> guide covers direct TCP and UDP connectivity testing.

If multiple services fail only through one NIC, the probability of a network-path problem increases.

If only one application fails while others work through the same interface, investigate that application first.


Use Wireshark or tcpdump to Confirm the Direction

Command-line capture:

sudo tcpdump -ni any host CLIENT_IP

A healthy TCP handshake should resemble:

Client → SYN
Server → SYN-ACK
Client → ACK

If you only see:

Client → SYN
Client → SYN
Client → SYN

the server is not successfully responding.

Now determine whether the packet:

  1. reaches the interface;
  2. survives reverse-path validation;
  3. survives firewall processing;
  4. reaches the listening socket.

For more advanced analysis, see <a href=”https://corginetwork.com/wireshark-explained/“>Wireshark Explained</a>.


A Complete rp_filter Troubleshooting Workflow

Use this order.

Step 1 — Identify interfaces

ip -br link

Step 2 — Identify addresses

ip -br addr

Step 3 — Check main routes

ip route

Step 4 — Check policy rules

ip rule

Step 5 — Check every routing table

ip route show table all

Step 6 — Inspect rp_filter

sysctl -a 2>/dev/null | grep '\.rp_filter'

Step 7 — Capture the incoming packet

sudo tcpdump -ni INTERFACE host CLIENT_IP

Step 8 — Reproduce the reverse lookup

ip route get CLIENT_IP

Step 9 — Check firewall rules

sudo nft list ruleset

Step 10 — Confirm listening sockets

ss -lntp

Step 11 — Test the service

nc -vz SERVER_IP PORT

Step 12 — If justified, test an alternative rp_filter mode

Make one controlled change and repeat exactly the same test.

This process gives you evidence instead of guesses.


Diagnostic Decision Tree

Packet reaches interface?
        |
   +----+----+
   |         |
  NO        YES
   |         |
Upstream     v
network    Correct destination?
             |
        +----+----+
        |         |
       NO        YES
        |         |
     Routing      v
               rp_filter active?
                    |
               +----+----+
               |         |
              NO        YES
               |         |
          Firewall /     v
          application  Reverse route
                         |
                    +----+----+
                    |         |
                 Expected   Different
                    |         |
                    v         v
               Check next   Policy routing /
                 layer      loose-mode analysis

Common Mistake 1: Immediately Setting rp_filter=0

This is perhaps the most common mistake.

A connection fails on the secondary NIC, so an administrator searches online and finds:

sysctl -w net.ipv4.conf.all.rp_filter=0

Connectivity returns.

Problem solved?

Not necessarily.

The test proved that reverse-path validation was relevant.

It did not prove that disabling validation is the best architecture.

You may instead need:

  • policy routing;
  • corrected route metrics;
  • a missing route;
  • loose mode;
  • a better multi-WAN design.

Common Mistake 2: Changing Only default.rp_filter

The default value is important for interface configuration, but you should inspect:

all
default
actual interface

rather than assuming one value describes the active behavior.

Use:

sysctl -a 2>/dev/null | grep '\.rp_filter'

and inspect the complete state.


Common Mistake 3: Confusing rp_filter with a Stateful Firewall

Reverse-path filtering is not the same thing as:

nftables
iptables
UFW
firewalld

It is kernel source validation based on routing information.

Both mechanisms can drop traffic, but they do so for different reasons.


Common Mistake 4: Fixing Filtering Before Fixing Routing

Suppose:

ip route get CLIENT_IP

clearly returns the wrong interface.

That routing problem should receive attention before you weaken validation to accommodate it.

Use the CorgiNetwork <a href=”https://corginetwork.com/linux-traffic-uses-wrong-interface/“>Wrong Interface Troubleshooting Guide</a> to investigate route selection first.


Common Mistake 5: Confusing rp_filter and arp_filter

Remember:

rp_filter
=
Reverse path validation of IP source


arp_filter
=
ARP response behavior

For multiple NICs on the same subnet and unexpected MAC/interface behavior, see the <a href=”https://corginetwork.com/linux-arp-flux-multiple-nics-same-subnetpolicy-routing/“>Linux ARP Flux Guide</a> instead.


Common Mistake 6: Ignoring Distribution Defaults

The upstream Linux kernel documentation lists the default rp_filter value as 0, while noting that some distributions enable it through startup configuration.

Therefore, never assume:

"My Linux distribution must use value X."

Measure the actual machine:

sysctl net.ipv4.conf.all.rp_filter

and:

sysctl net.ipv4.conf.INTERFACE.rp_filter

The running configuration is what matters.


Production Checklist

Before changing rp_filter permanently, confirm:

✓ Incoming interface identified
✓ Source address identified
✓ Reverse route verified
✓ Main routing table inspected
✓ Policy-routing rules inspected
✓ Custom routing tables inspected
✓ Firewall checked
✓ Listening application verified
✓ Packet capture performed
✓ Asymmetric routing confirmed or ruled out
✓ Security implications considered
✓ Strict vs loose mode evaluated
✓ Configuration documented
✓ Persistence tested after reboot

If you cannot explain why the current reverse route differs from the incoming interface, continue diagnosing before changing the security policy.


Frequently Asked Questions

What does Linux rp_filter do?

It performs IPv4 reverse-path source validation. Linux checks an incoming packet’s source against routing information to determine whether the source is plausible according to the configured mode.

What does rp_filter=0 mean?

It disables this reverse-path source-validation mechanism.

What does rp_filter=1 mean?

It enables strict mode. The kernel checks the source against the FIB, and the incoming interface must satisfy the strict best-reverse-path requirement.

What does rp_filter=2 mean?

It enables loose mode. The source needs to be reachable through an interface rather than satisfying strict incoming-interface validation. The kernel recommends loose mode for asymmetric or complicated routing scenarios.

Should I disable rp_filter on a multi-homed server?

Not automatically. First determine whether the routing configuration is correct. If legitimate asymmetric routing is intentional, loose mode may be appropriate depending on the architecture.

How do I check rp_filter for all interfaces?

Use:

sysctl -a 2>/dev/null | grep '\.rp_filter'

How can I test the reverse route?

If a packet arrives from:

203.0.113.50

run:

ip route get 203.0.113.50

Then compare the selected path with the interface on which the packet arrived.

Can policy routing fix an rp_filter problem?

Sometimes the real problem is incorrect reverse-path routing. Source-based policy routing can make routing consistent with a multi-interface architecture rather than weakening filtering to accommodate incorrect routes.

Is rp_filter a firewall?

No. It is an IPv4 source-validation mechanism associated with routing information. Firewall frameworks such as nftables provide separate packet-filtering capabilities.

Is rp_filter the same as arp_filter?

No. rp_filter deals with IP reverse-path validation. arp_filter controls aspects of ARP response behavior.

Why does tcpdump see packets when my application doesn’t?

Packet capture can observe traffic at a point before some later processing decisions. Therefore, seeing an incoming packet proves that it reached the host/interface, but it does not by itself prove that it reached the application socket.


Conclusion

Linux rp_filter is not simply an obscure sysctl that should be disabled whenever a second network interface stops working.

It is a security mechanism designed to validate incoming IPv4 source addresses against the kernel’s routing information.

The key difference is:

rp_filter = 1
       ↓
Strict reverse-path validation


rp_filter = 2
       ↓
Loose reverse-path validation


rp_filter = 0
       ↓
No rp_filter source validation

When a multi-homed Linux server drops legitimate traffic, the correct question is not:

What command disables rp_filter?

It is:

Why does Linux believe the reverse path for this source differs from the path on which the packet arrived?

Answer that with:

ip route
ip rule
ip route show table all
ip route get CLIENT_IP
sysctl -a 2>/dev/null | grep '\.rp_filter'
tcpdump

If Linux selects an incorrect interface, continue with CorgiNetwork’s <a href=”https://corginetwork.com/linux-traffic-uses-wrong-interface/“>Linux Traffic Uses the Wrong Interface</a> guide.

If different NICs require independent gateways, use the <a href=”https://corginetwork.com/netplan-multiple-default-routes-policy-routing/“>Netplan Multiple Default Routes and Policy Routing Guide</a>.

If the problem occurs before IP routing because the wrong interface answers ARP requests, continue with <a href=”https://corginetwork.com/linux-arp-flux-multiple-nics-same-subnetpolicy-routing/“>Linux ARP Flux: Multiple NICs on the Same Subnet</a>.

Together, these articles create a focused troubleshooting path:

Wrong interface
       ↓
Policy routing
       ↓
ARP behavior
       ↓
Reverse-path filtering
       ↓
Packet-level verification

That is a much more reliable approach than disabling networking protections until the connection starts working.

Leave a Reply

Your email address will not be published. Required fields are marked *