From: Denis Fondras Subject: Re: IPv6 forward IPsec only To: Alexander Bluhm Cc: tech@openbsd.org Date: Wed, 3 Jul 2024 18:07:08 +0200 Le Wed, Jul 03, 2024 at 04:39:31PM +0200, Alexander Bluhm a écrit : > Hi, > > With sysctl net.inet.ip.forwarding=2 IPv4 packets are only forwarded > if they were processed by IPsec. Diff below implements the same > feature for IPv6. > > ok? > Thank you. Looks OK denis@ Some comments below. > bluhm > > Index: net/pf.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v > diff -u -p -r1.1200 pf.c > --- net/pf.c 2 Jul 2024 18:33:47 -0000 1.1200 > +++ net/pf.c 2 Jul 2024 19:26:01 -0000 > @@ -7986,14 +7986,20 @@ done: > break; > case AF_INET6: > if (pd.dir == PF_IN) { > - int flags; > + int flags = IPV6_REDIRECT; > > - if (ip6_forwarding == 0) { > + switch (ip6_forwarding) { > + case 2: > + SET(flags, IPV6_FORWARDING_IPSEC); > + /* FALLTHROUGH */ Should `case 2` be enclosed with `#ifdef IPSEC` ? > + case 1: > + SET(flags, IPV6_FORWARDING); > + break; > + default: > ip6stat_inc(ip6s_cantforward); > action = PF_DROP; > goto out; > } > - flags = IPV6_FORWARDING | IPV6_REDIRECT; > ip6_forward(pd.m, NULL, flags); > } else > ip6_output(pd.m, NULL, NULL, 0, NULL, NULL); > Index: net/pf_norm.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_norm.c,v > diff -u -p -r1.231 pf_norm.c > --- net/pf_norm.c 20 Jun 2024 19:25:42 -0000 1.231 > +++ net/pf_norm.c 2 Jul 2024 20:32:57 -0000 > @@ -1011,7 +1011,20 @@ pf_refragment6(struct mbuf **m0, struct > while ((m = ml_dequeue(&ml)) != NULL) { > m->m_pkthdr.pf.flags |= PF_TAG_REFRAGMENTED; > if (ifp == NULL) { > - ip6_forward(m, NULL, IPV6_FORWARDING); > + int flags = 0; > + > + switch (ip6_forwarding) { > + case 2: > + SET(flags, IPV6_FORWARDING_IPSEC); > + /* FALLTHROUGH */ > + case 1: > + SET(flags, IPV6_FORWARDING); > + break; > + default: > + ip6stat_inc(ip6s_cantforward); > + return (PF_DROP); > + } > + ip6_forward(m, NULL, flags); > } else if ((u_long)m->m_pkthdr.len <= ifp->if_mtu) { > ifp->if_output(ifp, m, sin6tosa(dst), rt); > } else { > Index: netinet6/ip6_forward.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v > diff -u -p -r1.119 ip6_forward.c > --- netinet6/ip6_forward.c 20 Jun 2024 19:25:42 -0000 1.119 > +++ netinet6/ip6_forward.c 2 Jul 2024 20:50:39 -0000 > @@ -315,6 +315,15 @@ reroute: > } > #endif > > +#ifdef IPSEC > + if (ISSET(flags, IPV6_FORWARDING) && > + ISSET(flags, IPV6_FORWARDING_IPSEC) && > + !ISSET(m->m_pkthdr.ph_tagsset, PACKET_TAG_IPSEC_IN_DONE)) { > + error = EHOSTUNREACH; > + goto senderr; > + } > +#endif > + > error = if_output_tso(ifp, &m, dst, rt, ifp->if_mtu); > if (error) > ip6stat_inc(ip6s_cantforward); > Index: netinet6/ip6_input.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v > diff -u -p -r1.263 ip6_input.c > --- netinet6/ip6_input.c 20 Jun 2024 19:25:42 -0000 1.263 > +++ netinet6/ip6_input.c 2 Jul 2024 20:19:43 -0000 > @@ -416,8 +416,14 @@ ip6_input_if(struct mbuf **mp, int *offp > SET(flags, IPV6_REDIRECT); > #endif > > - if (ip6_forwarding != 0) > + switch (ip6_forwarding) { > + case 2: > + SET(flags, IPV6_FORWARDING_IPSEC); > + /* FALLTHROUGH */ > + case 1: > SET(flags, IPV6_FORWARDING); > + break; No default ? > + } > > /* > * Without embedded scope ID we cannot find link-local > @@ -491,7 +497,7 @@ ip6_input_if(struct mbuf **mp, int *offp > * must be discarded, else it may be accepted below. > */ > KERNEL_LOCK(); > - error = ip6_mforward(ip6, ifp, m); > + error = ip6_mforward(ip6, ifp, m, flags); > KERNEL_UNLOCK(); > if (error) { > ip6stat_inc(ip6s_cantforward); > @@ -1442,7 +1448,7 @@ const struct sysctl_bounded_args ipv6ctl > #ifdef MROUTING > { IPV6CTL_MRTPROTO, &ip6_mrtproto, SYSCTL_INT_READONLY }, > #endif > - { IPV6CTL_FORWARDING, &ip6_forwarding, 0, 1 }, > + { IPV6CTL_FORWARDING, &ip6_forwarding, 0, 2 }, > { IPV6CTL_SENDREDIRECTS, &ip6_sendredirects, 0, 1 }, > { IPV6CTL_DEFHLIM, &ip6_defhlim, 0, 255 }, > { IPV6CTL_MAXFRAGPACKETS, &ip6_maxfragpackets, 0, 1000 }, > Index: netinet6/ip6_mroute.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_mroute.c,v > diff -u -p -r1.142 ip6_mroute.c > --- netinet6/ip6_mroute.c 7 Jun 2024 08:37:59 -0000 1.142 > +++ netinet6/ip6_mroute.c 2 Jul 2024 20:25:35 -0000 > @@ -122,8 +122,8 @@ int mcast6_debug = 1; > do { } while (0) > #endif > > -int ip6_mdq(struct mbuf *, struct ifnet *, struct rtentry *); > -void phyint_send6(struct ifnet *, struct ip6_hdr *, struct mbuf *); > +int ip6_mdq(struct mbuf *, struct ifnet *, struct rtentry *, int); > +void phyint_send6(struct ifnet *, struct ip6_hdr *, struct mbuf *, int); > > /* > * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static, > @@ -853,7 +853,7 @@ socket6_send(struct socket *so, struct m > * discard it. > */ > int > -ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) > +ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m, int flags) > { > struct rtentry *rt; > struct mif6 *mifp; > @@ -902,7 +902,7 @@ ip6_mforward(struct ip6_hdr *ip6, struct > > /* Entry exists, so forward if necessary */ > if (rt) { > - return (ip6_mdq(m, ifp, rt)); > + return (ip6_mdq(m, ifp, rt, flags)); > } else { > /* > * If we don't have a route for packet's origin, > @@ -997,7 +997,7 @@ mf6c_expire_route(struct rtentry *rt, u_ > * Packet forwarding routine once entry in the cache is made > */ > int > -ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt) > +ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int flags) > { > struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); > struct mif6 *m6, *mifp = (struct mif6 *)ifp->if_mcast6; > @@ -1085,7 +1085,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *if > m6->m6_pkt_out++; > m6->m6_bytes_out += plen; > > - phyint_send6(ifn, ip6, m); > + phyint_send6(ifn, ip6, m, flags); > if_put(ifn); > } while ((rt = rtable_iterate(rt)) != NULL); > > @@ -1093,7 +1093,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *if > } > > void > -phyint_send6(struct ifnet *ifp, struct ip6_hdr *ip6, struct mbuf *m) > +phyint_send6(struct ifnet *ifp, struct ip6_hdr *ip6, struct mbuf *m, int flags) > { > struct mbuf *mb_copy; > struct sockaddr_in6 *dst6, sin6; > @@ -1126,8 +1126,8 @@ phyint_send6(struct ifnet *ifp, struct i > /* XXX: ip6_output will override ip6->ip6_hlim */ > im6o.im6o_hlim = ip6->ip6_hlim; > im6o.im6o_loop = 1; > - error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o, > - NULL); > + error = ip6_output(mb_copy, NULL, NULL, flags | IPV6_FORWARDING, > + &im6o, NULL); > return; > } > > Index: netinet6/ip6_output.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v > diff -u -p -r1.291 ip6_output.c > --- netinet6/ip6_output.c 17 Apr 2024 20:48:51 -0000 1.291 > +++ netinet6/ip6_output.c 2 Jul 2024 20:45:07 -0000 > @@ -533,7 +533,7 @@ reroute: > */ > if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomain] && > (flags & IPV6_FORWARDING) == 0) { > - if (ip6_mforward(ip6, ifp, m) != 0) { > + if (ip6_mforward(ip6, ifp, m, flags) != 0) { > m_freem(m); > goto done; > } > @@ -641,6 +641,15 @@ reroute: > if_put(ifp); /* drop reference since destination changed */ > ifp = NULL; > goto reroute; > + } > +#endif > + > +#ifdef IPSEC > + if (ISSET(flags, IPV6_FORWARDING) && > + ISSET(flags, IPV6_FORWARDING_IPSEC) && > + !ISSET(m->m_pkthdr.ph_tagsset, PACKET_TAG_IPSEC_IN_DONE)) { > + error = EHOSTUNREACH; > + goto bad; > } > #endif > > Index: netinet6/ip6_var.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v > diff -u -p -r1.118 ip6_var.h > --- netinet6/ip6_var.h 20 Jun 2024 19:25:42 -0000 1.118 > +++ netinet6/ip6_var.h 2 Jul 2024 20:18:35 -0000 > @@ -270,6 +270,7 @@ ip6stat_add(enum ip6stat_counters c, uin > #define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */ > #define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */ > #define IPV6_REDIRECT 0x08 /* redirected by pf */ > +#define IPV6_FORWARDING_IPSEC 0x10 /* most of IPv6 header exists */ > The comment is copied from IPV6_FORWARDING ? > extern int ip6_mtudisc_timeout; /* mtu discovery */ > extern struct rttimer_queue icmp6_mtudisc_timeout_q; > @@ -316,7 +317,7 @@ int ip6_unknown_opt(struct mbuf **, u_in > int ip6_get_prevhdr(struct mbuf *, int); > int ip6_nexthdr(struct mbuf *, int, int, int *); > int ip6_lasthdr(struct mbuf *, int, int, int *); > -int ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *); > +int ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *, int); > int ip6_process_hopopts(struct mbuf **, u_int8_t *, int, u_int32_t *, > u_int32_t *); > void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **); >