> 2020/12/07 16:47、Claudio Jeker <[email protected]>のメール:
> 
> 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.

There are 2 destination addresses for IPsec.
The inner packet destination address is written in the encapsulated packet and
the final address to be delivered.
The outer packet destination address is peer address of IPsec tunnel.

Do you mean that I have to set the routing table entry for the inner packet
destination address?

When I set a default route of IPv6, IPv6 packets are forwarded via IPsec.
So it sounds strange to me but necessary for me.

> Is there a reason why your IPv6 setup has no matching route that would
> allow ip6_forward to work?

My case of IPv6 network is for testing how iked(8) works.
So all routing tables are set by manual.

And when I set up OpenBSD that is not allowed to connect to the Internet,
I won't set a default gateway for a security reason.

>> 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

—
Yuichiro NAITO
[email protected]




Reply via email to