Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Setting up a NAT64 server on a cheap dual-stack LXC VPS with just 256MB memory

Hey there, LowEndTalks community! First post here - let me share something cool I figured out.

IPv4 addresses are expensive these days, while IPv6-only hosting is dirt cheap. The problem? Many sites still only work on IPv4, making IPv6-only setups kind of limited. That's where NAT64 comes in! It's like a universal translator between IPv6 and IPv4 with minimal complexity and resource overhead.

I've got this whole setup running smoothly on a tiny 256MB LXC VPS that costs me about $2/year. Talk about stretching your hosting dollars!

Prerequisites

You'll need:

  • A dual-stack VPS (has both IPv4 and IPv6)
  • Root access
  • Basic networking knowledge (or good copy-paste skills!)
  • Linux installed (I'll show examples for Alpine, Debian/Ubuntu, and RHEL/CentOS)

Step 1: Find Your IPv6 Subnet

Run this command to see what you're working with:

ip -6 route

You'll see something like:
2001:db8:1234::/64 dev eth0 proto kernel metric 256 pref medium

This shows your /64 subnet and network interface. Make note of it!

Step 2: Choose a /96 Prefix for IPv4 Mapping

Pick a /96 prefix from your subnet for mapping IPv4 addresses. If your subnet is 2001:db8:1234::/64, you might use:

2001:db8:1234:64:ff9b::/96

This format uses 96 bits for the IPv6 prefix and 32 bits for embedding IPv4 addresses.

Step 3: Add a Local Route

Tell your system to treat the prefix as local:

ip -6 route add local 2001:db8:1234:64:ff9b::/96 dev lo

Step 4: Set Up NDP Proxy

This lets your server answer neighbor discovery requests for your NAT64 prefix.

For Alpine:

# Install npd6
apk add npd6

# Configure npd6
cat > /etc/npd6.conf <<EOF
prefix=2001:db8:1234:64:ff9b::  # your chosen prefix
interface=eth0
ralogging=off
listtype=none
listlogging=off
collectTargets=100
linkOption=false
ignoreLocal=true
routerNA=true
maxHops=255
pollErrorLimit=20
EOF

# Start service
rc-update add npd6
service npd6 start

For Debian/Ubuntu:

# Install ndppd
apt install ndppd

# Configure ndppd
cat > /etc/ndppd.conf <<EOF
proxy eth0 {
  rule 2001:db8:1234:64:ff9b::/96 {
    static
  }
}
EOF

# Start service
systemctl enable ndppd
systemctl start ndppd

For RHEL/CentOS:

# Install ndppd
dnf install ndppd

# Configure same as Debian
# Then start service
systemctl enable ndppd
systemctl start ndppd

Remember to replace 2001:db8:1234:64:ff9b:: and eth0 with your actual values!

Step 5: Test Local Route Setup

Verify with a ping:

ping -6 2001:db8:1234:64:ff9b::1234

If you run into problems, check your firewall first, e.g. loopback traffic is accepted and ICMPv6 is enabled.

YMMV: Some cloud providers impose limitation on traffic over any ip. Oracle Cloud for example filters out traffic with IPv6 addresses are not bound to VNIC.

Comments

  • Step 6: Install and Run NAT64

    Download nat64 file from this minimalistic NAT64 server or build from source (can't attach link for whatever reason)

    Configure iptables to redirect traffic:

    ip6tables -t mangle -A PREROUTING -d 2001:db8:1234:64:ff9b::/96 -p tcp -j TPROXY --on-port=8888 --on-ip=::1
    

    Run the server:

    /path/to/nat64
    
  • Step 7: Set Up DNS64

    You have two deployment options for DNS64:

    1. Server-side DNS64: You can run both DNS64 and NAT64 on your dual-stack server. This is simpler to set up but gives you less control over traffic routing.

    2. Client-side DNS64: You run DNS64 on your IPv6-only client machines and just the NAT64 on your dual-stack server. This approach is generally preferred as it provides:

      • Faster DNS resolution (local DNS queries)
      • Full control over which traffic goes through NAT64
      • The ability to selectively route only certain domains through NAT64

    For client-side DNS64, you would install and configure Unbound on your client machines instead, pointing to your NAT64 server's prefix.

    Install Unbound:

    # Debian/Ubuntu
    apt install unbound
    
    # Alpine
    apk add unbound
    
    # RHEL/CentOS
    dnf install unbound
    

    Configure DNS64:

    cat > /etc/unbound/unbound.conf.d/dns64.conf <<EOF
    server:
      module-config: "dns64 iterator"
      dns64-prefix: 2001:db8:1234:64:ff9b::/96
      do-not-query-localhost: yes
    
    forward-zone:
      name: "."
      forward-addr: 1.1.1.1@53
      forward-addr: 8.8.8.8@53
    EOF
    

    Replace 2001:db8:1234:64:ff9b::/96 with your actual NAT64 prefix, and adjust the forward-addr to your preferred DNS servers.

    Restart Unbound and configure DNS:

    systemctl restart unbound
    echo "nameserver ::1" > /etc/resolv.conf
    
  • Step 8: Run NAT64 as a Service

    For systemd systems:

    cat > /etc/systemd/system/nat64.service <<EOF
    [Unit]
    Description=NAT64 Server
    After=network.target
    
    [Service]
    ExecStart=/path/to/nat64 -p 8888
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl enable nat64
    systemctl start nat64
    

    For Alpine with OpenRC:

    cat > /etc/init.d/nat64 <<EOF
    #!/sbin/openrc-run
    
    command=/path/to/nat64
    command_args="-p 8888"
    pidfile=/run/nat64.pid
    
    depend() {
      need net
      after network
    }
    
    start() {
      ebegin "Starting NAT64"
      start-stop-daemon --start --make-pidfile --pidfile \${pidfile} --background --exec \${command} -- \${command_args}
      eend \$?
    }
    EOF
    
    chmod +x /etc/init.d/nat64
    rc-update add nat64 default
    service nat64 start
    
  • Step 9: Make Configuration Permanent

    Create startup scripts to persist your settings across reboots.

    For Alpine:

    cat > /etc/local.d/nat64-setup.start <<EOF
    #!/bin/sh
    ip -6 route add local 2001:db8:1234:64:ff9b::/96 dev lo
    ip6tables -t mangle -A PREROUTING -d 2001:db8:1234:64:ff9b::/96 -p tcp -j TPROXY --on-port=8888 --on-ip=::1
    EOF
    
    chmod +x /etc/local.d/nat64-setup.start
    

    For Debian/Ubuntu:

    cat > /etc/network/if-up.d/nat64-setup <<EOF
    #!/bin/sh
    ip -6 route add local 2001:db8:1234:64:ff9b::/96 dev lo
    ip6tables -t mangle -A PREROUTING -d 2001:db8:1234:64:ff9b::/96 -p tcp -j TPROXY --on-port=8888 --on-ip=::1
    EOF
    
    chmod +x /etc/network/if-up.d/nat64-setup
    
  • Verify Your Setup

    Test with:

    ping -6 ipv4.google.com
    

    or try to curl with ipv6 http://ipv4only.me

    If those work, you're golden!

  • Conclusion - Profit!

    You've now got a working NAT64 gateway on a dirt-cheap VPS! This lets you:

    • Run services on budget IPv6-only VPS plans (we're talking $1-2/year cheap!)
    • Access IPv4-only services from IPv6-only networks
    • Save serious cash while getting full internet access

    The whole setup runs on even the tiniest containers with minimal resources. Combine this with a cheap IPv6 VPS plan, and you're saving serious money while still getting full internet access.

    Questions? Drop 'em in the comments!

  • Thanks for this! I was looking to set up a NAT64+DNS64 server this weekend so this came at the perfect time.

  • ailiceailice Member
    edited March 2025

    Tutorial so crystal-clear even have alpine version, is so chef kiss

Sign In or Register to comment.