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.

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]




Reply via email to