[Bug]: kernel configs build an nft-only kernel on linux-6.18.5 (NETFILTER_XTABLES_LEGACY unset), legacy iptables tables disappear
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- linux
- Domain
- build-system, operating-systems
Research direction
Start with kernel/config-arm64 and kernel/Makefile, then compare the generated configuration against the linux-6.18.5 Netfilter Kconfig symbols. Run the reported arm64 olddefconfig command and inspect the legacy and nftables settings with grep. Done means the selected backend is reflected consistently in the config and the reported legacy-table reproduction no longer contradicts that choice.
Written by the indexing model from the issue text.
Description
I have done the following
- I have searched the existing issues
- If possible, I've reproduced the issue using the 'main' branch of this project
Steps to reproduce
- Build the kernel from
mainaskernel/Makefiledoes (KSOURCEis linux-6.18.5):cp kernel/config-arm64 .config && make ARCH=arm64 olddefconfig && make ARCH=arm64 Image. - Boot it and try the legacy tables:
container run --rm --kernel ./Image --cap-add NET_ADMIN alpine:3.20 sh -c \
'apk add -q iptables iptables-legacy; iptables-legacy -t nat -L -n; iptables-legacy -t mangle -L -n'
Current behavior
iptables v1.8.10 (legacy): can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
iptables v1.8.10 (legacy): can't initialize iptables table `mangle': Table does not exist (do you need to insmod?)
iptables-nft works on the same kernel, and both work on the default 6.12.28 kernel.
Cause: the file was generated on 6.1.68 and still carries CONFIG_IP_NF_IPTABLES=y, CONFIG_IP_NF_NAT=y, CONFIG_IP_NF_MANGLE=y, CONFIG_IP_NF_FILTER=y. Newer kernels gate the legacy tables behind CONFIG_NETFILTER_XTABLES_LEGACY (net/netfilter/Kconfig, a bare bool that defaults off); CONFIG_IP_NF_IPTABLES_LEGACY and CONFIG_IP6_NF_IPTABLES_LEGACY depend on it, and IP_NF_NAT, IP_NF_MANGLE and IP_NF_FILTER depend on IP_NF_IPTABLES_LEGACY. The file predates those symbols, so on 6.18.5 olddefconfig leaves them unset and the legacy filter, nat and mangle tables silently drop out while the =y lines stay in the file:
$ make ARCH=arm64 olddefconfig; grep -E "XTABLES_LEGACY|IP_NF_IPTABLES" .config
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP6_NF_IPTABLES=y
# CONFIG_NETFILTER_XTABLES_LEGACY is not set
Effect on Kubernetes node images: apple/container#2120 already shows the two iptables backends are not interchangeable in kindest/node (there node prep calls iptables-nft and fails because the default kernel has no nf_tables). An nft-only kernel inverts it: kind's entrypoint selects the node's backend by counting existing rules and sends a 0-0 tie to legacy, so /usr/sbin/iptables inside the node answers "Table does not exist" and the container k8s node-prep rules cannot apply. kube-proxy itself keeps working because its image carries its own wrapper and picks nft (checked on a Cilium cluster on this kernel: ClusterIP and DNS answer); node-level tools that shell out to iptables-legacy are what break.
Expected behavior
Either the legacy tables the file still lists come back (CONFIG_NETFILTER_XTABLES_LEGACY=y, CONFIG_IP_NF_IPTABLES_LEGACY=y, CONFIG_IP6_NF_IPTABLES_LEGACY=y, which makes the existing IP_NF_* lines take effect again), or the kernel is documented as nft-only and the stale IP_NF_NAT/IP_NF_MANGLE/IP_NF_FILTER lines are removed so the file matches what it builds. Happy to send the PR for whichever you prefer.
Environment
- OS: macOS 26.2 (25C56), Apple silicon
- Xcode / Swift: not involved (kernel build in an ubuntu:24.04 container with gcc 13.3; the Kconfig defaults are toolchain-independent, but I have not run the in-tree
kernel/imagepath) - Container: container CLI version 1.0.0 (build: release, commit: ee848e3)
- containerization:
kernel/config-arm64atmain(sha256 dedb03de...), linux-6.18.5
Relevant log output
Found while measuring the config change proposed in #912.
Code of Conduct
- I agree to follow this project's Code of Conduct
- Dominant language
- Swift
- Stars
- 8.9k
- Forks
- 360
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 16
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apple/containerization
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apple/containerization#819 · 1 comment · 1 reaction ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apple/containerization#818 · 2 comments ·
-
LinuxContainer.create() leaks the VZ VM/XPC process when vm.start() throws — no do/catch around it Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apple/containerization#804 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
apple/containerization#921 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
apple/containerization#912 ·
All issues in apple/containerization
Similar issues
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
type: docs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
googleapis/google-cloud-swift#971 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
bitcoindevkit/bdk-ffi#1125 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
mozilla-mobile/firefox-ios#35743 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
manaflow-ai/cmux#13417 ·