Persisting nf_conntrack_max Value After Reboot: Sysctl Configuration Solutions


2 views

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:

  1. Sysctl applies settings early in boot process
  2. nf_conntrack module loads later (often via iptables service)
  3. 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