Bug 284857 - wg(4): IPv4 packet with IPv6 nexthop not forwarded
Summary: wg(4): IPv4 packet with IPv6 nexthop not forwarded
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 15.0-CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: Kyle Evans
URL: https://reviews.freebsd.org/D49172
Keywords:
Depends on:
Blocks:
 
Reported: 2025-02-17 06:20 UTC by Lexi Winter
Modified: 2025-03-15 02:53 UTC (History)
6 users (show)

See Also:
kevans: mfc-stable14+
kevans: mfc-stable13-


Attachments
0001-wg-Unbreak-IPv4-routes-with-an-IPv6-next-hops.patch (785 bytes, patch)
2025-02-28 17:52 UTC, Marek Zarychta
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Lexi Winter freebsd_triage 2025-02-17 06:20:08 UTC
using src ~f5aff1871d3273b3cd3621ea5d3e37cdd807e66f on amd64.

example Ethernet route:

# ifconfig igc3
igc3: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
        description: fuchsia
        options=4e420bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,WOL_MAGIC,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6,HWSTATS,MEXTPG>
        ether 207c.14f3.d8f5
        inet6 fe80::1%igc3/64 scopeid 0x4
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
        nd6 options=1<PERFORMNUD>
# route -n get 81.187.47.195
   route to: 81.187.47.195
destination: 81.187.47.195
    gateway: fe80::2%igc3
        fib: 0
  interface: igc3
      flags: <UP,GATEWAY,HOST,DONE>
 recvpipe  sendpipe  ssthresh  rtt,msec    mtu        weight    expire
       0         0         0         0      1500         1         0 

ping works:

# ping -S 81.187.47.196 81.187.47.195
PING 81.187.47.195 (81.187.47.195) from 81.187.47.196: 56 data bytes
64 bytes from 81.187.47.195: icmp_seq=0 ttl=64 time=0.318 ms

example Wireguard route:

# ifconfig wg1
wg1: flags=10080c1<UP,RUNNING,NOARP,MULTICAST,LOWER_UP> metric 0 mtu 1420
        description: yarrow
        options=80000<LINKSTATE>
        inet6 fe80::1%wg1/64 scopeid 0xf
        groups: wg
        tunnelfib: 1
        nd6 options=101<PERFORMNUD,NO_DAD>
# route -n get 46.235.229.111
   route to: 46.235.229.111
destination: 46.235.229.111
    gateway: fe80::2%wg1
        fib: 0
  interface: wg1
      flags: <UP,GATEWAY,HOST,DONE>
 recvpipe  sendpipe  ssthresh  rtt,msec    mtu        weight    expire
       0         0         0         0      1420         1         0 

ping doesn't work:

# ping -S 81.187.47.196 46.235.229.111
PING 46.235.229.111 (46.235.229.111) from 81.187.47.196: 56 data bytes
ping: sendto: Address family not supported by protocol family
ping: sendto: Address family not supported by protocol family
ping: sendto: Address family not supported by protocol family

the wg interface is configured with "allowed ips: ::/0, 0.0.0.0/0" and is running over an IPv6 transport.

traffic forwarded via this system is also affected: any traffic via this route is silently dropped.
Comment 1 Marek Zarychta 2025-02-28 17:52:07 UTC
Created attachment 258107 [details]
0001-wg-Unbreak-IPv4-routes-with-an-IPv6-next-hops.patch

Tested in semi-production scenario:

[hamal] /usr/src_head# route add 10.0.0.x/32 -6 2001:db8:db8::1
add net 10.0.0.x: gateway 2001:db8:db8::1 fib 0
[hamal] /usr/src_head# route get 10.0.0.x
   route to: 10.0.0.x
destination: 10.0.0.x
    gateway: 2001:db8:db8::1
        fib: 0
  interface: wg1
      flags: <UP,GATEWAY,HOST,DONE,STATIC>
 recvpipe  sendpipe  ssthresh  rtt,msec    mtu        weight    expire
       0         0         0         0      1420         1         0
[hamal] /usr/src_head# ping -c 3 -S 172.19.3.5 10.0.0.x
PING 10.0.0.x (10.0.0.x) from 172.19.3.5: 56 data bytes
64 bytes from 10.0.0.x: icmp_seq=0 ttl=63 time=8.893 ms
64 bytes from 10.0.0.x: icmp_seq=1 ttl=63 time=8.515 ms
64 bytes from 10.0.0.x: icmp_seq=2 ttl=63 time=8.506 ms
 
--- 10.0.0.x ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 8.506/8.638/8.893/0.180 ms

Tested from recent 15.0-CURRENT to 14.2-STABLE on the remote endpoint. Both endpoints were patched. Without this patch, the test was falling as reported above.
Comment 2 commit-hook freebsd_committer freebsd_triage 2025-03-04 19:58:12 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=2bef0d54f74dad6962ef7d1dfa407e95cb4fb4ad

commit 2bef0d54f74dad6962ef7d1dfa407e95cb4fb4ad
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-03-04 19:57:34 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-03-04 19:57:34 +0000

    kern: wg: remove overly-restrictive address family check

    IPv4 packets can be routed via an IPv6 nexthop, so the handling of the
    parsed address family is more strict than it needs to be.  If we have a
    valid header that matches a known peer, then we have no reason to
    decline the packet.

    Convert it to an assertion that it matches the destination as viewed by
    the stack below it, instead.  `dst` may be the gateway instead of the
    destination in the case of a nexthop, so the `af` assignment must be
    switched to use the destination in all cases.

    Add a test case that approximates a setup like in the PR and
    demonstrates the issue.

    PR:             284857
    Reviewed by:    markj (earlier version), zlei
    Differential Revision:  https://reviews.freebsd.org/D49172

 sys/dev/wg/if_wg.c     |  8 ++---
 tests/sys/net/if_wg.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 5 deletions(-)
Comment 3 commit-hook freebsd_committer freebsd_triage 2025-03-15 02:53:11 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=7215aed7974cc4b7d3197ca5e5fcf545d3a28c0f

commit 7215aed7974cc4b7d3197ca5e5fcf545d3a28c0f
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-03-04 19:57:34 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-03-15 02:52:02 +0000

    kern: wg: remove overly-restrictive address family check

    IPv4 packets can be routed via an IPv6 nexthop, so the handling of the
    parsed address family is more strict than it needs to be.  If we have a
    valid header that matches a known peer, then we have no reason to
    decline the packet.

    Convert it to an assertion that it matches the destination as viewed by
    the stack below it, instead.  `dst` may be the gateway instead of the
    destination in the case of a nexthop, so the `af` assignment must be
    switched to use the destination in all cases.

    Add a test case that approximates a setup like in the PR and
    demonstrates the issue.

    PR:             284857
    Reviewed by:    markj (earlier version), zlei

    (cherry picked from commit 2bef0d54f74dad6962ef7d1dfa407e95cb4fb4ad)

 sys/dev/wg/if_wg.c     |  8 ++---
 tests/sys/net/if_wg.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 5 deletions(-)