Skip to content

kernel: enable nftables NAT, masquerade and reject - #134

Open
shunnag wants to merge 1 commit into
commaai:masterfrom
shunnag:kernel-nat-config
Open

shunnag wants to merge 1 commit into
commaai:masterfrom
shunnag:kernel-nat-config

Conversation

@shunnag

@shunnag shunnag commented Sep 27, 2026

Copy link
Copy Markdown

Enable CONFIG_NF_NAT, CONFIG_NFT_NAT, CONFIG_NFT_MASQ and CONFIG_NFT_REJECT, so the Wi-Fi hotspot can NAT its clients with nftables.

Why

  • The kernel has nf_tables and conntrack, but NF_NAT, NFT_NAT and NFT_REJECT are not set, and NFT_MASQ needs NF_NAT. So NetworkManager's shared mode (ipv4.method=shared) gives hotspot clients an address but no NAT (see Testing).
  • NM's shared-mode table on the device also has reject rules next to masquerade, so I enabled NFT_REJECT too. I did not test a build with NAT but without NFT_REJECT.
  • These four options also turn on NF_NAT_MASQUERADE, NFT_REJECT_INET/IPV4/IPV6 and NF_REJECT_IPV4/IPV6. Nothing else in the netfilter config changes.
  • Legacy iptables is not a way around this. iptables-legacy is installed, but the ip_tables module is not in the image, so iptables-legacy -t nat -L fails with "Table does not exist".

