On Mon, Dec 07, 2020 at 01:00:05PM +0900, Yuichiro NAITO wrote:
> Hi.
>
> I have set up OpenBSD as a IPsec gateway and tried to forward IPv6 packets.
> But IPv6 packets are not forwarded via IPsec tunnel.
> IPv4 forwarding via IPsec works for me.
>
> Of course, I set following MIBs.
>
> net.inet.ip.forwarding=1
> net.inet6.ip6.forwarding=1
>
> I have confirmed ipsec policies by 'ipsecctl -sa'.
> Both SPD and SPA entries are good to me.
>
> In my investigation,
> IPv6 packets are forwarded by ip6_forward() function in ip6_forward.c.
> One of the arguments of ip6_forward() is "struct rtentry *rt" that will be
> NULL,
> if the packet is forwarded via IPsec tunnel.
> Because next hop information is written in SPD and not in the routing table.
>
> If rt is NULL, "rtisvalid(rt)" check is not satisfied,
> OpenBSD sends back network unreachable ICMP6 packet before
> ip6_output_ipsec_send().
>
> I have tried the following patch that makes dummy 'rt' to pass
> "rtisvalid(rt)” check
> and do the Scope check. It forwards IPv6 packets as I expected.
IPsec requires valid routing to work both for IPv6 and IPv4. At least you
need to have a default route that forwards the packet. The IPsec flow will
trigger on the output and "steal" the packets away.
Is there a reason why your IPv6 setup has no matching route that would
allow ip6_forward to work?
> diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
> index e47047e31f1..4dac045f243 100644
> --- a/sys/netinet6/ip6_forward.c
> +++ b/sys/netinet6/ip6_forward.c
> @@ -91,6 +91,7 @@ ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
> struct mbuf *mcopy = NULL;
> #ifdef IPSEC
> struct tdb *tdb = NULL;
> + struct rtentry rtent;
> #endif /* IPSEC */
> char src6[INET6_ADDRSTRLEN], dst6[INET6_ADDRSTRLEN];
>
> @@ -157,6 +158,17 @@ reroute:
> m_freem(m);
> goto freecopy;
> }
> + if (tdb != NULL && rt == NULL) {
> + /*
> + * If we try to forward via IPsec,
> + * create dummy rtent for scope check.
> + */
> + rt = &rtent;
> + memset(rt, 0, sizeof(rtent));
> + SET(rt->rt_flags, RTF_UP);
> + /* Do not match any existing interface */
> + memset(&rt->rt_ifidx, 0xff, sizeof(rt->rt_ifidx));
> + }
> }
> #endif /* IPSEC */
>
> @@ -302,6 +314,9 @@ reroute:
> /* tag as generated to skip over pf_test on rerun */
> m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
> srcrt = 1;
> +#ifdef IPSEC
> + if (rt != &rtent)
> +#endif /* IPSEC */
> rtfree(rt);
> rt = NULL;
> if_put(ifp);
> @@ -369,6 +384,9 @@ senderr:
> freecopy:
> m_freem(mcopy);
> out:
> +#ifdef IPSEC
> + if (rt != &rtent)
> +#endif /* IPSEC */
> rtfree(rt);
> if_put(ifp);
> }
>
> —
> Yuichiro NAITO
> [email protected]
>
>
>
>
--
:wq Claudio