How to route IPv4 via IPv6

Posted on 2020-02-10 by ungleich network

Imagine the following: you are running an IPv6 only network. And now someone asks you to pass IPv4 traffic through it, without tunneling it. Was sounds crazy at first, is actually quite feasible.

A short routing recap

Routers have routing tables. The routing tables basically say "if you receive a packet for this host, send it to that router".

IP routing

The important thing about this process is that the information on where to send it to, is not in the packet.

How to send IPv4 packets via IPv6

Because the next hop is not written into the IPv4 packet, the router is free to forward the packet via any method it thinks is the best. And if that happens to be IPv6 - well, it will forward the IPv4 packet via an IPv6 neighbour.

A practical example!

In the IPv6 only coworking network in the Digital Chalet, I can add an IPv4 default route via the IPv6 router:

[root@diamond ~]# ip route add 0/0 nexthop via inet6 fe80::21b:21ff:febb:6934 dev wlp0s20f3
[root@diamond ~]# ip r
default via inet6 fe80::21b:21ff:febb:6934 dev wlp0s20f3
[root@diamond ~]#

Now to be able to actually transmit IPv4 packets, I do need a source IPv4 address. In the current network I can use an address in the unused 10.0.8.0/22 network, however I'll add it with a /32 mask to make it clear that there is no interface local route applied:

[root@diamond ~]# ip addr add 10.0.8.42/32 dev wlp0s20f3
[root@diamond ~]# ip r
default via inet6 fe80::21b:21ff:febb:6934 dev wlp0s20f3
[root@diamond ~]# ip a sh dev wlp0s20f3
2: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 24:ee:9a:54:c3:bf brd ff:ff:ff:ff:ff:ff
    inet 10.0.8.42/32 scope global wlp0s20f3
       valid_lft forever preferred_lft forever
    inet6 2a0a:e5c0:0:4:c6ea:b1a8:ec14:6f35/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fe80::3b98:cb58:ed02:c25/64 scope link
       valid_lft forever preferred_lft forever
[root@diamond ~]#

And I can indeed ping another IPv4 address, routed via IPv6!

[root@diamond ~]# ping -4 10.0.8.3
PING 10.0.8.3 (10.0.8.3) 56(84) bytes of data.
64 bytes from 10.0.8.3: icmp_seq=1 ttl=64 time=2.37 ms
^C
--- 10.0.8.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.365/2.365/2.365/0.000 ms
[root@diamond ~]#

Why?

Why would anyone want to do this? It's quite easy: with this you can route an IPv4 address to an IPv6 only host. This enables IPv6 only resources to create and send IPv4 packets, even if they don't have IPv4 routes.

Do it yourself

If you don't believe us that it is possible, you can test it yourself on IPv6 only VMs on IPv6OnlyHosting.com.