Testing
comma four, liberation-day-7.2 kernel (7.2.0-vamos-7626c37) with local ath10k-only debug patches (different versions in Before and After; neither touches netfilter). "Before" is the released config. "After" adds these four options (and ATH10K_DEBUG); /proc/config.gz on the device shows NF_NAT=y, NFT_MASQ=y and NFT_REJECT=y. The netfilter lines of vamos.config and the kernel source commit are the same on master.

  • Before: an NM shared-mode hotspot came up and an iPhone got a DHCP lease, but the nft ruleset had no nm-shared-* table.
  • After, hand-written rule: wpa_supplicant AP on wlan0, an nft masquerade rule for oifname "usb0", and ip_forward=1. An iPhone (mobile data off) on the AP loaded a page from a test HTTP server on my Mac, which is connected over USB (usb0). The Mac saw the request coming from the device's usb0 address, 192.168.42.2.
  • After, NM shared mode (a wpa-psk profile set up like openpilot's hotspot): NM created nm-shared-wlan0 with the masquerade and reject rules. Traffic passed only after I also enabled forwarding on usb0 (see below).

Not covered: forwarding on the upstream interface
This PR only adds the kernel options. Even with them, the hotspot also needs forwarding on the upstream interface, and NM didn't turn it on for an upstream it doesn't manage:

  • Tested on the device (usb0 as the upstream): with NM shared mode up, only net.ipv4.conf.wlan0.forwarding was 1. net.ipv4.ip_forward and net.ipv4.conf.usb0.forwarding stayed 0, and nmcli shows usb0 as unmanaged. Replies coming back in on usb0 were dropped (InAddrErrors went from 77 to 132 during one page reload) until I set net.ipv4.conf.usb0.forwarding=1 by hand.
  • LTE, not tested on a device (my device has no LTE data): on liberation-day-7.2, ModemManager was dropped and LTE is ppp0, brought up by openpilot's modem.py with pppd. From reading the code, NM doesn't manage ppp0 either, so I expect the same problem when the hotspot shares LTE. On master, LTE still goes through ModemManager, so it may behave differently there.
  • Fixing this is a userspace change (for example, whatever brings up the hotspot also enables forwarding on the upstream interface). It is not part of this PR.

Note: I worked through this together with Claude (AI). English is hard for me, so the English was written with AI help, but I ran the device tests myself on my comma four, and the results above come from those runs.

The kernel has nf_tables and conntrack but no NAT: NF_NAT, NFT_NAT and
NFT_REJECT are not set, and NFT_MASQ is not available without NF_NAT.
On a comma four with this config, NetworkManager's shared mode gave a
hotspot client a DHCP lease, but no nm-shared table was created.

Enable NF_NAT, NFT_NAT, NFT_MASQ and NFT_REJECT. NFT_REJECT is included
because the nm-shared-wlan0 table that NetworkManager created on the
device has reject rules next to the masquerade rule. This also turns on
NF_NAT_MASQUERADE, NFT_REJECT_INET/IPV4/IPV6 and NF_REJECT_IPV4/IPV6.
@github-actions

Copy link
Copy Markdown

vamOS System Profile

Changes vs master

Metric Change
Used space 3438.4MB → 3439.8MB (+1.4MB)
Sparse image 3392.5MB → 3394.0MB (+1.5MB)
Package count 526 → 526

Added packages: cmake-4.2.2_3, dhcpcd-10.3.2_2, expat-2.8.4_1, expat-devel-2.8.4_1, jsoncpp-1.9.8_1, libharfbuzz-14.4.0_1, python3-3.14.7_1, python3-Mako-1.4.1_1, python3-Pygments-2.21.0_1, texinfo-7.3_2, vim-9.2.1031_1, vim-common-9.2.1031_1, xxd-9.2.1031_1

Removed packages: cmake-4.2.2_2, dhcpcd-10.3.2_1, expat-2.8.3_1, expat-devel-2.8.3_1, jsoncpp-1.9.6_1, libharfbuzz-14.3.1_1, python3-3.14.6_1, python3-Mako-1.3.2_3, python3-Pygments-2.20.0_1, texinfo-7.3_1, vim-9.2.0506_1, vim-common-9.2.0506_1, xxd-9.2.0506_1

Directory size changes (>1MB)
Directory Change

Metric Value
Used space 3439.8MB / 5959.5MB
Files 56307
Directories 4774
Symlinks 3602
Packages 526

Top 10 Directories

Directory Size

Category Breakdown

Category Size %
xbps packages 2516.5MB 73.1%
Python venv 591.8MB 17.2%
Firmware 11.2MB .3%
Other 320.2MB 9.3%

Top 10 Packages by Size

Package Size
mit-krb5-libs-1.21.3_1 270.4MB
gawk-5.3.2_1 210.3MB
llvm-21_3 148.6MB
libldns-1.9.2_1 124.3MB
pd-mapper-1.0_1 74MB
libclang21-21.1.7_1 70.2MB
glib-2.88.0_1 67.4MB
gcc-14.2.1+20250405_4 66.6MB
libcap-progs-2.78_1 56MB
cmake-4.2.2_3 53.2MB

Top 30 Files by Size

File Size
/usr/lib/llvm/21/lib/libLLVM.so.21.1 124.3MB
/usr/lib/llvm/21/lib/libMLIR.so.21.1 89.7MB
/usr/lib/llvm/21/bin/mlir-transform-opt 82.9MB
/usr/lib/llvm/21/lib/libclang-cpp.so.21.1 56MB
/usr/lib/llvm/21/bin/mlir-translate 53.2MB
/usr/lib/llvm/21/bin/llvm-exegesis 52MB
/usr/lib/llvm/21/bin/llvm-bolt-binary-analysis 50.6MB
/usr/bin/uv 41.6MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/gnat1 40.1MB
/usr/bin/gdb 39.1MB
/usr/lib/libgallium-26.1.8.so 37.7MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/cc1plus 37.3MB
/usr/lib/libllvm-qcom.so 35.2MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/cc1 35.2MB
/usr/lib/libRusticlOpenCL.so.1.0.0 34.4MB
/usr/lib/gcc/aarch64-linux-gnu/14.2/lto1 33.9MB
/usr/bin/lto-dump 33.9MB
/usr/local/venv/bin/ruff 31.8MB
/usr/share/icu/78.3/icudt78l.dat 31.5MB
/usr/lib/llvm/21/lib/libclang.so.21.1.7 30.2MB
/usr/lib/libz3.so 28.8MB
/usr/lib/llvm/21/bin/c-index-test 28.6MB
/usr/local/venv/lib/python3.12/site-packages/gcc_arm_none_eabi/toolchain/libexec/gcc/arm-none-eabi/13.2.1/cc1 28.2MB
/usr/bin/run 26.7MB
/usr/local/venv/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-71e1b124.so 23.6MB
/usr/comma/updater 23.5MB
/usr/comma/setup 23.5MB
/usr/comma/reset 23.5MB
/usr/local/uv/python/cpython-3.12.14-linux-aarch64-gnu/bin/python3.12 22.1MB
/usr/local/uv/python/cpython-3.12.14-linux-aarch64-gnu/lib/libpython3.12.so.1.0 22MB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant