Skip site navigation (1)Skip section navigation (2)
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>