Skip to main content
Open Source Open Source

NAT464 Sidecar: Bridging IPv4 and IPv6 in Kubernetes

Impact Summary

Built a zero-dependency Rust sidecar that transparently bridges IPv4 and IPv6 traffic in Kubernetes pods, enabling organizations to run legacy workloads on modern IPv6-only infrastructure without any application changes.

Role

Creator & Maintainer

Timeline

2026-Present

Scale

  • IPv6-only cluster compatible
  • Zero application changes required
  • Production security hardened

Links

Problem

As organizations migrate to IPv6-only Kubernetes clusters to simplify network architecture and reduce IPv4 address costs, they face a significant challenge: legacy applications that only speak IPv4. These applications, whether third-party binaries, older services, or dependencies that can’t be easily modified, become stranded when the underlying infrastructure no longer provides IPv4 connectivity.

The traditional solutions are problematic. Running dual-stack clusters adds operational complexity and defeats the purpose of IPv6 migration. Modifying applications to support IPv6 is often impossible when dealing with vendor software or legacy codebases. Cloud provider NAT64 gateways work for outbound traffic but don’t solve inbound connectivity to IPv4-only pods.

I needed a solution that would be completely transparent to the application: no code changes, no configuration updates, no awareness of IPv6 at all. The application should believe it’s operating in a normal IPv4 environment while the cluster runs pure IPv6.

Approach

I designed nat464-sidecar as a Kubernetes sidecar container that shares the network namespace with the application pod. This positioning is crucial. By operating in the same network namespace, the sidecar can intercept and translate traffic without requiring any kernel modifications or privileged capabilities.

The architecture handles bidirectional translation. For inbound traffic, the sidecar listens on an IPv6 address (the pod’s actual cluster IP) and forwards connections to the application on localhost over IPv4. From the application’s perspective, all requests arrive on 127.0.0.1. For outbound traffic, the sidecar provides a SOCKS5 proxy on localhost. When the application needs to reach external services, it connects through this proxy, and the sidecar handles DNS resolution and connection establishment over IPv6.

NAT464 sidecar bidirectional IPv4/IPv6 translation

Key Design Elements

  • Happy Eyeballs v3 implementation: The outbound proxy implements RFC 8305 connection racing, interleaving IPv6 and IPv4 addresses and staggering connection attempts. This ensures optimal latency when destinations support both address families through NAT64.
  • Address synthesis using Well-Known Prefix: IPv4-only destinations are synthesized into IPv6 using the 64:ff9b::/96 prefix (RFC 6052), enabling connectivity through standard NAT64 gateways.
  • Zero-privilege security model: The sidecar runs as non-root with no special capabilities. This was a deliberate constraint. I wanted something that platform teams could approve without security review escalations.
  • Distroless container image: Built on a minimal base with read-only root filesystem, reducing attack surface and meeting enterprise container security requirements.

I chose Rust for this project because the sidecar sits in the critical path of all application traffic. Memory safety bugs in a network proxy can have severe security implications, and Rust’s ownership model eliminates entire classes of vulnerabilities while maintaining the performance characteristics needed for transparent proxying.

Outcomes

  • Transparent IPv4-to-IPv6 migration path: Applications can run unmodified on IPv6-only clusters, removing the primary blocker for infrastructure modernization
  • Simplified cluster networking: Eliminates the need for dual-stack configuration and the associated complexity of managing two address families
  • Security-first deployment model: Requires no privileged capabilities, making it suitable for security-conscious environments and multi-tenant clusters

Key Contributions

  • Designed the bidirectional NAT464 architecture that operates entirely in userspace within a shared pod network namespace
  • Implemented Happy Eyeballs v3 connection racing algorithm with configurable delays for DNS resolution and connection attempts
  • Built a standards-compliant SOCKS5 proxy supporting the CONNECT command with hostname resolution
  • Created address synthesis logic using the Well-Known Prefix for NAT64 compatibility
  • Developed Kubernetes-native health endpoints for liveness, readiness, and startup probes
  • Packaged as a minimal distroless container with comprehensive security hardening

What I Learned

The hardest part of writing a network proxy in Rust wasn’t the networking — it was the async lifetime management. Tokio’s task model is excellent, but when you’re holding mutable state across bidirectional proxy connections while also managing connection pools and cooldowns, you end up in situations where the borrow checker is telling you something real about your design. Several times I thought I had a concurrency bug and it turned out I had a design flaw that the borrow checker was accurately diagnosing.

Happy Eyeballs v3 looks simple in the RFC — interleave IPv6 and IPv4 attempts, prefer the faster response. Implementing it correctly with proper cancellation when one connection wins was genuinely tricky. The hard part is cleaning up the losing connections without introducing delays that defeat the purpose of racing them in the first place. I ended up with more cancellation logic than connection logic.

The zero-privilege constraint turned out to be the right forcing function. By deciding early that the sidecar would run without NET_ADMIN or any privileged capabilities, I had to make the userspace proxy approach work rather than reaching for the easier kernel-level solutions. The result is something platform teams can actually deploy in security-conscious environments, which is the whole point. Constraints that feel limiting early on often produce better architecture than unlimited flexibility.

Key Takeaways

  • Enables legacy IPv4 applications to run on IPv6-only infrastructure
  • Eliminates need for dual-stack networking complexity
  • Requires no NET_ADMIN or privileged capabilities

This write-up was co-authored with AI, based on the author's working sessions and notes.

Explore the source

fakoli/nat464-sidecar

Star it, fork it, or open an issue — contributions and feedback welcome.

Related Projects