Introduction to Jool
Jool is an Open Source implementation of IPv4/IPv6 Translation on Linux. Until version 3.2.x, it used to be only a Stateful NAT64; starting from 3.3.0, it also supports SIIT mode.
As far as we know, this is the compliance status of Jool 3.6:
|RFC 6052||IP address translation||Fully compliant.|
|RFC 6144||IPv4/IPv6 Translation Framework||Fully compliant.|
|RFC 7915||SIIT||Fully compliant.|
|RFC 6146||Stateful NAT64||Fully compliant.|
|RFC 6384||FTP over NAT64||Not yet compliant.|
|RFC 6791||ICMP quirks||In short, this RFC wants two things: A pool of IPv4 addresses and an ICMP header extension. Jool implements the former but not the latter.|
|RFC 6877||464XLAT||Rather implemented as SIIT-DC-DTM; see below.|
|RFC 7755||SIIT-DC||Fully compliant.|
|RFC 7756||SIIT-DC: Dual Translation Mode||Fully compliant.|
|RFC 8021||Atomic Fragment Deprecation||Fully compliant.|
|RFC 7757||EAM||Fully compliant.|
|RFC 7422||Deterministic port allocations||Deterministic port allocations (sequential algorithm only) can be obtained using the pool4’s
Please let us know if you find additional compliance issues or RFCs/drafts we’ve missed.
|Jool version||Supported Linux kernels (mainline)||Supported Linux kernels (RHEL)|
|master||3.2 - 3.19, 4.0 - 4.16||RHEL 7.0 - RHEL 7.4|
|3.6.0||3.13 - 3.19, 4.0 - 4.19||RHEL 7.0 - RHEL 7.5|
|3.5.7||3.2 - 3.19, 4.0 - 4.16||RHEL 7.0 - RHEL 7.4|
If you’re using a non-RHEL distribution (eg. Debian derivatives), execute
uname -r to print the kernel version you’re running. Suffixes rarely matter. Here’s an example from my running machine, which states that my running kernel is 4.15:
user@T:~$ /bin/uname -r 4.15.0-36-generic
RHEL-based distributions (such as Red Hat and CentOS) do not follow the normal kernel versioning conventions; use the third column instead.
A Jool instance can be attached to one of two different traffic-intercepting, plugin-enabling, kernel-based frameworks: Netfilter and iptables. Despite some documentation out there, these two are not the same thing; at least not from Jool’s point of view.
Netfilter is a bunch of hooks (
POSTROUTING) in the Linux kernel where modules can inject code. Whenever a packet reaches a hook, the kernel runs it through all the corresponding registered modules. Netfilter Jool instances hook themselves to
PREROUTING and as such intercept all incoming traffic (“pre”vious to “routing”) with the intent of translating it.
Netfilter Jool instances are simple to configure. However, they are also greedy. This is, since there is no matching conditional (other than “packets need to match the network namespace the instance exists in”), translation has overwhelming priority. Only packets that meet failure during translation are left untouched by a Netfilter instance. Jool attempts to translate everything, and the rest of the network subsystem gets the leftovers. Because of this, a careless Netfilter Jool configuration could deprive its own namespace of external network traffic.
There can only be one Netfilter SIIT Jool instance and one Netfilter NAT64 instance per network namespace.
Netfilter Jool instances start packet translation as soon as they are created. They drop packets deemed corrupted, translate packets which can be translated (according to their configuration) and return everything else to the kernel.
Netfilter plugins are not allowed to change the network protocol of their packets. Additionally, the kernel API does not export a means to post packets in the
FORWARD chain. For these reasons, successfully translated packets skip
FORWARD, going straight to
Be aware that this means that, because filtering normally happens during
FORWARD, if you want to firewall forwarding traffic, you should probably enclose Jool in a network namespace and filter during the
FORWARD boxes outside of it:
Alternatively, if you know what you’re doing, you can filter on mangle.
Until Jool 3.5, Netfilter used to be the only available operation mode, and partly because of this, it is also the default one today.
iptables is another packet-handling framework. It is built on top of Netfiter, and is mostly known for its NAT’ing and firewalling capabilities. In regards to this discussion, its most relevant feature is its match system–A means to specify which packets are handled by some “target” plugin.
If you’re familiar with the
iptables utility, you might be accustomed to the following syntax:
# iptables -t filter -A PREROUTING --destination 192.0.2.0/24 -j DROP
For anyone not in the knowing, that command adds a rule to iptables’ filter table, which “DROP”s all packets headed towards the
192.0.2 network. This happens during
PREROUTING. (Which is the same concept from Netfilter.)
iptables Jool is implemented as an ordinary iptables target. Thus,
# iptables -t mangle -A PREROUTING --destination 192.0.2.0/24 -j JOOL --instance potato
adds a rule to iptables’s mangle table, which “Jools” all packets headed towards the
192.0.2 network. This happens during
PREROUTING. Of all the Jool instances available in the current namespace, the translation is done by the one whose name is
There can be any number of iptables Jool instances in any namespace, and any number of iptables rules can reference them.
iptables Jool instances sit idle until some iptables rule sends packets to them. (Of course, only packets that match the rule’s conditions are sent.) They translate packets that can be translated according to their configuration, and drop everything else.
iptables Jool has a quirk similar to Netfilter Jool that you should be aware of: iptables rules are also not allowed to change the network protocol of their packets, so iptables Jool rules also send their matched and successfully translated packets straight to
POSTROUTING. Packets which do not match the rule continue through the chain normally.
iptables Jool first became available in Jool 3.6.0.