- Python 83.1%
- Shell 16.6%
- Makefile 0.3%
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. |
||
|---|---|---|
| conf.d | ||
| overlay | ||
| plan | ||
| .gitignore | ||
| changelog | ||
| Makefile | ||
| README.md | ||
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.). - NAT64 prefix (default:
-
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/nat64is the single source of truth.apply-config.shrenders/etc/tayga.conffrom 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-cleanupscript removes device nodes from/var/spool/postfix/dev/that are recreated by the Postfixpostinstscript (triggered bycommon/conf/turnkey.d/postfix-localduring the build). Without this cleanup,pct createwith--unprivileged 1fails becausemknodis 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