Why? Imagine you have an IPv6-only VM on an IPv4 and IPv6 enabled Host, or for some reason IPv4 is routed differently on the VM than IPv6 (think VPN). Then you want to access your VM from an IPv4-only internet access point. Pretty much impossible, you’d think. But fear not! socat comes to rescue 🙂
SOcket CAT is the swiss army knife for network sockets, even when iptables can’t help you any more:
socat TCP4-LISTEN:<LPORT>,fork TCP6:[2001:db8::8]:<DPORT>
<LPORT> is the listen port on the Host. It can be anything, but if you want to run socat as a non-privileged user, it should be > 1024. <DPORT> is the destination port on the IPv6-only VM to forward <LPORT> to. Of course this is not arbitrary. The parameter fork makes socat keep listening after a connection is established. Otherwise it would exit after the connection is closed.
A systemd-unit would look like this:
[Unit] Description=Forward Port to IPv6 Requires=sys-subsystem-net-devices-br0.device After=sys-subsystem-net-devices-br0.device [Service] User=nobody ExecStart=/usr/bin/socat TCP4-LISTEN:44444,fork TCP6:[2001:db8::8]:3389 [Install] WantedBy=multi-user.target
The Requires and After order the service after the network bridge (br0) for your VM. Change it accordingly.
If your use case would be RDP (like above), and your favorite RDP client is rdpk, you can add a Host <IPv4-Address-of-Host>:44444 to rdpk and be done! Luckily rdpk passes the Hostname verbatim to xfreerdp /v: 🙂