Static IPv6 host in a SLAAC LAN – ping works, SSH connection fails

My webserver is a VPS with a public /64 IPv6 subnet running FreeBSD with a couple of VNET jails for proxy server, application server and database server, and I would like to replicate the network configuration closely in my home network.

My OpenWrt router (GL.iNet Flint 2) was initially configured to advertise an IPv6 ULA prefix ([cmd]fd7d:9594:ca69::/48[/cmd]) to all LAN clients. One of these clients is the FreeBSD host to be used as a local web server. I added want a static IPv6 unicast route for the host like this:

config route6
        option interface 'lan'
        option target 'fdf4:aaff:c9ae:80e3::/64'
        option gateway 'fdf4:aaff:c9ae:80e3::1'

On the host, the /64 subnet is split into two /65 subnets, with the router's link-local address as the defaultrouter for the external interface igb1 (the second /65 subnet will be assigned to a bridge interface for bastille which is not configured yet). The config looks like this (/etc/rc.conf):

ifconfig_igb1_ipv6="inet6 fdf4:aaff:c9ae:80e3::1 prefixlen 65"
ipv6_defaultrouter="fe80::9683:c4ff:feaa:be4e%igb1"
ipv6_gateway_enable="YES"
ipv6_activate_all_interfaces="YES"

Now I can ping the host from any LAN client:

# ping6 fdf4:aaff:c9ae:80e3::1
PING6(56=40+8+8 bytes) fd7d:9594:ca69:0:88a:219e:6254:9311 --> fdf4:aaff:c9ae:80e3::1
16 bytes from fdf4:aaff:c9ae:80e3::1, icmp_seq=0 hlim=63 time=14.864 ms
16 bytes from fdf4:aaff:c9ae:80e3::1, icmp_seq=1 hlim=63 time=9.488 ms

and I can establish an SSH connection to the host from the router, but I cannot connect to the host via SSH (connection times out). tcpdump on the client (tcpdump -i en0 -vv 'tcp port 22 and host fdf4:aaff:c9ae:80e3::1') returns the following (the localhost address is mapped to eden.internal in /etc/hosts):

tcpdump: listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes
18:07:15.643543 IP6 (class 0xb8, flowlabel 0xd0f00, hlim 64, next-header TCP (6) payload length: 44) eden.internal.63497 > fdf4:aaff:c9ae:80e3::1.ssh: Flags [S], cksum 0x676d (correct), seq 3244949679, win 65535, options [mss 1440,nop,wscale 6,nop,nop,TS val 2550467794 ecr 0,sackOK,eol], length 0
18:07:15.654294 IP6 (flowlabel 0x1dcb4, hlim 63, next-header TCP (6) payload length: 40) fdf4:aaff:c9ae:80e3::1.ssh > eden.internal.63497: Flags [S.], cksum 0x5efb (correct), seq 36822196, ack 3244949680, win 65535, options [mss 1440,nop,wscale 8,sackOK,TS val 4015278889 ecr 2550467794], length 0
18:07:15.654394 IP6 (class 0xb8, flowlabel 0xd0f00, hlim 64, next-header TCP (6) payload length: 32) eden.internal.63497 > fdf4:aaff:c9ae:80e3::1.ssh: Flags [.], cksum 0x85a4 (correct), seq 1, ack 1, win 2053, options [nop,nop,TS val 2550467805 ecr 4015278889], length 0
18:07:15.655223 IP6 (class 0xb8, flowlabel 0xd0f00, hlim 64, next-header TCP (6) payload length: 54) eden.internal.63497 > fdf4:aaff:c9ae:80e3::1.ssh: Flags [P.], cksum 0xcaac (correct), seq 1:23, ack 1, win 2053, options [nop,nop,TS val 2550467805 ecr 4015278889], length 22: SSH: SSH-2.0-OpenSSH_10.2
18:07:15.776049 IP6 (class 0xb8, flowlabel 0xd0f00, hlim 64, next-header TCP (6) payload length: 54) eden.internal.63497 > fdf4:aaff:c9ae:80e3::1.ssh: Flags [P.], cksum 0xca32 (correct), seq 1:23, ack 1, win 2053, options [nop,nop,TS val 2550467927 ecr 4015278889], length 22: SSH: SSH-2.0-OpenSSH_10.2
18:07:16.009393 IP6 (class 0xb8, flowlabel 0xd0f00, hlim 64, next-header TCP (6) payload length: 54) eden.internal.63497 > fdf4:aaff:c9ae:80e3::1.ssh: Flags [P.], cksum 0xc949 (correct), seq 1:23, ack 1, win 2053, options [nop,nop,TS val 2550468160 ecr 4015278889], length 22: SSH: SSH-2.0-OpenSSH_10.2

On the router, the traffic is logged like this:

# tcpdump -i br-lan -vv -nn 'tcp port 22 and host fd7d:9594:ca69:0:88a:219e:6254:9311 and host fdf4:aaff:c9ae:80e3::1'
tcpdump: listening on br-lan, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:49:55.903696 IP6 (class 0xb8, flowlabel 0x30b00, hlim 64, next-header TCP (6) payload length: 44) fd7d:9594:ca69:0:88a:219e:6254:9311.50080 > fdf4:aaff:c9ae:80e3::1.22: Flags [S], cksum 0xb484 (correct), seq 3352321667, win 65535, options [mss 1440,nop,wscale 6,nop,nop,TS val 3928309193 ecr 0,sackOK,eol], length 0
09:49:55.903912 IP6 (class 0xb8, flowlabel 0x30b00, hlim 63, next-header TCP (6) payload length: 44) fd7d:9594:ca69:0:88a:219e:6254:9311.50080 > fdf4:aaff:c9ae:80e3::1.22: Flags [S], cksum 0xb484 (correct), seq 3352321667, win 65535, options [mss 1440,nop,wscale 6,nop,nop,TS val 3928309193 ecr 0,sackOK,eol], length 0
09:49:55.906682 IP6 (flowlabel 0xde79b, hlim 64, next-header TCP (6) payload length: 40) fdf4:aaff:c9ae:80e3::1.22 > fd7d:9594:ca69:0:88a:219e:6254:9311.50080: Flags [S.], cksum 0x8060 (correct), seq 771614619, ack 3352321668, win 65535, options [mss 1440,nop,wscale 8,sackOK,TS val 1941879742 ecr 3928309193], length 0
09:49:55.906725 IP6 (flowlabel 0xde79b, hlim 63, next-header TCP (6) payload length: 40) fdf4:aaff:c9ae:80e3::1.22 > fd7d:9594:ca69:0:88a:219e:6254:9311.50080: Flags [S.], cksum 0x8060 (correct), seq 771614619, ack 3352321668, win 65535, options [mss 1440,nop,wscale 8,sackOK,TS val 1941879742 ecr 3928309193], length 0

And finally, on the host:

