Skip to content

Declarative NFTables config documents #12383

Description

@kbaegis

Feature Request: Declarative NAT/Masquerade Configuration

Why (Use Case)

Edge/Gateway Deployments: Talos nodes deployed at the network edge need to perform NAT/masquerade for internal subnets to reach the internet. This is a fundamental networking requirement for:

  1. Home lab edge routers - Talos node with dual-homed NICs (internal LAN + ISP uplink)
  2. Branch office gateways - Kubernetes at the edge providing NAT for local networks
  3. Air-gapped environments - Controlled egress through a Talos gateway node

Why This Matters

Talos is uniquely positioned for edge deployments. Its immutable, API-driven design makes it ideal for remote locations where physical access is limited. However, edge nodes frequently serve as network gateways - not just Kubernetes workers. Without declarative NAT support, operators must choose between:

  1. Abandoning Talos at the edge - Using a traditional Linux distro for the gateway role, fragmenting infrastructure management
  2. Security compromises - Running privileged containers that bypass Talos's security model
  3. Operational fragility - Relying on workarounds that break on reboot, upgrade, or network changes

The gap: Talos already has the internal machinery (NfTablesChains, NfTablesRule with matchOIfName, matchSourceAddress). The API reference documents these structures. What's missing is a user-facing configuration document to expose NAT chain types and the masquerade verdict.

Scope alignment: This isn't asking Talos to become a full router OS. It's requesting exposure of a single nftables primitive (masquerade) that the kernel and Talos internals already support. The Ingress Firewall proves Talos is willing to expose nftables functionality declaratively - this extends that pattern to a complementary use case.

Current Workaround: Deploying a privileged pod that runs iptables/nft commands:

machine.pods:
  - apiVersion: v1
    kind: Pod
    spec:
      containers:
      - command: ["/bin/sh"]
        args: ["-c", "apk add iptables && iptables -t nat -A POSTROUTING -o <nic> -j MASQUERADE"]
        securityContext:
          privileged: true
      hostNetwork: true

Problems with current approach:

  • Requires privileged container (security risk)
  • External image dependency at boot time
  • Race condition with network availability
  • Not declarative/idempotent
  • Bypasses Talos configuration management

How (Proposed Machine Config Document)

Introduce a new document type NATRuleConfig:

apiVersion: v1alpha1
kind: NATRuleConfig
name: masquerade-to-isp
spec:
  type: masquerade          # masquerade | snat
  sourceAddress:
    includeSubnets:
      - <CIDR>       # Internal network to NAT
  outputInterface:
    interfaceNames:
      - <nic>            # Egress interface
  # Optional for SNAT:
  # snatAddress: 203.0.113.1

Implementation Plan

1. nftables Mapping

The config would generate:

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 172.21.0.0/16 oif "<nic>" masquerade
  }
}

Key nftables elements:

Config Field nftables Mapping
type: masquerade masquerade verdict
type: snat snat to <address>
sourceAddress.includeSubnets ip saddr <cidr>
outputInterface.interfaceNames oif "<interface>"

2. Priority Selection

Hook Priority Keyword Numeric Purpose
postrouting srcnat 100 Source NAT / Masquerade
prerouting dstnat -100 Destination NAT (future)

Use standard Linux netfilter priorities. The srcnat priority (100) is the canonical location for SNAT/masquerade operations.

3. Relationship to Ingress Firewall

Aspect Ingress Firewall Proposed NAT
Hook input, prerouting postrouting
Chain type filter nat
Purpose Block/allow incoming Transform outgoing
Priority -140, -110 100

No conflict - different hooks and chain types.

4. Controller Implementation

Extend NfTablesChainConfigController to:

  1. Parse new NATRuleConfig documents
  2. Generate NfTablesChains resources with:
    • type: nat
    • hook: postrouting
    • priority: srcnat (100)
    • Rules with verdict: masquerade or SNAT action

Test Plan

  1. Unit Tests:

    • Config parsing and validation
    • nftables rule generation
  2. Integration Tests:

    • Apply config, verify talosctl get nftableschain shows NAT chain
    • Verify nft list ruleset shows correct rules
    • Traffic test: internal host → external destination with tcpdump showing masqueraded source
  3. Edge Cases:

    • Interface not present at boot (deferred rule application)
    • Multiple NAT rules (different subnets/interfaces)
    • Config update/removal (clean teardown)

Additional Considerations

  1. DNAT Support: Future extension for port forwarding (hook: prerouting, priority: dstnat)

  2. IPv6: Initial implementation IPv4 only (ip family). IPv6 NAT rare but could be added later.

  3. Conntrack: NAT requires conntrack - verify kernel config includes CONFIG_NF_CONNTRACK and CONFIG_NF_NAT.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions