Offering IPv4-only services over IPv6

Posted by Steve on Sun 29 Nov 2015 at 08:06

Although IPv6 is clearly the way of the future there are some software services which only support IPv4 access. Here we'll show a simple approach to exporting them to IPv6-based clients.

Although they are becoming rarer there are still some network services which don't support IPv6, which you might wish to use. I see examples of this reasonably often as a result of having a couple of virtual machines with IPv6-only connectivity.

There are a couple of different ways you can provide IPv6 support to IPv4-only systems, for example you can use NAT64 if you have a dual-homed server to act as a bridge, similarly you could sidestep the problem by running a small/local VPN giving your IPv6-only hosts a IPv4 address each.

As a simple solution though it is hard to beat the use of socat . The socat package is a program which will allow bi-direction data transfer, and supports many useful options.

Install it as per usual:

# aptitude install socat

Now we'll configure it to run - we'll assume we have a dual-stack system running Puppet on an IPv4-only address. Puppet is accessed over port 8140, so we want to make sure:

IPv6 connections to port 8140 are forwarded to 127.0.0.1:8140.

To do that we'll run this:

# socat TCP6-LISTEN:8140,reuseaddr,fork TCP4:127.0.0.1:8140

This will listen on the IPv6 port 8140, thanks to the use of TCP6-LISTEN , and traffic which comes in will be sent to 127.0.0.1:8140 , via TCP4 . Perfect.

As these are "high ports" this can be executed by any user, and doesn't need root-permissions. The example above will bind port 8140 on all available IPv6 addresses, if you prefer to listen upon a single address then you can add it explicitly:

~$ socat TCP6-LISTEN:8140,reuseaddr,fork,bind=[2001:41c8:123:123:123:123] TCP4:127.0.0.1:8140

Because this is a simple one-line command it is pretty simple to turn into a service. If you're running systemd, for example, you can create the file /lib/systemd/system/puppet-proxy.service with the following content:

[Unit] Description=Puppet Proxy Application [Service] User=puppet ExecStart=/usr/bin/socat TCP6-LISTEN:8140,reuseaddr,fork TCP4:127.0.0.1:8140 [Install] WantedBy=multi-user.target

With that file saved you enable it, and start it, via:

# systemctl enable puppet-proxy.service # systemctl start puppet-proxy.service

Note that I'm explicitly specifying a user to run the command as, via the " User=puppet " line. There's no reason to run socat as root, and it is best avoided.

I should also note that I'm not intending to pick on puppet here. The puppet server/master does support IPv6 natively, although historically there have been many users who had problems running a master upon both IPv6 and IPv4.

Finally it should be noted that by swapping the arguments around you can provide services in the reverse direction - using socat to proxy from IPv4 to IPv6 systems.