No description
  • Python 83.1%
  • Shell 16.6%
  • Makefile 0.3%
Find a file
navigator 0675d860d5 feat: v2 — TAYGA_IPV6, pool CGNAT, confconsole plugin, fixes
Major changes:
- Added 5th parameter TAYGA_IPV6 (required when using well-known
  prefix 64:ff9b::/96 with RFC 1918 ipv4-addr). Inithook auto-detects
  global IPv6 from interface.
- Default pool changed to 100.64.0.0/10 (RFC 6598 CGNAT, ~4M virtual
  addresses, internal to box only).
- Default TAYGA_IPV4 changed to 100.64.0.1.
- Confconsole plugin moved from plugins.d/NAT64/ dir to single file
  plugins.d/nat64.py (PluginDir format was incompatible).
- Plugin now has 5 options: Status, Stats (pool usage + conntrack +
  MASQUERADE counters), Configure (5-field form with validation),
  Restart, and Logs (journalctl viewer).
- Added conntrack and tcpdump to plan.
- conf.d/main: added chmod +x for all scripts and plugin, added
  tayga_ipv6 inithook symlink.
- conf.d/zz-lxc-cleanup: removes /var device nodes recreated by
  postfix postinst — required for unprivileged LXC extraction.
- tayga.service: changed to --nodetach (Type=simple) for proper
  systemd lifecycle management.

Tested in production: DNS64 + NAT64 working across all VLANs
(eth1.2-16, eth1.88, eth2.2-9) via edge01/edge02 static route.
2026-03-20 04:14:24 +00:00
conf.d feat: v2 — TAYGA_IPV6, pool CGNAT, confconsole plugin, fixes 2026-03-20 04:14:24 +00:00
overlay feat: v2 — TAYGA_IPV6, pool CGNAT, confconsole plugin, fixes 2026-03-20 04:14:24 +00:00
plan feat: v2 — TAYGA_IPV6, pool CGNAT, confconsole plugin, fixes 2026-03-20 04:14:24 +00:00
.gitignore feat: v2 — TAYGA_IPV6, pool CGNAT, confconsole plugin, fixes 2026-03-20 04:14:24 +00:00
changelog feat: initial tkldev structure — Makefile, plan, changelog, README 2026-03-19 23:56:04 +00:00
Makefile feat: initial tkldev structure — Makefile, plan, changelog, README 2026-03-19 23:56:04 +00:00
README.md Fix to md 2026-03-19 23:59:12 +00:00

NAT64 - IPv6-to-IPv4 Translation Gateway (TAYGA)

TAYGA_ is a userspace NAT64 translator that operates via a TUN device. This TurnKey appliance packages TAYGA as a dedicated NAT64 gateway, optimized for deployment as an unprivileged LXC container on Proxmox.

Architecture

::

Clients (IPv6-only)         DNS64 servers
      |                     prefix=64:ff9b::/96
      v                           |
  [Edge Router] --- static route 64:ff9b::/96 ---> [LXC nat64]
                                                      TAYGA (TUN)
                                                      iptables MASQUERADE
                                                          |
                                                     Internet (IPv4)

The DNS64 servers synthesize AAAA records for IPv4-only destinations using the well-known prefix 64:ff9b::/96. Clients send IPv6 traffic to the synthesized address, which the edge routers forward to this appliance. TAYGA translates the packets to IPv4, and iptables MASQUERADE handles the source NAT on the way out.

Features

This appliance includes all the standard features in TurnKey Core_, and on top of that:

  • TAYGA NAT64 stateful translator running in userspace (no kernel module required, compatible with unprivileged LXC).

  • Systemd integration with two services:

    • tayga-setup.service: creates TUN device, routes, and iptables MASQUERADE rules.
    • tayga.service: runs the TAYGA daemon with auto-generated config.
  • Firstboot configuration (inithooks) with four dialog screens:

    • NAT64 prefix (default: 64:ff9b::/96)
    • TAYGA IPv4 address (default: 100.64.0.1)
    • Dynamic IPv4 pool (default: 100.64.0.0/10)
    • Outbound interface (default: eth0)

    All dialogs support --pass= for non-interactive provisioning (Ansible, cloud-init, etc.).

  • Confconsole plugin with five management options:

    • Status: TUN interface, routes, process, MASQUERADE rules.
    • Stats: pool utilization, conntrack count, packet counters.
    • Configure: edit all four parameters with live validation.
    • Restart: restart TAYGA with confirmation.
    • Logs: last 50 journal entries for both services.
  • Template-based config: /etc/default/nat64 is the single source of truth. apply-config.sh renders /etc/tayga.conf from a template on every service start.

