| clatd(8) | clatd - CLAT, SIIT-DC and IPv6-only with many XLAT engines | clatd(8) |
clatd - a CLAT / SIIT-DC Edge Relay implementation for Linux
clatd implements the CLAT component of the 464XLAT network architecture specified in RFC 6877. It allows an IPv6-only host to have IPv4 connectivity that is translated to IPv6 before being routed to an upstream PLAT (which is typically a Stateful NAT64 operated by the ISP) and there translated back to IPv4 before being routed to the IPv4 internet. This is especially useful when local applications on the host requires actual IPv4 connectivity or cannot make use of DNS64 (for example because they use legacy AF_INET socket calls, or if they are simply not using DNS64).
clatd may also be used to implement an SIIT-DC Edge Relay as described in RFC 7756. In this scenario, the PLAT is in reality a SIIT-DC Border Relay (see RFC 7755) instead of a Stateful NAT64 (see RFC6146). When used as a SIIT-DC Edge Relay, you will probably want to manually configure the settings clat-v4-addr, clat-v6-addr, and plat-prefix to mirror the SIIT-DC Border Relay's configuration.
It relies either on the software package TAYGA by Nathan Lutchansky or on the kernel module nat46 by Andrew Yourtchenko for the actual translation of packets between IPv4 and IPv6 (RFC 6145) TAYGA may be downloaded from its home page at <http://www.litech.org/tayga/>, nat46 from its repository at <https://github.com/ayourtch/nat46>.
clatd [options]
clatd is meant to be run under a daemonising control process such as systemd or similar. It is further meant to be (re)started whenever a network interface goes up/down as this might mean a change in the PLAT availability or which prefixes/addresses needs to be used for the CLAT to work. It may also be run directly from the command line. It will run until killed with SIGINT (^C) or SIGTERM, at which point it will clean up after itself and exit gracefully.
See the scripts/ directory in the source distribution for some examples on how to invoke it it.
clatd is designed to be able to run without any user-supplied configuration in most cases. However, user-specified configuration settings may be added to the configuration file, the path to which may be given on the command line using the -c option, or if it is not, the default location /etc/clatd.conf is used. Configuration settings may also be given directly on the command line when starting clatd, which takes precedence over settings in the configuration file.
Settings are of the form key=value. A list of recognised keys and their possible values follow below:
The script is run by the system shell, so you can do everything you could in an interactive shell: run multiple commands by separating them by semi-colon or double ampersands, use standard if/else statements, use variable substitutions, redirect output to files, set up command pipelines, and so on. However it must all be on one line, so if you want to do complex things or use some other programming language it's probably better to put the script itself in a separate executable file and just make script-up invoke that file instead.
If the script returns a nonzero exit status, this is considered a fatal error, and clatd will abort. This can be prevented by appending || true at the end of the script.
All of clatd's configuration settings are available as standard variables in the script's environment (hyphens are replaced with underscores).
Logging or debug messages from the script may simply be sent to stdout, where it will be picked up by the init system along with clatd's own output. The script may of course consult the $quiet and $debug environment variables in order to determine how much output is appropriate.
The script should not be enclosed in quotes in the configuration file (even though it contains whitespace). For example:
script-up=echo `date -Ins`: clatd started on $clat_dev | tee -a ~/clatd.log
If on the other hand you want to supply a script-up containing whitespace directly clatd's command line, quoting is required in order to prevent the shell from splitting it up and into multiple command line arguments. For example:
clatd 'script-up=ip route add 192.0.2.0/24 dev $clat_dev || true'
An unsuccessful exit code from script-down will cause clatd to exit unsuccessfully too. Beyond that an unsuccessful exit won't change anything, because script-down is invoked at a point in time where the only thing left for clatd to do is to clean up after itself and exit anyway.
When using clatd as an SIIT-DC Edge Relay (RFC 7756), you will want to set this to the IPv4 Service Address configured in the SIIT-DC Border Relay. This way, local applications can correctly identify which public address they'll be using on the IPv4 internet, and will be able to provide fully functional references to it in application-level payload, and so on.
The default address is one from RFC 7335.
When set to shared (the default), clatd will re-use and share the primary IPv6 address used by the host OS when communicating with directly with the PLAT prefix. This allows clatd to operate without requiring a separate, dedicated IPv6 address assigned to the CLAT function. While this mode is the most compatible with various network deployments, it comes with certain trade-offs, see the LIMITATIONS section for more information.
When set to derived, clatd will attempt to figure out which network device will be used for traffic towards the PLAT, see if there is any SLAAC-based globally scoped addresses on it (i.e., a /64 with '0xfffe' in the middle of the Interface ID), and will if so substitute that '0xfffe' value with '0xc1a7' ("clat") to generate a CLAT IPv6 address.
If only a non-SLAAC global address is found on the PLAT-facing device, clatd will substitute its Interface ID with a random integer and use the result as the CLAT IPv6 address. It will only do so if the prefix length is /120 or smaller, as otherwise the risk of IID collisions is considered to be too high. Note that on most Perl platforms, the rand() function is limited to 48 bits, which means that for longer IIDs, the least significant bits will be all 0.
The derived mode is not guaranteed to result in a working configuration, see the LIMITATIONS section for more information.
If multiple addresses are found in either category, the one that shares the longest common prefix with the PLAT prefix will be preferred when deriving the CLAT IPv6 address according to the algorithm described above.
This means that connections initiated from the external IPv4 network via the PLAT will not reach the CLAT, therefore the use of this feature is incompatible with using clatd as a SIIT-DC Edge Relay (RFC 7756).
It might be useful to override this in case your network does not advertise the PREF64 RA option, your ISP doesn't provide you with a DNS64-enabled name server, and you want to test clatd using any of the public DNS64/NAT64 instances on the internet. The first PLAT prefix encountered will be used.
To prevent PLAT prefix discovery via systemd-networkd from being attempted, set this to an empty string.
If you don't want clatd to add and remove UFW firewall rules, set this to an empty string.
All sysctls that are modified will be restored to their original values when clatd is shutting down.
If the CLAT is sharing an IPv6 address with the host OS, this is not necessary as the host OS will be handling NDP anyway, so Proxy-ND does get enabled by default when clat-v6-addr is set to its default value shared.
Any entries added wil be removed when clatd is shutting down.
The default address is one from RFC 7335.
If you want to always start the CLAT whenever possible, even though the system has IPv4 connectivity, disable this setting. You may instead use the v4-defaultroute-enable and v4-defaultroute-metric settings to prevent clatd from interfering with native IPv4 connectivity.
Note that enabling v4-defaultroute-replace will override v4-conncheck-enable and unconditionally disable IPv4 connectivity checking.
Set it to 0 to perform the check immediately.
Note that nothing prevents software like a connection manager or a DHCPv4 client daemon from re-adding any replaced routes while clatd is running.
If you enable v4-defaultroute-replace while at the same time disabling v4-defaultroute-enable, clatd will remove any pre-existing IPv4 default routes but not add any of its own.
Setting v4-defaultroute-replace to yes will disable the IPv4 connectivity check.
If you know that the IPv6 Path MTU between the host and the PLAT is larger than 1280, you may increase this, but then you should also recompile TAYGA with a larger ipv6_offlink_mtu setting in conffile.c.
You should normally not need to set this. By default the value is calculated by taking the value of v4-defaultroute-mtu and substracting 40 (20 bytes for the IPv4 header + 20 bytes for the TCP header). If v4-defaultroute-mtu is unset or 0, there is no default.
When using clat-v6-addr=shared (or when clat-v6-addr is set to another address assigned to a local interface) and ctmark is set to 0, the host OS will not be able to communicate bi-directionally with IPv4 destinations directly through the PLAT (e.g., ping6 64:ff9b::192.0.2.1). This is because the response traffic will be routed back to the CLAT, and ultimately return to the Linux kernel as an IPv4 packet, which does not match the outgoing IPv6 socket. Such direct communication is normal when using DNS64 synthesis for all queries (as opposed to just ipv4only.arpa).
When using clat-v6-addr=derived and no IPv6 addresses on the PLAT-facing device are EUI-64-derived (e.g., when using SLAAC with RFC 4941 or RFC 7217 privacy addressing or static addresses), clatd will generate and use an CLAT IPv6 address using a random Interface ID from the same subnet prefix (if it is /120 or shorter). RFC 6877 suggests DHCPv6 IA_PD should be attempted in this case instead, but this isn't currently implemented.
clatd will not attempt to perform Duplicate Address Detection for the IPv6 address it generates when using clat-v6-addr=derived. This is a violation of RFC 6877.
There is no guarantee that the generated CLAT IPv6 address is in fact usable, as the network might block its use.
If the upstream network is using DHCPv6, clatd will not be able to generate a CLAT IPv6 address at all, due to the fact that DHCPv6-assigned addresses do not carry a prefix length.
clatd will not attempt to perform a connectivity check to a discovered PLAT prefix before setting up the CLAT, as RFC 7050 suggest it should.
If you are experiencing any bugs or have any feature requests, head over to <https://github.com/toreanderson/clatd/issues> and submit a new issue (if someone else hasn't already done so). Please make sure to include logs with full debugging output (using -d -d on the command line or debug=2 in the configuration file) when reporting a bug.
Copyright (c) 2014-2025 Tore Anderson <tore@fud.no>.
SPDX-License-Identifier: MIT
ip(8), nft(8), systemd.network(5), tayga(8), tayga.conf(5)
RFC 6052, RFC 6145, RFC 6146, RFC 6877, RFC 7050, RFC 7335 RFC 7755, RFC 7756, RFC 7757, RFC 8781
| 2025-04-16 | perl v5.40.1 |