Re: IPv6 over an ipv4 tunnel

From: Olivier_Cochard-Labbé <olivier_at_freebsd.org>
Date: Fri, 04 Apr 2025 16:19:25 UTC
On Thu, Apr 3, 2025 at 10:36 PM Jack Raats <mlist@jarasoft.net> wrote:

> Hi,
>
> I have two servers, both running FreeBSD 14.2
>
> Server A has only one ipv4 address, no ipv6.
>
> Server B has one ipv4 address and an ipv6 subnet.
>
> Is it possible to give Server A an ipv6 address from server B ipv6
> subnet and ipv6 connectivity and how?
>
>
>
Server B needs to configure an NDP proxy to hide the fact that Server A is
behind it from the other hosts on this subnet.
Example:

hostA (epair10a) ---- (epair10b) hostB (epair11b) ---- (epair11a) hostC
             192.0.2.0/24                   2001:db8::/32

First, step through the basic setup:

ifconfig epair10 create
ifconfig epair11 create
jail -c name=hostA persist vnet vnet.interface=epair10a
jail -c name=hostB persist vnet vnet.interface=epair10b vnet
vnet.interface=epair11b
jail -c name=hostC persist vnet vnet.interface=epair11a
jexec hostA ifconfig epair10a inet 192.0.2.1/24 up
jexec hostB ifconfig epair10b inet 192.0.2.2/24 up
jexec hostB ifconfig epair11b inet6 2001:db8::2/32 up
jexec hostC ifconfig epair11a inet6 2001:db8::3/32 up

Now we want to create an IPv4 tunnel between hostA and hostB that will
encapsulate IPv6, while here we set address 2001:db8::1/32 to hostA.

kldload if_gif
jexec hostA ifconfig gif0 create
jexec hostA ifconfig gif0 tunnel 192.0.2.1 192.0.2.2 up
jexec hostA ifconfig gif0 inet6 2001:db8::1/32
jexec hostB ifconfig gif0 create
jexec hostB ifconfig gif0 tunnel 192.0.2.2 192.0.2.1 up
jexec hostB ifconfig gif0 inet6 -ifdisabled

Instruct hostA to use this new tunnel to exit all inet6 traffic:

jexec hostA route -6 add default 2001:db8::2

Instruct hostB how to reach hostA:

local=$(jexec hostA ifconfig gif0 inet6 | grep fe80 | cut -d ' ' -f 2)
jexec hostB route -6 add -host 2001:db8::1 $local

Checking current status, hostB should be able to ping hostA:

# jexec hostB ping -c2 -S 2001:db8::2 2001:db8::1
PING(56=40+8+8 bytes) 2001:db8::2 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim=64 time=0.505 ms
16 bytes from 2001:db8::1, icmp_seq=1 hlim=64 time=0.470 ms

--- 2001:db8::1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.470/0.488/0.505/0.017 ms

And now, enable the ndp proxy on hostB to impersonate hostA for other hosts
on the IPv6 subnet:

localmac=$(jexec hostB ifconfig epair11b ether | grep ether | cut -d ' ' -f
2)
jexec hostB ndp -s 2001:db8::1 $localmac proxy

But once hostB receives packets, it has to forward them to hostA, so you
need to enable forwarding on hostB:

jexec hostB sysctl net.inet6.ip6.forwarding=1

This will allow hostC to ping hostA:

# jexec hostC ping -c2 2001:db8::1
PING(56=40+8+8 bytes) 2001:db8::3 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim=63 time=0.509 ms
16 bytes from 2001:db8::1, icmp_seq=1 hlim=63 time=0.543 ms

--- 2001:db8::1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.509/0.526/0.543/0.017 ms

Regards,
Olivier