Skip to content

bug(mesh): MASQUERADE applied to traffic between disjoint allowedLocationIPs CIDRs within same location #496

@Arsolitt

Description

@Arsolitt

Description

When a location has nodes with multiple disjoint allowedLocationIPs CIDRs (e.g., 192.168.102.0/23 and 10.10.0.0/16), traffic between those subnets within the same location is incorrectly MASQUERADEd.

Root cause

pkg/mesh/routes.go:405-408 creates per-CIDR POSTROUTING rules for same-location segments:

POSTROUTING -d 192.168.102.0/23 -j KILO-NAT
POSTROUTING -d 10.10.0.0/16     -j KILO-NAT

Traffic from 10.10.0.5 (inside the second CIDR) to 192.168.102.10 (inside the first CIDR) enters KILO-NAT. Since there is no RETURN rule for 192.168.102.10 (only for specific node IPs), it falls through to MASQUERADE. Both subnets are local to the same site, so this NAT is unnecessary and harmful.

The annotation is parsed via strings.Split(",") in backend.go:331, so multiple CIDRs per node are supported. filterAllowedLocationIPs deduplicates across locations but not within the same location, so disjoint CIDRs within one location survive.

Affected granularity modes

The code path runs in all granularity modes (the only condition is t.location == s.location), but in practice this is primarily relevant to cross-mesh granularity where allowed-location-ips is commonly used.

Steps to reproduce

  1. Deploy 2+ nodes in the same kilo.squat.ai/location
  2. Set different kilo.squat.ai/allowed-location-ips on each (e.g., 192.168.102.0/23 on node A, 10.10.0.0/16 on node B)
  3. Send traffic from a host on 10.10.0.0/16 to a host on 192.168.102.0/23
  4. Observe that the source IP is rewritten by MASQUERADE

Proposed fix

Exclude the union of all same-location allowedLocationIPs from the source match:

POSTROUTING -d 192.168.102.0/23 ! -s 192.168.102.0/23 ! -s 10.10.0.0/16 -j KILO-NAT
POSTROUTING -d 10.10.0.0/16     ! -s 192.168.102.0/23 ! -s 10.10.0.0/16 -j KILO-NAT

Alternatively, use an ipset containing all same-location CIDRs for cleaner matching at scale.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions