NAT-APP46: Building a Real-Time Stateless IPv4-to-IPv6 Protocol Engine
A technical walkthrough of how APP46 performs real-time stateless IPv4-to-IPv6 translation at the client, covering RFC 7915/6052 compliance, address mapping, TCP session handling, and the engineering decisions behind a protocol engine that runs transparently as a Windows service.
Most IPv4-to-IPv6 translation solutions operate at the network boundary — NAT64 gateways, DNS64 resolvers, stateful translators sitting between network segments. They handle the problem at the infrastructure level, and they work well for traffic that originates on the IPv6 side and needs to reach IPv4 resources.
But there's a harder problem that boundary solutions don't address: what happens when an IPv4-only client application needs to send traffic outbound through an IPv6-only tunnel?
This is the problem APP46 was built to solve. Not at the network boundary. Not on the server. At the client, in real time, as a stateless protocol engine running inside a Windows service. This post is a technical walkthrough of how that engine works, the standards it implements, and the engineering decisions that shaped it.
The Gap That Boundary Solutions Leave Open
In a modern enterprise remote access deployment, VPN tunnels often carry IPv6 traffic exclusively. This is by design — IPv6 provides the addressing model that makes large-scale tunnel deployments manageable. Server-side infrastructure like NAT64 and DNS64 handles the reverse path: when IPv6 traffic arrives at the corporate network and needs to reach an IPv4 resource, these gateways translate it.
The problem surfaces on the client side. A remote user launches a legacy line-of-business application — something built years ago, compiled against IPv4 socket APIs, with no IPv6 awareness in its network stack. That application opens a socket, resolves a hostname to an IPv4 address, and attempts to connect. The IPv4 packet hits the local network stack and has nowhere to go. The IPv6 VPN tunnel won't carry it. The application fails silently, or times out, or throws a connection error that means nothing to the end user.
IT gets a ticket. The user can't work. And the root cause isn't a misconfiguration or an outage — it's a fundamental protocol mismatch between what the application speaks and what the tunnel carries.
Server-side translation can't help here because the packet never reaches the server. It dies on the client. The translation has to happen before the packet enters the tunnel — which means it has to happen on the client itself.
Why Stateless Translation Was the Right Architecture
When we designed the APP46 protocol engine, the first and most consequential decision was whether to build a stateful or stateless translator.
A stateful translator (like NAT64 as defined in RFC 6146) maintains a session table. For every active connection, the translator tracks the mapping between the original IPv4 addresses/ports and the translated IPv6 addresses/ports. This session state must be created, maintained, and eventually expired. It consumes memory. It introduces failure modes — if the translator restarts, all session state is lost and active connections break. And it creates a single point of serialization: every packet in both directions must be matched against the session table.
For a client-side translator running as a Windows service on thousands of remote laptops, stateful translation would have been the wrong choice. These machines sleep, hibernate, lose connectivity, switch networks, and resume — often mid-session. A session table that can be invalidated by a laptop lid closing is a liability, not an asset.
APP46 implements stateless translation as described in RFC 7915 (IP/ICMP Translation Algorithm) with address mapping following RFC 6052 (IPv6 Addressing of IPv4/IPv6 Translators). In a stateless model, each packet is translated independently based on a deterministic address mapping. There is no session table. There is no per-connection state. The mapping between an IPv4 address and its corresponding IPv6 address is fixed and configured — and that mapping is all the translator needs to process any packet in either direction.
The practical consequence: if the APP46 service restarts, or the machine wakes from sleep, or the network path changes, translation resumes immediately. There is no session table to rebuild, no timeout to wait for, no stale state to reconcile. The engine picks up where it left off because there was nothing to remember in the first place.
Address Mapping: The Core of the Engine
The APP46 protocol engine is built around a 1:1 address mapping model. For each configured application, the mapping defines three things: the client application's executable path and identity, the TCP ports the application uses, and a local IPv4 address (typically a loopback or a reserved address) that maps to the server's IPv6 address.
Here's how it works at the packet level. The APP46 client service binds a local IPv4 address on behalf of each configured server resource. When the client application connects to that local IPv4 address on the configured port, the APP46 engine intercepts the outbound packet, strips the IPv4 header, constructs a new IPv6 header with the mapped destination address derived from the RFC 6052 mapping, and forwards the translated packet into the IPv6 network stack — where it enters the VPN tunnel like any other IPv6 packet.
On the return path, the inverse happens. IPv6 packets arriving from the server hit the APP46 engine, which recognizes the source address as belonging to a configured mapping, translates it back to the corresponding local IPv4 address, and delivers the packet to the client application's socket. The application never sees IPv6. It believes it's communicating with a local IPv4 endpoint.
This 1:1 model is deliberately simple. There is no port remapping, no address pooling, no overloaded NAT behavior. One IPv4 address maps to exactly one IPv6 address, and the mapping is fully reversible. This eliminates an entire class of translation ambiguities and makes the engine's behavior completely predictable — which matters when you're debugging a connectivity issue on a remote laptop at 2 AM.
TCP Session Handling Without Session State
This is where it gets nuanced. APP46 is a stateless translator — it does not maintain per-connection session state. But TCP is inherently a stateful protocol: it has SYN, SYN-ACK, established, FIN, RST states. How does a stateless translator handle a stateful protocol?
The answer is that APP46 doesn't need to track TCP state to translate TCP packets. The translation operation is purely at the IP layer: replace the IPv4 header with an IPv6 header (or vice versa), update the pseudo-header checksum, and forward. The TCP state machine runs entirely between the two endpoints — the client application and the remote server. APP46 sits below that conversation, translating the carrier (IP) without interpreting the cargo (TCP).
This means TCP handshakes, window scaling, retransmissions, keepalives, and connection teardown all pass through the translator unmodified. The SYN goes out as an IPv6 packet. The SYN-ACK comes back and gets translated to IPv4. The client application's TCP stack sees a normal handshake and proceeds. APP46 never needs to know whether the connection is in ESTABLISHED or TIME_WAIT — it just translates headers.
FQDN Interception and Name Resolution
In earlier versions of APP46, server resources were identified by short hostnames — NetBIOS-style names that the application would resolve locally. Version 6.0 introduced full FQDN interception, which significantly broadened the range of applications APP46 can handle.
Here's why this matters. Many modern applications — even legacy ones — resolve servers using fully qualified domain names. An application might connect to appserver.corp.contoso.com rather than just appserver. If the translator only intercepts short name resolution, those FQDN-based lookups slip past and resolve to an IPv4 address that can't be routed through the IPv6 tunnel.
With FQDN interception, the APP46 engine hooks into the name resolution path and intercepts DNS lookups for configured server FQDNs. When the application resolves a configured FQDN, APP46 returns the local IPv4 address that maps to that server's IPv6 address. The application connects to that local address, and translation proceeds normally. The application is unaware that anything happened — it resolved a name, got an IP address, and connected. The fact that the address it received is a local translation endpoint rather than the actual server address is invisible to it.
Running as a Windows Service: Architectural Constraints
APP46 runs as a native Windows service — not a driver, not a filter, not a user-mode proxy that requires the user to configure application settings. This was a deliberate architectural choice driven by deployment reality.
The target environment for APP46 is enterprise-managed Windows machines deployed to hundreds or thousands of remote users. These machines are managed through Active Directory Group Policy. Users don't have administrative privileges. IT needs to deploy, configure, and update the translation engine without touching each machine individually and without requiring user interaction.
A Windows service meets all of these requirements. It starts automatically at boot, runs under a service account with appropriate privileges, survives user logon/logoff cycles, and can be deployed and configured entirely through GPO using the administrative templates (ADMX/ADML) that ship with APP46. The MSI installers support silent installation, so deployment can happen through SCCM, Intune, or any other software distribution mechanism the organization already uses.
Running as a service also means the translation engine is active before the user logs on. For VPN deployments where the tunnel establishes at machine startup (device tunnel scenarios), APP46 is already running and ready to translate by the time the user opens an application.
Intelligent Auto-Sensing: Knowing When to Translate
Translation should only happen when it needs to. If the user is sitting in the office, connected directly to the corporate LAN, their IPv4 applications can reach servers natively — no translation required. If they're on an alternate VPN that carries IPv4 traffic, translation is also unnecessary. APP46 should only activate when the IPv6 VPN tunnel is the active network path.
The APP46 engine handles this through a configurable auto-sensing mechanism. At a configurable polling interval, the engine tests connectivity to internal network resources using one or more verification methods: HTTP requests to an internal URL, ICMP ping to an internal host, or Network Location Server (NLS) checks. If the internal resources are directly reachable, the engine concludes the machine is on the corporate LAN (or on a VPN that provides direct IPv4 access) and disables translation. If the resources are unreachable via direct IPv4 but the IPv6 VPN tunnel is active, the engine enables translation.
This auto-sensing runs continuously in the background. When a user disconnects from the office network, drives home, and the VPN tunnel activates, APP46 detects the change and enables translation — no manual intervention, no notification, no user awareness required. When they return to the office the next morning, the reverse happens automatically.
Best practice for configuring auto-sensing: use diverse verification targets with fully qualified domain names. A single verification target creates a single point of failure in detection. Multiple targets with different network paths provide resilient detection that handles partial network outages correctly.
Centralized Configuration Management
Every aspect of the APP46 translation engine — application definitions, address mappings, port configurations, auto-sensing parameters, polling intervals — is managed through the APP46 Configuration Server. This is a server-side GUI application that serves as the single point of configuration for all APP46 clients in the environment.
The operational model is straightforward. An administrator adds or modifies a configuration in the Configuration Server. On each APP46 client's next check-in (which happens at service startup and at configurable intervals thereafter), the client pulls the updated configuration and applies it. There is no push mechanism — clients poll for changes. This was a deliberate design choice: polling is more resilient to network interruptions, doesn't require inbound connectivity to client machines, and works naturally with machines that come online and offline unpredictably.
The configuration itself can also be defined as an XML file for environments that prefer file-based configuration management or need to integrate with existing configuration pipelines. The service consumes either the server-provided configuration or the local XML — giving IT teams flexibility in how they manage the deployment.
The Result
The APP46 protocol engine is intentionally narrow in scope and deep in execution. It does one thing — stateless IPv4-to-IPv6 translation at the client — and it does it in a way that is transparent to applications, transparent to users, deployable at enterprise scale through standard Windows management tools, and resilient to the realities of how remote laptops actually behave in the field.
For organizations running VPN infrastructure with IPv6 tunnels and a portfolio of legacy IPv4 applications, APP46 eliminates the protocol mismatch that would otherwise require rewriting applications, deploying additional gateway infrastructure, or telling users that certain applications simply won't work remotely.
It's a protocol engine, not a platform. And that's by design.
If you're evaluating how to extend legacy IPv4 application support across your VPN infrastructure, we'd welcome the conversation. Contact our engineering team or reach out to your IVO Networks account representative to discuss your environment. We also offer a free 30-day trial of APP46 — call 866-4IVOAPP to get started.