On Thu, May 21, 2015 at 11:07 +0200, Alexandr Nedvedicky wrote: > Hello, > > > On Tue, May 19, 2015 at 14:07 +0200, Alexandr Nedvedicky wrote: > > > Hello Mike, > > > > > > I've reworked patch from yesterday. I've done some quick testing > > > to see if it fixes problem. It looks like it works. I have not > > > tested NAT-64 yet. Also I'd like to come up with test case, which > > > will show the state check is still able to block invalid ICMP packet > > > (invalid with respect to state). > > > > > > The idea of fix is to keep icmp_dir in state as well. The icmp_dir > > > indicates whether state got created by ICMP request or response. > > > This is useful later in pf_icmp_state_lookup() to check whether > > > ICMP request/response matches state direction. > > > > > > > This feels slightly convoluted... check my diff out! (: > > nice, I like your "XOR Magic!" comment.
(: > Looks like I was trying to fix the other end... And you were not wrong. > your patch is minimalistic and correct as far as I can tell. > Well, not entirely (: I did it while exploring the code and sent out to provoke further discussion. Today I've talked to reyk@ and we think that it's better to go down a different road: make sure we don't create states on reply packets in the first place. Please consider the following: unless sloppy state tracking is used, TCP states can only be set up by the first SYN packet (ok, ok, it's because of "flags S/SA", but that is largely irrelevant nowadays since "S/SA" is now the default and nobody is doing "flags any"). ICMP was made to adhere to a stricter set of rules and recently I've added sloppy handling there so perhaps we should just prevent state creation for replies (icmp_dir == PF_OUT)? If that is not what sysadmin wants he can always specify "keep state (sloopy)" and move on with his/her life. I've tested this with ICMP, ICMPv6 and NAT64 (slightly). Any OKs? Objections? diff --git sys/net/pf.c sys/net/pf.c index 39d5cb6..dbc8707 100644 --- sys/net/pf.c +++ sys/net/pf.c @@ -3201,10 +3201,15 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm, PF_TEST_ATTRIB((r->type && r->type != icmptype + 1), TAILQ_NEXT(r, entries)); /* icmp only. type always 0 in other cases */ PF_TEST_ATTRIB((r->code && r->code != icmpcode + 1), TAILQ_NEXT(r, entries)); + /* icmp only. don't create states on replies */ + PF_TEST_ATTRIB((r->keep_state && !state_icmp && + (r->rule_flag & PFRULE_STATESLOPPY) == 0 && + icmp_dir != PF_IN), + TAILQ_NEXT(r, entries)); break; default: break; }