Skip to content

Network Hardening

All network-level hardening is applied via boot.kernel.sysctl in server/modules/kernel.nix and firewall rules in server/modules/network.nix.

BPF Hardening

nix
"net.core.bpf_jit_harden" = 2;
"net.core.bpf_jit_kallsyms" = 0;
SysctlValueEffect
bpf_jit_harden2Applies JIT hardening to all BPF programs (not just unprivileged), constant blinding prevents JIT spray attacks
bpf_jit_kallsyms0Hides JIT-compiled BPF program addresses from /proc/kallsyms

Combined with kernel.unprivileged_bpf_disabled = 1 from Kernel Hardening, this eliminates eBPF as an attack vector for unprivileged users and hardens it for privileged use.

Core Network Security

nix
"net.core.fb_tunnels_only_for_init_net" = 1;
"net.core.xfrm_larval_drop" = 1;
SysctlValueEffect
fb_tunnels_only_for_init_net1Restricts fallback tunnel devices to the initial network namespace only
xfrm_larval_drop1Drops packets requiring IPsec SA resolution instead of queueing them

IPv4 Interface Hardening

Applied to both all and default interfaces to ensure coverage for dynamically created interfaces (e.g., container veth pairs):

nix
# Applied to both conf.all and conf.default
"net.ipv4.conf.*.accept_redirects" = 0;
"net.ipv4.conf.*.accept_source_route" = 0;
"net.ipv4.conf.*.bootp_relay" = 0;
"net.ipv4.conf.*.forwarding" = 0;
"net.ipv4.conf.*.log_martians" = 1;
"net.ipv4.conf.*.mc_forwarding" = 0;
"net.ipv4.conf.*.proxy_arp" = 0;
"net.ipv4.conf.*.rp_filter" = 1;
"net.ipv4.conf.*.send_redirects" = 0;
SettingValueRationale
accept_redirects0Prevents ICMP redirect poisoning (MitM attacks)
accept_source_route0Blocks source-routed packets (used to bypass firewalls)
bootp_relay0Disables BOOTP relay (not needed)
forwarding0Disables IP forwarding at the sysctl level (NAT is handled by nftables)
log_martians1Logs packets with impossible source addresses for forensic analysis
mc_forwarding0Disables multicast forwarding
proxy_arp0Prevents this host from answering ARP requests for other hosts
rp_filter1Strict reverse path filtering; drops packets with spoofed source addresses
send_redirects0Prevents sending ICMP redirects (host is not a router)

Why Both all and default?

conf.all applies to existing interfaces. conf.default applies to interfaces created after boot. Both must be set because container veth interfaces are created dynamically.

ICMP Hardening

nix
"net.ipv4.icmp_echo_ignore_all" = 1;
"net.ipv4.icmp_echo_ignore_broadcasts" = 1;
"net.ipv4.icmp_errors_use_inbound_ifaddr" = 0;
"net.ipv4.icmp_ignore_bogus_error_responses" = 1;
"net.ipv4.icmp_msgs_burst" = 10;
"net.ipv4.icmp_msgs_per_sec" = 10;
"net.ipv4.icmp_ratelimit" = 100;
"net.ipv4.icmp_ratemask" = 6168;
SettingValueEffect
icmp_echo_ignore_all1Host does not respond to ping; makes port scanning harder
icmp_echo_ignore_broadcasts1Ignores broadcast pings (Smurf attack mitigation)
icmp_errors_use_inbound_ifaddr0ICMP errors use primary address, not the interface the error arrived on
icmp_ignore_bogus_error_responses1Silently drops malformed ICMP error messages
icmp_msgs_burst / icmp_msgs_per_sec10Rate limits ICMP message generation to 10/sec with burst of 10
icmp_ratelimit100Rate limit in milliseconds between ICMP packets
icmp_ratemask6168Bitmask selecting which ICMP types are rate-limited

TCP Hardening

nix
"net.ipv4.tcp_sack" = 0;
"net.ipv4.tcp_dsack" = 0;
"net.ipv4.tcp_fack" = 0;
"net.ipv4.tcp_syncookies" = 1;
"net.ipv4.tcp_rfc1337" = 1;
"net.ipv4.tcp_timestamps" = 0;
SettingValueRationale
tcp_sack0Disables Selective ACK; SACK has had critical CVEs (e.g., SACK Panic CVE-2019-11477)
tcp_dsack0Disables Duplicate SACK (depends on SACK)
tcp_fack0Disables Forward ACK (depends on SACK)
tcp_syncookies1Enables SYN cookies to protect against SYN flood DoS
tcp_rfc13371Drops RST packets for TIME-WAIT sockets (TIME-WAIT assassination protection)
tcp_timestamps0Disables TCP timestamps; prevents uptime fingerprinting and side-channel leaks

Performance Trade-off

Disabling SACK reduces TCP performance on lossy or high-latency links. For a homelab on a local LAN with a Cloudflare Tunnel, this trade-off is acceptable. If you add WAN-facing services without Cloudflare, reconsider tcp_sack.

TCP Optimisation

nix
"net.ipv4.tcp_fastopen" = 3;
"net.ipv4.tcp_congestion_control" = "bbr";
"net.core.default_qdisc" = "cake";
SettingValueEffect
tcp_fastopen3Enables TCP Fast Open for both client and server connections (reduces latency)
tcp_congestion_controlbbrGoogle BBR congestion control; better throughput and lower latency than Cubic
default_qdisccakeCAKE queueing discipline; mitigates bufferbloat

Buffer Tuning

nix
"net.core.rmem_default" = 524288;      # 512 KB
"net.core.wmem_default" = 524288;      # 512 KB
"net.core.rmem_max" = 8388608;         # 8 MB
"net.core.wmem_max" = 8388608;         # 8 MB
"net.core.optmem_max" = 262144;        # 256 KB
"net.core.netdev_max_backlog" = 4096;

These are 4-8x the kernel defaults. Larger buffers help with bursty workloads (e.g., Immich photo uploads, Restic backup transfers) without requiring per-socket tuning.

Firewall

Defined in server/modules/network.nix:

nix
firewall = {
  enable = true;
  allowPing = false;
  allowedUDPPorts = [ 53 ];
  allowedTCPPorts = [ 53 80 443 ];
};

Only three services are reachable from the LAN:

PortServiceProtocol
53AdGuard Home (DNS)TCP + UDP
80Traefik (HTTP, redirects to 443)TCP
443Traefik (HTTPS)TCP

SSH (port 22) is also open via services.openssh.ports but is not listed in the firewall rules because NixOS automatically opens ports for enabled openssh service.

See also Networking & Firewall for the full network architecture.

Built with VitePress