mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
ip: Defer checks for an unspecified dstaddr until after pfil hooks
To comply with Common Criteria certification requirements, it may be
necessary to ensure that packets to 0.0.0.0/::0 are dropped and logged
by the system firewall. Currently, such packets are dropped by
ip_input() and ip6_input() before reaching pfil hooks; let's defer the
checks slightly to give firewalls a chance to drop the packets
themselves, as this gives better observability. Add some regression
tests for this with pf+pflog.
Note that prior to commit 713264f6b8, v4 packets to the unspecified
address were not dropped by the IP stack at all.
Note that ip_forward() and ip6_forward() ensure that such packets are
not forwarded; they are passed back unmodified.
Add a regression test which ensures that such packets are visible to
pflog.
Reviewed by: glebius
MFC after: 3 weeks
Sponsored by: Klara, Inc.
Sponsored by: OPNsense
Differential Revision: https://reviews.freebsd.org/D48163
This commit is contained in:
parent
886396f1b1
commit
40faf87894
4 changed files with 97 additions and 8 deletions
|
|
@ -521,11 +521,6 @@ ip_input(struct mbuf *m)
|
|||
goto bad;
|
||||
}
|
||||
}
|
||||
/* The unspecified address can appear only as a src address - RFC1122 */
|
||||
if (__predict_false(ntohl(ip->ip_dst.s_addr) == INADDR_ANY)) {
|
||||
IPSTAT_INC(ips_badaddr);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
|
||||
sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
|
||||
|
|
@ -641,6 +636,17 @@ tooshort:
|
|||
}
|
||||
}
|
||||
passin:
|
||||
/*
|
||||
* The unspecified address can appear only as a src address - RFC1122.
|
||||
*
|
||||
* The check is deferred to here to give firewalls a chance to block
|
||||
* (and log) such packets. ip_tryforward() will not process such
|
||||
* packets.
|
||||
*/
|
||||
if (__predict_false(ntohl(ip->ip_dst.s_addr) == INADDR_ANY)) {
|
||||
IPSTAT_INC(ips_badaddr);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process options and, if not destined for us,
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ ip6_tryforward(struct mbuf *m)
|
|||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
|
||||
IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst) ||
|
||||
IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) ||
|
||||
in6_localip(&ip6->ip6_dst))
|
||||
return (m);
|
||||
|
|
|
|||
|
|
@ -621,10 +621,10 @@ ip6_input(struct mbuf *m)
|
|||
IP_PROBE(receive, NULL, NULL, ip6, rcvif, NULL, ip6);
|
||||
|
||||
/*
|
||||
* Check against address spoofing/corruption.
|
||||
* Check against address spoofing/corruption. The unspecified address
|
||||
* is checked further below.
|
||||
*/
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
|
||||
/*
|
||||
* XXX: "badscope" is not very suitable for a multicast source.
|
||||
*/
|
||||
|
|
@ -749,6 +749,17 @@ ip6_input(struct mbuf *m)
|
|||
}
|
||||
|
||||
passin:
|
||||
/*
|
||||
* The check is deferred to here to give firewalls a chance to block
|
||||
* (and log) such packets. ip6_tryforward() will not process such
|
||||
* packets.
|
||||
*/
|
||||
if (__predict_false(IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst))) {
|
||||
IP6STAT_INC(ip6s_badscope);
|
||||
in6_ifstat_inc(rcvif, ifs6_in_addrerr);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disambiguate address scope zones (if there is ambiguity).
|
||||
* We first make sure that the original source or destination address
|
||||
|
|
|
|||
|
|
@ -195,9 +195,80 @@ state_max_cleanup()
|
|||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "unspecified_v4" "cleanup"
|
||||
unspecified_v4_head()
|
||||
{
|
||||
atf_set descr 'Ensure that packets to the unspecified address are visible to pfil hooks'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
unspecified_v4_body()
|
||||
{
|
||||
pflog_init
|
||||
|
||||
vnet_mkjail alcatraz
|
||||
jexec alcatraz ifconfig lo0 inet 127.0.0.1
|
||||
jexec alcatraz route add default 127.0.0.1
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
jexec alcatraz ifconfig pflog0 up
|
||||
pft_set_rules alcatraz "block log on lo0 to 0.0.0.0"
|
||||
|
||||
jexec alcatraz tcpdump -n -e -ttt --immediate-mode -l -U -i pflog0 >> pflog.txt &
|
||||
sleep 1 # Wait for tcpdump to start
|
||||
|
||||
atf_check -s not-exit:0 -o ignore -e ignore \
|
||||
jexec alcatraz ping -S 127.0.0.1 -c 1 0.0.0.0
|
||||
|
||||
atf_check -o match:".*: block out on lo0: 127.0.0.1 > 0.0.0.0: ICMP echo request,.*" \
|
||||
cat pflog.txt
|
||||
}
|
||||
|
||||
unspecified_v4_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "unspecified_v6" "cleanup"
|
||||
unspecified_v6_head()
|
||||
{
|
||||
atf_set descr 'Ensure that packets to the unspecified address are visible to pfil hooks'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
unspecified_v6_body()
|
||||
{
|
||||
pflog_init
|
||||
|
||||
vnet_mkjail alcatraz
|
||||
jexec alcatraz ifconfig lo0 up
|
||||
jexec alcatraz route -6 add ::0 ::1
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
jexec alcatraz ifconfig pflog0 up
|
||||
pft_set_rules alcatraz "block log on lo0 to ::0"
|
||||
|
||||
jexec alcatraz tcpdump -n -e -ttt --immediate-mode -l -U -i pflog0 >> pflog.txt &
|
||||
sleep 1 # Wait for tcpdump to start
|
||||
|
||||
atf_check -s not-exit:0 -o ignore -e ignore \
|
||||
jexec alcatraz ping -6 -S ::1 -c 1 ::0
|
||||
|
||||
cat pflog.txt
|
||||
atf_check -o match:".*: block out on lo0: ::1 > ::: ICMP6, echo request,.*" \
|
||||
cat pflog.txt
|
||||
}
|
||||
|
||||
unspecified_v6_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "malformed"
|
||||
atf_add_test_case "matches"
|
||||
atf_add_test_case "state_max"
|
||||
atf_add_test_case "unspecified_v4"
|
||||
atf_add_test_case "unspecified_v6"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue