An inexpensive IPv6‑only VPS can look appealing, but a public service needs more than a running server: can IPv4‑only users reach it?
An IPv6‑only origin can serve a public site without its own IPv4 address, provided another service bridges the gap. NAT64/DNS64 handles outbound access to IPv4 services; IPv4‑only visitors need a separate inbound proxy or translation path.
In this guide, I’ll walk you through how NAT64/DNS64 actually helps, how to handle both directions of traffic (spoiler: outbound is different from inbound), where reverse proxies and SIIT‑DC fit in, and some gotchas to watch for. If you’ve ever wondered whether an IPv6‑only VPS can host real sites and apps without alienating IPv4 users, you’re in the right place.
Why even bother with an IPv6‑only VPS?
An application may keep its core business logic while its network path changes, but test its assumptions about address families. Configuration files, IP literals, allow lists and external integrations can still depend on IPv4. The important feasibility question is whether each required connection works through native IPv6, the chosen proxy or a supported translation path.
IPv6-only can avoid assigning a scarce public IPv4 address to every origin. Compare current provider quotes and availability rather than assuming a discount or instant provisioning. Include gateway, proxy, transfer, redundancy and administration costs. Confirm that the application and its external dependencies work with the chosen IPv6 and translation paths.
Here’s the thing, though. Running IPv6‑only doesn’t mean ignoring IPv4 users. It means you put a small layer in front or near your server that speaks IPv4 on their behalf. This layer still needs monitoring and maintenance, whether you operate it yourself or use a managed service.
NAT64/DNS64 in plain language: your bilingual friend at the door
Let’s translate the acronyms into something you can picture. NAT64 is a translator that sits between IPv6 and IPv4 networks. It lets IPv6‑only machines reach IPv4‑only services by converting the packets in a stateful way. DNS64 is the phonebook trick that makes this work smoothly: when your IPv6‑only server asks DNS for a domain that only has an A record (IPv4), DNS64 manufactures an AAAA answer (IPv6) by embedding the IPv4 address into a special IPv6 prefix. Your machine then connects to that synthetic IPv6 address, and the NAT64 box quietly relays to the real IPv4 destination.
Think of NAT64/DNS64 as a friendly concierge for outbound connections. Your app wants to contact an API that only speaks IPv4? No problem — the concierge dials the right number, bridges the call, and you carry on. For IPv6‑capable applications using DNS names, this can support package downloads, outgoing webhooks and calls to IPv4‑only APIs.
Now the twist. NAT64/DNS64 helps IPv6‑only clients reach IPv4‑only services. IPv6‑capable visitors can reach your IPv6 origin directly when routing and firewall rules permit. But what about an IPv4‑only visitor? DNS64 cannot give that visitor IPv6 connectivity; synthesizing AAAA records does not provide an IPv4 destination for your origin. You need either a reverse proxy that presents an IPv4 address to the world, or a translation gateway that does the reverse path (commonly called NAT46 or a data center pattern known as SIIT‑DC). Same translation magic, flipped for incoming traffic.
The two directions you must care about (and the simplest patterns)
Outbound from your IPv6‑only server to IPv4 services
This is where NAT64/DNS64 is a joy. Put a NAT64 translator nearby (some providers already run one). Point your server’s resolver at a DNS64 service whose synthesis prefix is routed from your server to that translator. An IPv6‑enabled curl can then reach IPv4‑only sites by hostname; IPv4 literals and IPv4‑only socket use need another mechanism, such as 464XLAT or a proxy. You keep your host IPv6‑only and still consume the legacy web without sweating over dual‑stack plumbing on the box.
If your provider offers NAT64 and DNS64, follow its routing and resolver instructions. The well‑known prefix is 64:ff9b::/96, but providers may use another prefix. Otherwise, you can operate a translator on a dual‑stack gateway with suitable routing.
Inbound from IPv4 users to your IPv6‑only service
There are a few practical routes here, and the right one depends on your app.
For HTTP and HTTPS, the easiest move is to use a CDN or managed reverse proxy that terminates IPv4 on the edge and forwards to your IPv6 origin. Choose a service that supports IPv6‑only origins. TLS termination, caching, WAF, rate limiting and DDoS protection depend on the service and plan. It’s the one‑step solution most teams feel comfortable with, and it avoids tinkering with low‑level translation on day one.
For suitable TCP or UDP applications, a network translation gateway can map an allocated public IPv4 address to an IPv6 origin. SIIT-DC uses stateless IP translation, but still requires address mapping, routes, protocol support, firewall policy and capacity planning. A lack of per-flow translation state does not guarantee minimal latency or unlimited scale.
In other words, you either put a smart doorman at the edge who also does security and caching, or you put a small glass door that simply converts IPv4 visitors into IPv6 visitors and back. Both approaches can work. The first is faster to deploy for websites; the second is wonderfully transparent for custom protocols.
Planning separate NAT64/DNS64 and SIIT-DC paths
When the provider does not offer NAT64/DNS64, an outbound gateway can supply it. Inbound access is a separate decision: a reverse proxy is often suitable for HTTP, while SIIT can serve compatible network protocols. The examples below use separate gateway VMs and allocated IPv4 addresses for NAT64 and SIIT. Combining them on one host requires a reviewed packet-selection or namespace design; simply loading both broad Netfilter instances does not provide that separation.
General idea before commands
Outbound clients send synthesized IPv6 destinations to the NAT64 gateway, whose IPv4 pool handles return traffic for those sessions. For the separate SIIT path, route a dedicated public IPv4 service address to the SIIT gateway and map it to the origin IPv6 address. The gateway also represents IPv4 client addresses within its SIIT translation prefix. The origin must route replies for that prefix back through the SIIT gateway. Use a separate prefix from outbound NAT64, and keep management access outside the service mapping.
Sketching the steps
On the gateway VM, you enable forwarding and install Jool. Jool provides stateful NAT64 and stateless SIIT functionality through separate modules and command-line tools.
Prepare reachability, forwarding and firewall policy on each gateway before adding translation. DNS64 must synthesize the same prefix routed from outbound clients to NAT64. SIIT needs its own client-address prefix, an allocated public service address and return routing from the origin. EAMT mappings select addresses, not application ports; multiple origins need distinct mappings or a separate port-aware proxy. The snippets are separate lab building blocks, not a combined one-gateway deployment.
Example commands to make it concrete
Install a supported Jool version using its distribution instructions first. Replace all 203.0.113.0/24 and 2001:db8::/32 documentation addresses with addresses and prefixes you control. Before the first snippet, route the NAT64 prefix from each client to that gateway and ensure the IPv4 pool address reaches it. Reserve pool ports that do not overlap local services or the configured ephemeral range. Before the second snippet, route a separate public service IPv4 to the SIIT gateway and the origin’s client-prefix replies back to that gateway. Its management IPv4 must remain outside the mapping. Review both IP-family firewall paths and keep console recovery available. These temporary commands do not install DNS64, assign addresses, create routes or persist the setup across reboot.
# Gateway A: outbound NAT64 only; routes/firewall already prepared
sudo sysctl -w net.ipv4.conf.all.forwarding=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1
sudo modprobe jool
sudo jool instance add nat64 --netfilter --pool6 64:ff9b::/96
sudo jool -i nat64 pool4 add --tcp 203.0.113.10 61001-65535
sudo jool -i nat64 pool4 add --udp 203.0.113.10 61001-65535
sudo jool -i nat64 pool4 add --icmp 203.0.113.10 61001-65535
sudo jool -i nat64 pool4 display
Run the following on a DIFFERENT gateway VM with its own routed service IPv4 and client-translation prefix:
# Gateway B: inbound SIIT only; not Gateway A
sudo sysctl -w net.ipv4.conf.all.forwarding=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1
sudo modprobe jool_siit
sudo jool_siit instance add siit0 --netfilter --pool6 2001:db8:46::/96
sudo jool_siit -i siit0 eamt add 203.0.113.20/32 2001:db8:abcd:1::50/128
sudo jool_siit -i siit0 eamt display
Check allowed test sessions and return traffic, then configure persistence using the installed version’s documentation. This mapping does not make every protocol work or provide a firewall. Diagnose path MTU and permitted ICMP/ICMPv6 error messages before considering a narrowly scoped TCP MSS adjustment; a blanket MSS rule is not a universal network fix.
For DNS64, you can run a local resolver on the gateway and point your IPv6‑only servers to it. Bind it to the intended trusted interface and restrict recursive access and TCP/UDP port 53 to authorized clients; do not expose an unrestricted public recursive resolver. Configure its DNS64 synthesis prefix to match the outbound NAT64 translator; SIIT‑DC inbound mappings alone do not provide this outbound service. The servers continue asking for hostnames as usual; the resolver fabricates AAAA answers when only A exists, and traffic takes the NAT64 path.
A practical note: if your provider already runs NAT64/DNS64, try theirs first. It’s one less box for you to manage; compare its routing and latency with your requirements.
When a managed proxy is the right answer
For websites and HTTPS APIs, a managed proxy can provide an IPv4 entry point with an IPv6 origin when that combination is supported. Compare its TLS validation, caching rules, protocol and port limits, filtering options and capacity against the application’s requirements. These capabilities vary by provider and plan; verify the actual origin connection instead of treating proxy activation as a complete deployment.
If you head this way, spend a moment on request headers and logging. You want your app to see the real client IP, not the proxy’s IP. For most reverse proxies, that’s handled via headers like X‑Forwarded‑For or by PROXY protocol. Trust client-IP headers only from authorized proxy addresses, and ensure the proxy sanitizes client-supplied values. PROXY protocol requires explicit support and configuration at both ends; it is not an HTTP header.
A configured WAF and appropriate request limits can reduce some unwanted HTTP traffic before it reaches the origin. Their effectiveness depends on application behavior, rule scope and service capacity. Monitor false positives and intended user flows. A bare NAT64 or SIIT translator does not provide those application-layer controls.
For custom TCP/UDP services, some edge providers offer a product that does the same trick — IPv4 at the edge, IPv6 at the origin — for arbitrary ports. If your protocol can’t live behind HTTP, this kind of managed layer is an elegant alternative to running your own SIIT‑DC.
Practical inbound patterns: website, API, and beyond
Website or API over HTTPS
Point DNS A and AAAA at the reverse proxy, and set your origin to IPv6‑only. Configure your server to trust client-IP headers only from the proxy. Use HTTPS to the origin and configure the proxy to validate the origin certificate. Restrict origin access to the proxy, or use mutual TLS to authenticate it. You get dual‑stack reachability without managing any IPv4 on the VPS itself.
Custom TCP service
For a custom TCP service, choose a managed proxy that supports the protocol, required ports and IPv6 origin, or design an appropriate translation path. In the separate SIIT example, the allocated service IPv4 maps to the origin IPv6, while IPv4 client addresses are represented within the SIIT prefix. Route origin replies for that client prefix back through the SIIT gateway. Address mapping alone does not configure routes, firewall policy or protocol compatibility; test the full path before publishing the A record.
SSH and admin access
Here’s a little trick I like: keep SSH accessible only over IPv6 and your VPN, and don’t even bother offering IPv4 for admin. You reduce surface area and keep your security team happy. If you must allow IPv4 for SSH, map a dedicated IPv4 on the gateway to your server’s IPv6 and fence it with strict allow lists. IPv6 is not an access control: restrict SSH to the VPN or trusted source ranges and use key-based authentication.
Certificates and DNS: the part people forget until 2 a.m.
Certificates can trip you up if your ACME flow relies on HTTP‑01 and some of your validation path is IPv4‑only. The clean fix is to use DNS‑01 challenges, which work beautifully in an IPv6‑only origin world. With a supported DNS API and ACME client, renewal can be automated without inbound HTTP validation. HTTP‑01 can also work over IPv6 when the CA supports it and every published validation path serves the challenge.
Publish every intended hostname using the managed proxy’s supported DNS procedure, then inspect the actual A and AAAA answers. With a separate SIIT service path, the A record names the allocated service IPv4; publish a direct origin AAAA only if direct IPv6 access is intended. If both address families must traverse the same protected edge, align their DNS and access policy accordingly. Happy Eyeballs may race connection attempts but does not guarantee application-level failover. Lower TTLs ahead of a planned change, allowing existing cache lifetimes to expire; a new TTL does not instantly invalidate older cached records.
For a walkthrough of certificate automation with DNS‑01 on common stacks, see: the hands‑off guide to wildcard SSL with DNS‑01 and painless renewals. It’s the kind of thing that quietly removes a whole category of midnight alerts.
Gotchas to plan for
Logs and the real client IP
A proxy may hide the visitor IP unless forwarding is configured as described above. SIIT‑DC instead represents an IPv4 source as a translated IPv6 address; it does not insert HTTP headers or PROXY protocol metadata. Account for that address representation in logs and access rules.
PMTU and MSS clamping
Sometimes the path between your translator and origin has a smaller MTU, and you’ll see weird stalls or partial loads. Check that ICMP fragmentation-needed and ICMPv6 Packet Too Big messages can traverse the relevant paths. MSS clamping may mitigate TCP stalls if applied at the correct hook with an appropriate value, but it does not fix UDP or replace working path MTU discovery.
Email deliverability from an IPv6‑only box
Here’s where I’m cautious: not every receiving server loves mail from IPv6‑only senders, and you can spend days chasing reputation and reverse DNS quirks. For IPv6‑only app servers, consider offloading outbound mail to a dedicated SMTP relay or a transactional email service reachable over IPv6 or your outbound translation path. It’s boring and reliable. If your business depends on email, this is not the place to be a hero.
Firewalling and states
Review both IPv4 and IPv6 policy at each hop. Stateful NAT64 maintains translation sessions; SIIT address translation is stateless. A firewall may independently maintain connection state in either design. Document rule ownership, permitted services, return paths and capacity limits. The examples here use separate gateways and distinct prefixes; any shared-host design needs explicit packet selection or isolation and separate validation.
Performance and monitoring: what it feels like day to day
Measure the visitor-to-edge and edge-to-origin paths, packet loss, gateway load and connection capacity. Geographic proximity alone does not guarantee low latency. NAT64 and SIIT translate packets; they do not cache pages or inspect HTTP as a WAF. A suitable managed proxy may provide caching or filtering, depending on its plan and configuration. Evaluate those features separately from the cost of the extra hop.
For monitoring, I like to keep an eye on three things: the health of the translator or proxy itself, the origin’s capacity, and end‑to‑end reachability for both IPv4 and IPv6. A simple set of black‑box checks that hit your service over each protocol path will catch surprises early. It’s also helpful to graph translator counters so you can see if connections are growing faster than you expected. You’ll get a sixth sense for what normal looks like.
Documenting the Two Traffic Paths
Keep an explicit record of the two paths. For outbound traffic, record the DNS64 resolver, synthesis prefix, client route, NAT64 gateway and allocated IPv4 pool. For inbound traffic, record each published hostname, edge or SIIT service address, origin destination, return route and authentication boundary. Record which operator owns each dependency and how it is monitored and restored. This inventory makes a routing or certificate incident easier to diagnose without repeating the installation checklist.
Keep the design as small as the requirements permit, but treat each gateway or proxy as a maintained dependency. Monitor both address-family paths and test failure recovery, certificate renewal and routing changes. Extra addressing space does not remove capacity limits, software updates or the need for an operator response plan.
Concrete tooling and where to read more
If you’re rolling your own translator, two projects are worth bookmarking. Jool supports stateful NAT64 and SIIT‑DC. Tayga is another classic for NAT64 that some folks still like for simple setups. If you prefer a managed edge for non‑HTTP protocols, look at products that expose an IPv4 listener and connect to an IPv6 origin.
Here are a few links for further reading:
Jool, a NAT64/SIIT‑DC toolkit — clear docs and examples
Cloudflare Spectrum TCP/UDP edge proxy — IPv4 listeners with IPv6 origins; protocol availability depends on the plan
Tayga NAT64 — lightweight and familiar to many
Troubleshooting scenarios to investigate
An IPv6‑only API behind a managed HTTP proxy can still suffer region-specific timeouts from a path MTU problem. Check that required ICMP Packet Too Big messages can pass. For TCP, MSS clamping on an edge you control may help mitigate PMTU black holes; a managed edge may require provider assistance.
A move to IPv6‑only can leave the app working while builds fail because vendor scripts come from an IPv4‑only endpoint. For hostname-based fetches by IPv6-capable tools, DNS64 plus a reachable NAT64 gateway can provide outbound access. Changing the resolver alone does not supply that gateway or fix IPv4 literals.
If every log shows the proxy’s IP, check real-client-IP handling before blaming the cache. Accept X‑Forwarded‑For only from explicitly trusted proxies, with a defined header-sanitization policy; never trust arbitrary client-supplied values.
Security posture: what changes, what doesn’t
Running IPv6‑only on the origin doesn’t magically secure your app, but it often tightens your focus. You can expose fewer services directly by restricting origin access to a designated edge; IPv6‑only addressing does not enforce that restriction. That’s good discipline. Keep your gateway lean and patched if you run one, and treat it like any other critical piece: minimal packages, tight firewall rules, and monitoring with alerts you actually read. If the managed edge offers a WAF and rate limits for your traffic, tune them to reduce unwanted requests reaching the origin.
One potential benefit is clearer addressing for allow lists and internal policies. With ample IPv6 space, carving out ranges for testing, staging, or certain backend jobs is easy and unambiguous. It’s a small quality‑of‑life improvement that adds up over time.
Costs and trade‑offs without the spreadsheet
Compare the total current cost of addresses, gateways, managed services, bandwidth, monitoring and administration. Stateful outbound NAT64 can share an IPv4 address across multiple clients subject to protocol and port capacity. SIIT inbound address mappings generally need distinct public service addresses for distinct origins; they do not select an origin by port. A proxy may share an address for suitable application traffic. Capacity and redundancy can require more than one gateway, so savings are not guaranteed by removing IPv4 from each origin.
The trade‑off is that you’re adding one indirection layer, so your troubleshooting playbook must include it. Not a big deal, but it’s different than the old mental model of app directly on an IPv4. That layer also needs capacity planning and failure monitoring.
A tidy checklist to get you moving today
First verify IPv6 routing, management access and the external repositories, APIs and certificate services your deployment needs. Establish outbound NAT64/DNS64 before installation if required dependencies are IPv4-only. Then deploy the application and choose inbound access: an IPv6-origin-capable proxy for supported traffic, or a separately designed SIIT gateway with its own service IPv4, client prefix and return routing. Keep the two example gateways separate; a shared-host design requires explicit packet selection or isolation. Publish DNS for every hostname and intended IPv4/IPv6 path, configure trusted client-IP handling, protect any DNS-01 credentials and test renewals. Finish with independent checks of both address families, application behavior and failure recovery.
IPv6-only hosting with tested IPv4 connectivity
An IPv6-only origin can serve suitable applications when both directions of connectivity are planned. NAT64/DNS64 supports hostname-based outbound connections from IPv6-capable applications to IPv4 services; direct IPv4 addresses and IPv4-only sockets need separate handling. An inbound proxy or suitable SIIT design can serve IPv4 visitors. Reliable operation still depends on routes, security policy, application compatibility, capacity and recovery.
Evaluate the design first on a small service with representative external dependencies and users. Check proxy-header trust, allowed traffic, both address families and failure recovery before a wider rollout. A successful page load is one useful test; it does not establish that every protocol, API dependency or return path is correct.
Retain the tested configuration, address plan and rollback steps, and recheck them after provider, certificate or application changes. That operational record makes the chosen IPv4 compatibility layer maintainable alongside the IPv6 origin.





