When working with connection tracking in Linux, you'll notice two seemingly identical paths in /proc
:
/proc/sys/net/netfilter/nf_conntrack_max /proc/sys/net/nf_conntrack_max
These are actually symlinks pointing to the same underlying value, which explains why changing one affects the other. This legacy design exists for backward compatibility.
The core issue occurs because the nf_conntrack
module loads after sysctl applies its settings during boot. Here's what's happening:
1. Boot process applies sysctl.conf settings 2. Kernel loads nf_conntrack module (later in boot) 3. Module initializes with default values 4. Your custom settings get overwritten
Here are three effective methods to ensure your settings persist:
Method 1: Load Module Early
Create a modprobe configuration file:
# /etc/modprobe.d/nf_conntrack.conf options nf_conntrack nf_conntrack_max=65535
Method 2: Post-Module Sysctl
Create a systemd service that runs after network initialization:
# /etc/systemd/system/set-conntrack.service [Unit] Description=Set nf_conntrack_max After=network.target [Service] Type=oneshot ExecStart=/usr/sbin/sysctl -w net.netfilter.nf_conntrack_max=65535 [Install] WantedBy=multi-user.target
Then enable it:
systemctl enable set-conntrack.service
Method 3: Network Script Solution
For systems using network scripts, add this to your ifup-post script:
#!/bin/sh echo 65535 > /proc/sys/net/netfilter/nf_conntrack_max
After implementing any solution, verify with:
cat /proc/sys/net/netfilter/nf_conntrack_max sysctl net.netfilter.nf_conntrack_max
For modern systems using systemd-networkd, create a drop-in file:
# /etc/systemd/network/50-conntrack.network [Network] LinkLayerAddressingPolicy=persistent IPForward=ipv4 IPv6PrivacyExtensions=no [Network] # Additional settings
Then add the sysctl setting to the networkd service:
# /etc/systemd/system/systemd-networkd.service.d/override.conf [Service] ExecStartPost=/usr/sbin/sysctl -w net.netfilter.nf_conntrack_max=65535
Many Linux administrators encounter this frustrating scenario - you carefully set nf_conntrack_max
in /etc/sysctl.conf
, only to find it reverts to default after reboot. The issue stems from load timing between kernel modules and sysctl initialization.
The two paths in /proc
are actually symlinks pointing to the same kernel parameter:
$ ls -l /proc/sys/net/netfilter/nf_conntrack_max lrwxrwxrwx 1 root root 0 Aug 12 10:15 /proc/sys/net/netfilter/nf_conntrack_max -> ../../../../kernel/net/netfilter/nf_conntrack_max $ ls -l /proc/sys/net/nf_conntrack_max lrwxrwxrwx 1 root root 0 Aug 12 10:15 /proc/sys/net/nf_conntrack_max -> ../../kernel/net/netfilter/nf_conntrack_max
The core issue occurs because:
- Sysctl applies settings early in boot process
- nf_conntrack module loads later (often via iptables service)
- Module loading overwrites our configured value with defaults
Here are three working approaches:
Method 1: Load Module Early via initramfs
# Edit /etc/modules-load.d/nf_conntrack.conf nf_conntrack
Then rebuild initramfs:
$ sudo update-initramfs -u
Method 2: Systemd Service Unit
Create /etc/systemd/system/set-conntrack.service
:
[Unit] Description=Set nf_conntrack_max After=netfilter.service [Service] Type=oneshot ExecStart=/sbin/sysctl -w net.netfilter.nf_conntrack_max=65536 [Install] WantedBy=multi-user.target
Enable it:
$ sudo systemctl enable set-conntrack.service
Method 3: Iptables Ruleset Script
For systems using iptables, add this to your rules script:
#!/bin/sh /sbin/sysctl -w net.netfilter.nf_conntrack_max=65536 # Rest of iptables rules...
After implementing any method, verify with:
$ cat /proc/sys/net/netfilter/nf_conntrack_max 65536
Check after reboot to confirm persistence.
For newer kernels (4.9+), consider using connection tracking helpers:
$ echo 1 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose $ echo 120 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established