Enabling IPv6 support for IPv4-only apps on Linux

By on 21 Jun 2023

Category: Tech matters

Tags: , , , ,

1 Comment

Blog home

To prove that IPv6 is ready for production use, I’ve been using an IPv6-only setup on my Ubuntu PC for more than four months. To access the legacy IPv4 Internet, I use a NAT64 gateway based on Tayga deployed on a RockPro64 SBC in my cupboard:

Figure 1 — The RockPro64 is an ARM64-based SBC with a dedicated 1G Ethernet and PCI-E slot.
Figure 1 — The RockPro64 is an ARM64-based SBC with a dedicated 1G Ethernet and PCI-E slot.

Most of the apps I use support IPv6 but there are some cases when a lack of IPv4 connectivity on my machine negatively affects the experience.

One of the cases that affect my daily experience is the constant need to manually prepend IPv4 addresses for SSH as direct attempts to use SSH with an IPv4 address fail:

ssh: connect to host port 22: Network is unreachable

Instead, I have to constantly append my IPv6 NAT64 prefix:

ssh 64:ff9b::
pavel@64:ff9b::103:307's password:

Luckily, Linux provides an exceptionally easy way to intercept some specific library functions using a simple dynamically linked library: LD_PRELOAD.

Figure 2 — LD_PRELOAD allows us to override some functions with our own logic.
Figure 2 — LD_PRELOAD allows us to override some functions with our own logic.

When an app needs to connect to the network it uses Linux system functions such as socket(), connect(), getpeername(), and getsockname(), and by overriding them with functions that explicitly transform all IPv4 connection attempts to special IPv6 addresses crafted using a NAT64 prefix, we can automatically add IPv6 support for apps with IPv6 support.

Thankfully, that’s exactly how a tool called TNAT64 works. You can find this tool in the Debian or Ubuntu official repositories and installation is easy:

sudo apt install -y tnat64

TNAT64 provides a single dynamic library available on the following path:


To enable it for a specific session in the terminal, we need to run the following commands:

export LD_PRELOAD=/usr/lib/tnat64/libtnat64.so TNAT64_DEBUG=10 TNAT64_DEBUG_FILE=/tmp/tnat64.log

The only mandatory requirement here is that LD_PRELOAD, TNAT64_DEBUG, and TNAT64_DEBUG_FILE enable debugging to provide more information on how this library works.

After that, when you run any app in the same terminal session it will load libtnat64.so first. Then all calls to network functions will be intercepted, and as a consequence, any attempt to connect to IPv4 will work just fine even on a machine without external IPv4 connectivity:

pavel@'s password:

I recommend using this approach only for apps with clear IPv6 support issues. Attempts to enable this logic may lead to some issues as some apps may have issues with syscalls.

To get more information about the runtime activity of TNAT64 you can check the content of its log file /tmp/tnat64.log:

Figure 3 —  The TNAT64 log file.
Figure 3 — The TNAT64 log file.

Our global current success with IPv6 deployment is the result of a colossal amount of work over the last two decades from an incredible number of very talented engineers. I’d like to acknowledge the author of TNAT64, Andrej Shadura, which was written around 2011.

Pavel Odintsov is a software engineer with a passion for computer networks, having worked in domain registry, cloud hosting, Internet exchange, and global cyber security. He is the technical lead of the FastNetMon project.

Adapted from the original at Pavel’s blog.

Rate this article
Discuss on Hacker News

The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.

One Comment

  1. Andrej Shadura


    Great to see my old project getting some publicity
    Just a note: the package also ships a shell script to automatically preload the library. Also, there’s been some recent development in Git, but I would welcome help reviewing contributions, since I’m quite busy with other things these days.



Leave a Reply

Your email address will not be published. Required fields are marked *