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

Reply via email to