Bug 245190 - Ipfilter, statefull packet filtering - IPV6 UDP packets issue
Summary: Ipfilter, statefull packet filtering - IPV6 UDP packets issue
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 11.3-RELEASE
Hardware: i386 Any
: --- Affects Some People
Assignee: Cy Schubert
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-30 16:02 UTC by vlad
Modified: 2020-04-02 09:19 UTC (History)
1 user (show)

See Also:


Attachments
Backport of 11-STABLE MFCs (1.76 KB, patch)
2020-03-30 18:48 UTC, Cy Schubert
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description vlad 2020-03-30 16:02:44 UTC
Hi,   
I found a strange behavior with IPv6 udp packets, when ipfilter rules are configured for statefull packet filtering. OS - FreeBSD 11.3-Release, IP Filter: v5.1.2.
FreeBSD is configured as a router/firewall with dual stack IPv4/IPv6(tunnel-broker) 

This is a simple rule set, that can produce the issue:

ipfstat -in6
1 pass in quick on lo0 all
2 block in log quick from any to any with short
3 block in log quick from any to any with ipopts
4 skip 1 in inet6 proto tcp from any to any flags S/FSRA
5 block in quick proto tcp from any to any
6 block in log quick on re0 inet6 from any to any head 1000
7 block in log quick on gif0 inet6 from any to any head 2000
8 block in log quick inet6 from any to any

9 pass in quick inet6 from fe80::/10 to fe80::/10 group 1000
10 pass in quick inet6 from ff00::/8 to ff00::/8 group 1000
11 pass in quick inet6 from fe80::/10 to ff00::/8 group 1000
12 pass in quick inet6 from 2001:xxxx::/64 to any keep state group 1000
13 pass in quick inet6 from fe80::/10 to 2001:xxxx::1/128 keep state group 1000

14 block in log quick inet6 from pool/rfc5156-4291 to any group 2000
15 pass in quick inet6 proto ipv6-icmp from any to 2001:xxxx::2/128 icmp-type echo keep state group 2000
16 pass in quick inet6 proto ipv6-icmp from any to 2001:xxxx:/64 keep state group 2000
17 pass in quick inet6 proto udp from any to 2001:xxxx::/64 port 33433 >< 33601 keep state group 2000


 ipfstat -onh6
1 pass out quick on lo0 all
2 pass out quick on re0 inet6 from any to any keep state
3 pass out quick on gif0 inet6 from any to any keep state
4 block out log quick all

When setup the above rules, ipmon start showing events for blocked egress udp packets on gif0 (ntp, dns packets...) 
When I do traceroute6 from firewall host the packet was also blocked. Because somehow those packets doesn’t match the rule: 
pass out quick on gif0 inet6 from any to any keep state

and match 
block out log quick all

Ipmon generate event:
ipmon[1153]: 12:24:31.328486 gif0 @0:6 b 2001:xxxx::2,47011 -> 2a00:1450:4017:80a::2003,33435 PR udp len 40 60 OUT bad

Note: The event " @0:6 b " because there are IPv4 rules that also counts.

ipfstat -t6 do not show any udp state 

When I set
pass out quick on gif0 inet6 from any to any
the IPv6 udp packets match the rule, but this leads the need to add an ingress rule(e.g. stateless filtering)

This behavior happen only when IPv6 udp packets are sourced from the router/firewall.

When IPv6 udp packets are sourced from the inside IPv6 network(behind the router/firewall) udp packets match keep state rule and forwarded between interfaces correctly. Also states can be seen with ipfstat -t6


Can anyone reproduce or confirm this issue or bug.
Comment 1 Cy Schubert freebsd_committer 2020-03-30 18:15:31 UTC
An observation: best practice is to separate TCP and UDP keep state rules, with TCP keeping state with flags S/SAFR to avoid creating new state entries after TCP session handshake.

Regarding UDP "bad", these usually indicate bad checksum. I'll send you a DTrace script after work today.
Comment 2 Cy Schubert freebsd_committer 2020-03-30 18:32:45 UTC
The fix for this was MFCed to 11-STABLE in December by the following commits:

------------------------------------------------------------------------
r355795 | cy | 2019-12-15 18:38:47 -0800 (Sun, 15 Dec 2019) | 7 lines

MFC r355670:

Rather than pass the address of the packet information control block to
ipf_pcksum6(), directly pass the adddress of the mbuf to it. This reduces
one pointer dereference. ipf_pcksum6() doesn't use the packet information
control block except to obtain the mbuf address.

------------------------------------------------------------------------
r355785 | cy | 2019-12-15 13:28:08 -0800 (Sun, 15 Dec 2019) | 4 lines

MFC r355669:

in6_cksum() returns zero when checksums are good.

------------------------------------------------------------------------
r355306 | cy | 2019-12-02 13:00:29 -0800 (Mon, 02 Dec 2019) | 6 lines

MFC r355156:

Include fin, the packet information structure (fr_info_t), in the
l4sums DTrace probe, making more information available for the diagnosis
of IPv6 checksum errors.

------------------------------------------------------------------------

You have three options:

Apply the patches from the above MFCs, update to 11-STABLE, or wait for the 11.4-RELEASE.
Comment 3 Cy Schubert freebsd_committer 2020-03-30 18:48:35 UTC
Created attachment 212872 [details]
Backport of 11-STABLE MFCs

I'm not sure if this will apply or or if you will need prerequisites already MFCed to 11-STABLE. Try applying this with the -C flag. If it fails you will need more from 11-STABLE than just this.
Comment 4 vlad 2020-03-30 22:07:31 UTC
Thank you for the quick response and guidance. I'll check in coming days if patch would apply cleanly. 
Starting from your last comment.
I will return feedback.

Regards
Comment 5 vlad 2020-04-02 09:19:07 UTC
(In reply to Cy Schubert from comment #3)
Hello Cy, 
It Seems that everything is fine now.
I’ve patched fil.c, ip_fil.h, ip_fil_freebsd.c 
Rebuild/install kernel.
Then found, that also must buildworld, because ipfilter tools didn’t work as expected. 
After those steps IPv6 udp packets match the keep state. :)

Kind regards