Skip to content

feat(api): accept IPv6 in api_allow_from + dual-stack bind (#243) - #246

Merged
VijitSingh97 merged 1 commit into
developfrom
claude/ipv6-api-allow-243
Jul 12, 2026
Merged

VijitSingh97 merged 1 commit into
developfrom
claude/ipv6-api-allow-243

Conversation

@VijitSingh97

Copy link
Copy Markdown
Contributor

Closes #243. Surfaced enabling the control path (#236) on the fleet: the stack resolves to IPv6 only while the rig APIs bind IPv4, so api_allow_from (IPv4-only) couldn't pin the writable path to the stack and fell back to a LAN /24.

  • parse_config: accepts an IPv6 address/CIDR (hex+colons charset + ≥2 colons + 0–128 prefix — the charset is the injection guard, matching the IPv4 octet check) and sets API_ALLOW_FAMILY (ip|ip6).
  • install_api_firewall: renders ip6 saddr vs ip saddr per family (the inet rigforge table already carries both).
  • api-server.py + control-server.py: bind AF_INET6 dual-stack (IPV6_V6ONLY=0) when the bind is a v6 address, so api_bind/control_bind = :: actually serves both families.

Tests: IPv4+IPv6 parse & family, malformed rejects (bad prefix, non-hex, hostname, and two shell/nft-injection attempts incl. "fd00::/64 accept; drop"), and ip6 saddr rendering — 19 assertions. IPv6 bind smoke-verified on ::1. Docs updated. Local gate: 1239 / 0, lint + lint-md green.

(No fleet action needed — the rigs stay on the LAN /24 scope; this just makes a tighter v6 pin possible.)

@VijitSingh97
VijitSingh97 enabled auto-merge (squash) July 12, 2026 01:37
@VijitSingh97
VijitSingh97 force-pushed the claude/ipv6-api-allow-243 branch from a753236 to 33201fb Compare July 12, 2026 01:37
On an IPv6-primary LAN the stack (pithead-prod/gouda) resolves to IPv6
only, while the rig APIs bind IPv4 — so enabling the control path (#236)
couldn't pin api_allow_from to the stack and fell back to a broad LAN
/24. Now:
- parse_config accepts an IPv6 address/CIDR (charset+colon+prefix guard,
  same injection-safety posture as the IPv4 octet check) and sets
  API_ALLOW_FAMILY=ip|ip6.
- install_api_firewall renders  vs 74.244.47.217 per family in
  the dual-family inet table.
- api-server.py + control-server.py bind AF_INET6 (dual-stack via
  IPV6_V6ONLY=0) when the bind address is v6, so :: actually serves.

19 new assertions (IPv4+IPv6 parse + families, malformed/injection
rejects, ip6 saddr rendering); IPv6 bind smoke-verified on ::1. Docs
updated. 1239 passed / 0 failed, lint + lint-md green.

Closes #243

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@VijitSingh97
VijitSingh97 force-pushed the claude/ipv6-api-allow-243 branch from 33201fb to 5d71174 Compare July 12, 2026 01:38
@VijitSingh97
VijitSingh97 merged commit f21846c into develop Jul 12, 2026
9 checks passed
@VijitSingh97
VijitSingh97 deleted the claude/ipv6-api-allow-243 branch July 12, 2026 01:41
VijitSingh97 added a commit that referenced this pull request Jul 13, 2026
On an IPv6-primary LAN the stack (pithead-prod/gouda) resolves to IPv6
only, while the rig APIs bind IPv4 — so enabling the control path (#236)
couldn't pin api_allow_from to the stack and fell back to a broad LAN
/24. Now:
- parse_config accepts an IPv6 address/CIDR (charset+colon+prefix guard,
  same injection-safety posture as the IPv4 octet check) and sets
  API_ALLOW_FAMILY=ip|ip6.
- install_api_firewall renders  vs 74.244.47.217 per family in
  the dual-family inet table.
- api-server.py + control-server.py bind AF_INET6 (dual-stack via
  IPV6_V6ONLY=0) when the bind address is v6, so :: actually serves.

19 new assertions (IPv4+IPv6 parse + families, malformed/injection
rejects, ip6 saddr rendering); IPv6 bind smoke-verified on ::1. Docs
updated. 1239 passed / 0 failed, lint + lint-md green.

Closes #243

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

api_allow_from / api_bind are IPv4-only — can't tightly scope the APIs on an IPv6-primary LAN (control path #236)

1 participant