# tcpdump -i igb1 -vv -nn 'tcp port 22 and host fd7d:9594:ca69:0:88a:219e:6254:9311'
tcpdump: listening on igb1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:17:10.254052 IP6 (class 0xb8, flowlabel 0x00800, hlim 64, next-header TCP (6) payload length: 54) fd7d:9594:ca69:0:88a:219e:6254:9311.65445 > fdf4:aaff:c9ae:80e3::1.22: Flags [P.], cksum 0x5a7e (correct), seq 1417288109:1417288131, ack 2278129201, win 2053, options [nop,nop,TS val 1910062500 ecr 1517251301], length 22: SSH: SSH-2.0-OpenSSH_10.2
09:17:10.457054 IP6 (flowlabel 0x97e30, hlim 64, next-header TCP (6) payload length: 1111) fdf4:aaff:c9ae:80e3::1.22 > fd7d:9594:ca69:0:88a:219e:6254:9311.65445: Flags [P.], cksum 0x74ef (incorrect -> 0x5005), seq 1:1080, ack 22, win 259, options [nop,nop,TS val 1517253563 ecr 1910061378], length 1079: SSH: SSH-2.0-OpenSSH_10.0 FreeBSD-20250801
09:17:11.418867 IP6 (class 0xb8, flowlabel 0x00800, hlim 64, next-header TCP (6) payload length: 54) fd7d:9594:ca69:0:88a:219e:6254:9311.65445 > fdf4:aaff:c9ae:80e3::1.22: Flags [P.], cksum 0x55f5 (correct), seq 0:22, ack 1, win 2053, options [nop,nop,TS val 1910063661 ecr 1517251301], length 22: SSH: SSH-2.0-OpenSSH_10.2
09:17:11.620062 IP6 (flowlabel 0x97e30, hlim 64, next-header TCP (6) payload length: 1111) fdf4:aaff:c9ae:80e3::1.22 > fd7d:9594:ca69:0:88a:219e:6254:9311.65445: Flags [P.], cksum 0x74ef (incorrect -> 0x4b7a), seq 1:1080, ack 22, win 259, options [nop,nop,TS val 1517254726 ecr 1910061378], length 1079: SSH: SSH-2.0-OpenSSH_10.0 FreeBSD-20250801

I noticed the messages referring to incorrect checksums, but I cannot interpret them – which aspect of the routing would cause incorrect checksums, and how can I fix it? When I revert the host back to SLAAC, I can establish SSH connections from any LAN client.

Are dumps from same event?

Please connect to your OpenWrt device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button (red circle; this works best in the 'Markdown' composer view in the blue oval):

Screenshot 2025-10-20 at 8.14.14 PM

Remember to redact passwords, VPN keys, MAC addresses and any public IP addresses you may have:

ubus call system board
cat /etc/config/network
cat /etc/config/wireless
cat /etc/config/dhcp
cat /etc/config/firewall

Thanks for the reply. I solved the problem in the meantime by matching the static route on the router with the interface configuration on the host: The router now has two routes to /65 subnets:

  • fdf4:aaff:c9ae:80e3::/65, gateway fdf4:aaff:c9ae:80e3::1
  • fdf4:aaff:c9ae:80e3:8000::/65, gateway fdf4:aaff:c9ae:80e3::1

I can successfully establish a SSH connection to the host via fdf4:aaff:c9ae:80e3::1.

Why do you cut a /64?

EDIT:
Everyone finding this thread: DO NOT DO THIS! Neither is subnetting a /64 into two /65 a good idea, nor is the other router for the /65 a "solution" of any problem. It is just another problem added.
With IPv6 the assumption is that subnet is always [0] is a /64 and SLAAC and NDP depend on that!

[0] Only valid exception is a /127 which just defines a unicast point to point link.

2 Likes

Why do you cut a /64?

What if a /64 is all I got, and I need to split it --- e.g. multiple addresses on my VPS, the 2 wireguard endpoints between the VPS and my OpenWRT router, and hosts here behind the router?

I use static addresses for all of that, so SLAAC and ND assumptions should not matter.

--
Ian

You cannot split a /64.
Yes, from a purely technical point of view you could (while still being strongly discouraged, OpenWrt won't stop you), but doing so breaks a lot of devices and software - among them anything google/ android/ chromeos related (as those insist on SLAAC, which exclusively works with /64 subnetting), but also many others.

2 Likes

I don't allow any of the devices you specifically listed on this network. It is ethernet only, for "real computers". And the computers are all Linux or FreeBSD. Guests get to use the wifi on the ISP router. And, so far, it works beautifully.

Can you refer me to a RFC that says I "MUST NOT" do this?

Have you done your research already?
The topic is covered in every IPv6 beginner guide.
I would need to dig it up too but would expect this in the address architecture RFC and where slaac is specified.

https://datatracker.ietf.org/doc/html/rfc7421 Analysis of the 64-bit Boundary in IPv6 Addressing from 2015

Thank you (though it has info status only). Will definitely read through.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.