Date: Sun, 27 May 2018 23:41:43 +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: <dc6d2ded-59ea-8d50-adda-1b1a1bf0388b@freebsd.org> In-Reply-To: <a1c2f4e4-10e4-0de7-6d57-b01c1955560e@freebsd.org> References: <583c0634-c87c-5502-300b-6450253f71a7@wagsky.com> <a1c2f4e4-10e4-0de7-6d57-b01c1955560e@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On 27/5/18 11:32 pm, Julian Elischer wrote: > 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. #$%^%$ spellcheck... expected.. not executed. > >> >> 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" >> >> > > _______________________________________________ > 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?dc6d2ded-59ea-8d50-adda-1b1a1bf0388b>