Subject: kern/34746: pf(4) synproxy state feature doesn't work with tag/tagged keywords
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Nino Dehne <ndehne@gmail.com>
List: netbsd-bugs
Date: 10/07/2006 18:05:00
>Number:         34746
>Category:       kern
>Synopsis:       pf(4)'s synproxy state breaks when used with tags
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Oct 07 18:05:00 +0000 2006
>Originator:     Nino Dehne
>Release:        4.99.3
>Organization:
>Environment:
System: NetBSD [...] 4.99.3 NetBSD 4.99.3 (KERNEL) #0: Thu Oct  5 00:54:03 CEST 2006  build@[...]:/tmp/wrap/HEAD/obj/x/s/n/HEAD/src/sys/arch/i386/compile/KERNEL i386
Architecture: i386
Machine: i386
>Description:
Using the synproxy state feature of pf together with the tag/tagged keywords
doesn't work.

This problem was reported for OpenBSD here:

http://archives.neohapsis.com/archives/openbsd/2005-04/0709.html

A patch was committed to the OpenBSD CVS repository later. I believe the
relevant diff is from 1.483 to 1.486 of OpenBSD's src/sys/dev/net/pf.c.
They fixed some other bug in 1.487 which I pulled in locally as well, beware
though.
>How-To-Repeat:
/etc/pf.conf:
	pass in  quick on $ext_if proto tcp from any to any port 22 flags S/SA \
		tag EXT-INT synproxy state (if-bound)
	pass out quick on $int_if tagged EXT-INT (if-bound)

The packet is not matched by the second rule.
>Fix:
Pull a diff for src/sys/net/pf.c from revision 1.483 to 1.486 from OpenBSD's
CVS repository. It applies with some offsets to our version and fixes the
problem for me.

A diff from 1.483 to 1.487 that applies cleanly is attached.

--EVF5PPMfhYS0aIcm
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pf.c.diff"

2c2
< /*	$OpenBSD: pf.c,v 1.483 2005/03/15 17:38:43 dhartmei Exp $ */
---
> /*	$OpenBSD: pf.c,v 1.487 2005/04/22 09:53:18 dhartmei Exp $ */
164c164
< 			    struct ether_header *, struct ifnet *);
---
> 			    u_int16_t, struct ether_header *, struct ifnet *);
1008c1008
< 		    TH_RST|TH_ACK, 0, 0, 0, 1, NULL, NULL);
---
> 		    TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
1471c1471
<     struct ether_header *eh, struct ifnet *ifp)
---
>     u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
1517a1518,1522
> 	if (rtag)
> 		if (pf_tag_packet(m, NULL, rtag)) {
> 			m_freem(m);
> 			return;
> 		}
2939c2944
< 			    r->return_ttl, 1, pd->eh, kif->pfik_ifp);
---
> 			    r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
3139c3144
< 			    TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, NULL, NULL);
---
> 			    TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
4115c4120
< 			    NULL, NULL);
---
> 			    0, NULL, NULL);
4153c4158
< 			    (*state)->src.mss, 0, 0, NULL, NULL);
---
> 			    (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
4168c4173
< 			    NULL, NULL);
---
> 			    (*state)->tag, NULL, NULL);
4173c4178
< 			    NULL, NULL);
---
> 			    0, NULL, NULL);
4179,4180d4183
< 			    (*state)->src.max_win;
< 			(*state)->dst.seqhi = (*state)->dst.seqlo +
4181a4185,4186
> 			(*state)->dst.seqhi = (*state)->dst.seqlo +
> 			    (*state)->src.max_win;
4452c4457
< 				    (*state)->rule.ptr->return_ttl, 1,
---
> 				    (*state)->rule.ptr->return_ttl, 1, 0,

--EVF5PPMfhYS0aIcm--

>Unformatted:
 --EVF5PPMfhYS0aIcm
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline