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 on the software package TAYGA by Nathan Lutchansky for the actual translation of packets between IPv4 and IPv6 (RFC 6145) TAYGA may be downloaded from its home page at https://www.litech.org/tayga/.
clatd [options]
- -q
-
Quiet mode; suppress normal output. This is the same as setting quiet=1. Warnings and errors are still outputted, to silence those too, repeat -q.
- -d
-
Enable debugging output. This is the same as setting debug=1. Repeat for even more debugging output, which is the equivalent of setting debug=2.
- -c conf-file
-
Read configuration settings from conf-file. See section CONFIGURATION below for more info.
- -h, --help
-
Print a brief usage help and exit.
- key=value
-
Set configuration key to value, overriding any setting found in the configuration file. Refer to the section CONFIGURATION below for more info.
clatd is meant to be run under a daemonising control process such as systemd, upstart, 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.
The following commands will quickly download and install the latest version of clatd and its dependencies:
- git clone https://github.com/toreanderson/clatd
- sudo make -C clatd install installdeps
This will install clatd to /usr/sbin, plus install systemd, upstart, and/or NetworkManager scripts if your distribution appears to be using them, and install all the dependencies. Note that TAYGA isn't available in all RPM-based distros (in particular RHEL and its clones). It is however available in EPEL (see https://fedoraproject.org/wiki/EPEL).
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:
- quiet=integer (default: 0)
-
Set this to 1 to suppress normal output from clatd. This is the same as providing the command line option -q. Set it to 2 to additionally suppress warnings and errors. Note that this does not suppress debugging output.
- debug=integer (default: 0)
-
Set this to 1 to get debugging output from clatd, or 2 to get even more of the stuff. These are the equivalent of providing the command line option -d the specified number of times.
- script-up=string (no default)
-
Specify a custom script to be run when clatd is starting up. The invocation of this script is the last thing that happens before TAYGA starts up, so all the preparations have been completed at that point (i.e., the clat-dev exists and has routing/addressing configured, forwarding has been enabled, and so on).
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'
- script-down=string (no default)
-
This works exactly the same as script-up, only that this script is run right after TAYGA has exited, before the clean-up process of restoring any settings that were changed.
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.
- clat-dev=string (default: clat)
-
The name of the network device used by the CLAT. There should be no reason to change the default, unless you plan on running multiple instances of clatd simultaneously.
- clat-v4-addr=ipv4-address (default: 192.0.0.1)
-
The IPv4 address that will be assigned to the CLAT device. Local applications will bind to this address when communicating with external IPv4 destinations. In a standard 464XLAT environment with a stateful NAT64 serving as the PLAT, there should be no need to change the default.
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.
- clat-v6-addr=ipv6-address (default: auto-generated)
-
The IPv6 address of the CLAT. Traffic to/from the clat-v4-addr will be translated into this address. When using clatd as an SIIT-DC Edge Relay, you will want to set this to the same IPv6 address in the Explicit Address Mapping configured in the SIIT-DC Border Relay.
By default, 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.
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.
- dns64-servers=srv1,[srv2,..] (default: use system resolver)
-
Comma-separated list of DNS64 servers to use when discovering the PLAT prefix using the method described in RFC 7050. By default, the system resolver is used, but it might be useful to override this in case 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.
- cmd-ip=path (default: assume in $PATH)
-
Path to the ip binary from the iproute2 package available at https://www.kernel.org/pub/linux/utils/net/iproute2. Required.
- cmd-ip6tables=path (default: assume in $PATH)
-
Path to the ip6tables binary from the netfilter package available at https://netfilter.org. Only required for adding ip6tables rules (see the ip6tables-enable configuration setting).
- cmd-tayga=path (default: assume in $PATH)
-
Path to the tayga binary from the TAYGA package available at https://www.litech.org/tayga. Required.
- forwarding-enable=bool (default: yes)
-
Controls whether or not clatd should enable IPv6 forwarding if necessary. IPv6 forwarding is necessary for clatd to work correctly. It will also ensure that the accept_ra sysctl is to '2' for all devices have it set to '1', in order to prevent any connectivity loss as a result of enabling forwarding.
All sysctls that are modified will be restored to their original values when clatd is shutting down.
- ip6tables-enable=bool (default: see below)
-
Controls whether or not clatd should insert ip6tables rules that permit the forwarding of IPv6 traffic between the CLAT and PLAT devices. Such forwarding must be permitted for clatd to work correctly. Any rules added will be removed when clatd is shutting down.
The default is yes if the ip6tables_filter kernel module is loaded, no if it is not.
- plat-dev (default: auto-detect)
-
Which network device is facing the PLAT (NAT64). By default, this is auto-detected by performing a route table lookup towards the PLAT prefix. This setting is used when setting up generating the CLAT IPv6 address, and when setting up ip6tables rules and Proxy-ND entries.
- plat-prefix (default: auto-detect)
-
The IPv6 translation prefix into which the PLAT maps the IPv4 internet. See RFC 6052 for a closer description. By default, this is auto-detected from DNS64 answers using the method in RFC 7050.
- proxynd-enable (default: yes)
-
Controls whether or not clatd should add a Proxy-ND entry for the CLAT IPv6 address on the network device facing the PLAT. This is probably necessary on Ethernet networks (otherwise the upstream IPv6 router won't know where to send packets to the CLAT's IPv6 address), but likely not necessary on point-to-point links like PPP or 3GPP mobile broadband, as in those cases IPv6 ND isn't used. However it doesn't hurt to add Proxy-ND entries in that case, either.
Any entries added wil be removed when clatd is shutting down.
- tayga-conffile (default: use a temporary file)
-
Where to write the TAYGA configuration file. By default, a temporary file will be created (and also deleted when clatd is shutting down), but you may also specify an explicit configuration file here, which will not be deleted on shutdown.
- tayga-v4-addr (default: 192.0.0.2)
-
The IPv4 address assigned to the TAYGA process. This is used for emitting ICMPv4 errors back to the host (i.e., it will show up as the first hop when tracerouting to IPv4 destinations), and you may also ping it to verify that the TAYGA process is still alive and well.
The default address is one from RFC 7335.
- v4-conncheck-enable=bool (default: yes)
-
Whether or not to check if the system has IPv4 connectivity before starting the CLAT. If it does, then clatd will simply exit without doing anything. This is meant so that you can always enable clatd to the system startup scripts or network-up event scripts (such as NetworkManager's dispatcher scripts), but not have clatd interfering with native IPv4 connectivity when this is present.
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.
- v4-conncheck-delay=seconds (default: 10)
-
When performing an IPv4 connectivity check, wait this number of seconds before actually doing anything. This is to avoid a race condition where for example IPv6 SLAAC finshes and triggers a network-up event script to start clatd, while IPv4 DHCPv4 is still running in the background. This is at least a likely scenario when using NetworkManager, as it will start the dispatcher scripts as soon as either IPv4 or IPv6 has completed, and IPv6 SLAAC is typically faster than IPv4 DHCPv4.
Set it to 0 to perform the check immediately.
- v4-defaultroute-enable=bool (default: yes)
-
Whether or not to add an IPv4 default route pointing to the CLAT. In a typical 464XLAT environment, you want this. However when using clatd in an environment where native IPv4 connectivity is also present, you might want to disable this and instead control manually which IPv4 destinations is reached through the CLAT and which are not.
- v4-defaultroute-replace=bool (default: no)
-
Instructs clatd to remove any pre-existing IPv4 default routes, replacing it with one pointing to the CLAT (assuming v4-defaultroute-enable is yes). The replacement is temporary, any pre-existing routes that were removed will be restored when clatd is shutting down.
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.
- v4-defaultroute-metric=integer (default: 2048)
-
The metric of the IPv4 default route pointing to the CLAT. The default is chosen because it is higher than that of a native IPv4 default route added by NetworkManager, which makes it so that the native IPv4 connectivity is preferred if present.
- v4-defaultroute-mtu=integer (default: 1260)
-
The MTU of the default route pointing to the CLAT. The default is the default IPv6 MTU used by TAYGA (1280, which in turn comes from RFC 6145) minus 20 to compensate for the difference in header size between IPv4 and IPv6. This prevents outbound packets from having to be fragmented by TAYGA, and also makes local applications advertise a TCP MSS to their remote peers that prevent them from sending packets beck to us that would require fragmentation.
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.
- v4-defaultroute-advmss=integer (default: v4-defaultroute-mtu - 40)
-
The "advmss" value assigned to the the default route potining to the CLAT. This controls the advertised TCP MSS value for TCP connections made through the CLAT.
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.
clatd will not be able to acquire an IPv6 address for the CLAT if SLAAC isn't used. RFC 6877 suggests DHCPv6 IA_PD should be attempted in this case, but this isn't currently implemented.
clatd will not attempt to perform Duplicate Address Detection for the IPv6 address it generates. This is a violation of RFC 6877.
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-2019 Tore Anderson <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ip(8), ip6tables(8), tayga(8), tayga.conf(5)
RFC 6052, RFC 6145, RFC 6146, RFC 6877, RFC 7050, RFC 7335 RFC 7755, RFC 7756, RFC 7757