Dynamic Pool

The dynamic pool (default 100.64.0.0/10, RFC 6598 CGNAT space) provides approximately 4 million virtual IPv4 addresses for mapping IPv6 hosts. These addresses are internal to the appliance only — they never appear on the network because iptables MASQUERADE rewrites the source address before packets leave the box.

This means:

  • No VLANs, bridges, or physical infrastructure needed for the pool.
  • No conflict with real client IPs or public addresses.
  • No routes needed on edge routers for the pool range.
  • The only real resource consumed is memory (~10 MB for 20,000 mappings).

The pool size only limits the number of distinct IPv6 hosts that can use NAT64 simultaneously.

Proxmox LXC Requirements

This appliance runs as an unprivileged container but requires TUN device access. Add the following to /etc/pve/lxc/<CTID>.conf before starting the container::

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Example container creation::

pct create <CTID> local:vztmpl/turnkey-nat64-18.0-bookworm-amd64.tar.gz \
    --hostname nat64 \
    --unprivileged 1 \
    --net0 name=eth0,bridge=vmbr16,ip=<LXC_IPV4>/24,gw=<GATEWAY_IPV4>,ip6=<LXC_IPV6>/64,gw6=<GATEWAY_IPV6> \
    --storage local-lvm \
    --memory 256 \
    --cores 1

Replace <LXC_IPV4>, <GATEWAY_IPV4>, <LXC_IPV6>, and <GATEWAY_IPV6> with your actual network addresses.

Edge Router Configuration

Add a static route on your edge routers pointing the NAT64 prefix to this appliance's IPv6 address::

set protocols static route6 64:ff9b::/96 next-hop <LXC_IPV6>

DNS64 Setup

Your recursive DNS servers need the dns64-prefix directive. For PowerDNS Recursor, add to recursor.conf::

dns64-prefix=64:ff9b::/96

Verify with::

dig AAAA ipv4only.arpa @<dns-server-ip>

The response should contain addresses in the 64:ff9b:: prefix.

Testing

From any host using the DNS64 resolvers::

ping6 64:ff9b::0101:0101        # 1.1.1.1
ping6 64:ff9b::0808:0808        # 8.8.8.8
curl -6 http://[64:ff9b::0808:0808]/

Building with TKLDev

::

cd /turnkey/fab/products
git clone https://git.pop.coop/turnkeylinux/tayga-nat64.git
cd tayga-nat64
make

Generate the LXC template from the sandbox::

cd build/root.sandbox
tar czf /tmp/turnkey-nat64-18.0-bookworm-amd64.tar.gz .

File Layout

::

Makefile                                    # TKLDev Makefile (Core base)
plan/main                                   # Package plan
changelog                                   # Debian-format changelog
conf.d/
    main                                    # Post-install configuration
    zz-lxc-cleanup                          # Remove device nodes for LXC
overlay/
    etc/
        default/nat64                       # Configuration defaults
        tayga.conf.template                 # TAYGA config template
        sysctl.d/99-nat64.conf              # IPv4/IPv6 forwarding
        systemd/system/
            tayga-setup.service             # TUN + routes + iptables
            tayga.service                   # TAYGA daemon
        confconsole/services.txt            # No web services
    usr/
        local/bin/
            tayga-setup.sh                  # Setup/teardown/status script
            apply-config.sh                 # Template renderer
        lib/
            inithooks/bin/
                _nat64_common.py            # Shared validation functions
                nat64_prefix.py             # Firstboot: NAT64 prefix
                tayga_ipv4.py               # Firstboot: TAYGA IPv4
                dynamic_pool.py             # Firstboot: dynamic pool
                outbound_iface.py           # Firstboot: outbound interface
            confconsole/plugins.d/NAT64/
                nat64_status.py             # Confconsole management plugin

Known Issues

  • The conf.d/zz-lxc-cleanup script removes device nodes from /var/spool/postfix/dev/ that are recreated by the Postfix postinst script (triggered by common/conf/turnkey.d/postfix-local during the build). Without this cleanup, pct create with --unprivileged 1 fails because mknod is not permitted in unprivileged user namespaces.

License

This appliance is developed by PopSolutions Cooperative_ (pop.coop).

.. _TAYGA: http://www.litech.org/tayga/ .. _TurnKey Core: https://www.turnkeylinux.org/core .. _PopSolutions Cooperative: https://pop.coop