Documentation > Introduction > What is Jool?

Introduction to Jool


  1. Overview
  2. Compliance
  3. Compatibility
  4. Design


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 4:

RFC/draft Reminder name Status
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 --mark argument (mark-src-range ip6tables plugin suggested).

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.13 - 3.19
4.0 - 4.20
RHEL 7.0 - RHEL 7.5
4.0.1 3.13 - 3.19
4.0 - 4.20
RHEL 7.0 - RHEL 7.5
3.5.8 3.2 - 3.19
4.0 - 4.18
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

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 (PREROUTING, LOCALIN, FORWARD, LOCALOUT and 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 POSTROUTING:

Fig.1 - Jool within Netfilter

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:

Fig.2 - Jool and Filtering

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 -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 -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 potato.

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 4.0.0.