Index | Thread | Search

From:
Denis Fondras <denis@openbsd.org>
Subject:
Re: IPv6 forward IPsec only
To:
Alexander Bluhm <bluhm@openbsd.org>
Cc:
tech@openbsd.org
Date:
Wed, 3 Jul 2024 18:07:08 +0200

Download raw body.

Thread
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 **);
>