Date: Sun, 27 May 2018 23:32:35 +0800 From: Julian Elischer <julian@freebsd.org> To: Jeff <freebsd@wagsky.com>, freebsd-ipfw@freebsd.org Subject: Re: Unexpected behavior ipfw check-state with count tag or call Message-ID: <a1c2f4e4-10e4-0de7-6d57-b01c1955560e@freebsd.org> In-Reply-To: <583c0634-c87c-5502-300b-6450253f71a7@wagsky.com> References: <583c0634-c87c-5502-300b-6450253f71a7@wagsky.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 27/5/18 9:03 am, Jeff wrote: > TL;DR > > If an ipfw rule's action is "count [tag]" or "call" and initiates a > keep-state, when the check-state is matched, the execution not only > performs the action of the original rule, but also the rule > number. This results in the "continuation" being not where the > check-state was executed but where the corresponding keep-state is > numbered. yes, that is executed though not really documented. > > Before I either file a ticket or start to work on the code or docs, > is this intended behavior? > > --- > > Context: > > IPv4 and NAT -- Capture the "established" connections on egress by use > of a "count tag XXX keep-state :out-ifN" rule. When a "return" packet > arrives, the "check-state :out-ifN" would then tag the packet XXX, > which could be used in identifying it as it flows through the firewall > as "expected from valid connection", even as its addr:port is modified. > You can't "accept keep-state" as the packet still needs NAT on the > way in. > > I've tried "count tag" as well as "call" to "tag ; return" with the > same > results, the "next" rule evaluated is the one following the keep-state > rule, not the check-state rule. > that is expected. the way it is implemented is that the dynamic rule is basically a shortcut to the action part of the static rule that made it. I didn't write it and it surprised me in the beginning but it can be useful as well sometimes. > (I've still got a couple other things I'm going to try as > work-arounds.) > > > Once I've got my rules running here, I'd like to tackle this, but I > don't know if this is a "documentation weakness", or perhaps > unintended behavior, based on the man pages and what I've been able to > find in the code. I know the man page and comments have grown > organically since I started using ipfw back in the 4.0 days and may > not be completely up-to-date. > > If there's any insight into intent of the code before I dive in, I'd > certainly appreciate it! > > Thanks, > > Jeff > > > > > > ipfw(8): > > check-state [:flowname | :any] > Checks the packet against the dynamic ruleset. If a > match is > found, execute the action associated with the rule which > generated this dynamic rule, otherwise move to the next > rule. > > "action associated with the rule" -- not the rule itself > > > > ip_fw_dynamic.c has some "interesting" comments: > > * Each dynamic rule holds a pointer to the parent ipfw rule so > * we know what action to perform. Dynamic rules are removed when > * the parent rule is deleted. This can be changed by dyn_keep_states > * sysctl. > * > * There are some limitations with dynamic rules -- we do not > * obey the 'randomized match', and we do not do multiple > * passes through the firewall. XXX check the latter!!! > > > > ip_fw2.c appears to the match/dispatch: > > 2191 /* > 2192 * Found dynamic entry, update stats > 2193 * and jump to the 'action' part of > 2194 * the parent rule by setting > 2195 * f, cmd, l and clearing cmdlen. > 2196 */ > > (I haven't pursued the code deeper yet) > > > > > Here are the rules used for confirming this behavior > > > 192.168.0.100 is the management interface > 10.0.0.100 is the "outside" interface, leading to the "true" gateway > 172.217.11.164 is an IP of www.google.com used to drive outside traffic > > 00001 reass > 00010 allow via lo0 > 00011 deny ip from 127.0.0.0/8 to any > 00012 deny ip from any to 127.0.0.0/8 > 00013 deny ip from ::1 to any > 00014 deny ip from any to ::1 > 00020 allow tcp from 192.168.0.100 22 to 192.168.0.100/24 via igb2 > 00021 allow tcp from 192.168.0.100/24 to 192.168.0.100 dst-port 22 > via igb2 > 00080 skipto 90 log proto tcp src-ip 10.0.0.100 via igb0 dst-ip > 172.217.11.164 dst-port 443 > 00081 skipto 90 log proto tcp src-ip 172.217.11.164 src-port 443 > dst-ip 10.0.0.100 via igb0 > 00092 skipto 2000 log not layer2 in > 00093 skipto 3000 log not layer2 out recv * > 00094 skipto 4000 log not layer2 out // not recv * > 00099 deny log // first-stage dispatch problem > 02000 count log // ip_input > 02100 count log tagged 40 > 02104 check-state :IP4_TAG_OUTER_outside log // "established" IPv4 > connections > 02500 count log // Inbound "NAT" of IPv4 > 02510 allow log tagged 40 // "established" IPv4 connections,post-NAT > 02999 deny log // ip_input -- DENY remaining > 03000 deny log // ip_output -- forwarded > 04000 count log // ip_output -- common output > 04204 count log // Outbound "NAT" > 04304 count log tag 40 xmit igb0 keep-state :IP4_TAG_OUTER_outside > 04400 allow log tagged 40 > 04999 deny log // ip_output -- common output -- DENY remaining > 65535 deny ip from any to any > > # First packet goes out, tagged keep-state at 4304, accepted at 4400 > > ipfw: 80 SkipTo 90 TCP 10.0.0.100:45427 172.217.11.164:443 out via igb0 > ipfw: 94 SkipTo 4000 TCP 10.0.0.100:45427 172.217.11.164:443 out via > igb0 > ipfw: 4000 Count TCP 10.0.0.100:45427 172.217.11.164:443 out via igb0 > ipfw: 4204 Count TCP 10.0.0.100:45427 172.217.11.164:443 out via igb0 > ipfw: 4304 Count TCP 10.0.0.100:45427 172.217.11.164:443 out via igb0 > ipfw: 4400 Accept TCP 10.0.0.100:45427 172.217.11.164:443 out via igb0 > > # Return packet comes back, check-state fires at 2104 (as expected) > # Action is logged as 4304 (location of the keep-state rule) > # Then continues at 4400 -- UNEXPECTED > > ipfw: 81 SkipTo 90 TCP 172.217.11.164:443 10.0.0.100:45427 in via igb0 > ipfw: 92 SkipTo 2000 TCP 172.217.11.164:443 10.0.0.100:45427 in via > igb0 > ipfw: 2000 Count TCP 172.217.11.164:443 10.0.0.100:45427 in via igb0 > ipfw: 2104 UNKNOWN TCP 172.217.11.164:443 10.0.0.100:45427 in via igb0 > ipfw: 4304 Count TCP 172.217.11.164:443 10.0.0.100:45427 in via igb0 > ipfw: 4400 Accept TCP 172.217.11.164:443 10.0.0.100:45427 in via igb0 > > [...] > > _______________________________________________ > freebsd-ipfw@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-ipfw > To unsubscribe, send any mail to "freebsd-ipfw-unsubscribe@freebsd.org" > >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?a1c2f4e4-10e4-0de7-6d57-b01c1955560e>