With 'scrub fragment reassemble' if a packet contains multiple IPv6
fragment headers we would reassemble the packet and immediately
continue processing it.
That is, we'd remove the first fragment header and expect the next
header to be a final header (i.e. TCP, UDP, ICMPv6, ...). However, if
it's another fragment header we'd not treat the packet correctly.
That is, we'd fail to recognise the payload and treat it as if it were
an IPv6 fragment rather than as its actual payload.
Fix this by restarting the normalisation on the reassembled packet.
If there are multiple fragment headers drop the packet.
Reported by: Enrico Bassetti bassetti@di.uniroma1.it (NetSecurityLab @ Sapienza University of Rome)
MFC after: instant
Sponsored by: Rubicon Communications, LLC ("Netgate")
Support NAT-ing SCTP connections.
This is mostly similar to UDP and TCP, but we refuse to change ports for
SCTP, to avoid interfering with multihomed connections.
As a result we also never copy the SCTP header back or recalculate
checksums as we'd do for TCP or UDP (because we don't modify the header
for SCTP).
We do use the existing pf_change_ap() function to modify the packet,
because we may still need to update the IPv4 header checksum.
Reviewed by: tuexen
MFC after: 3 weeks
Sponsored by: Orange Business Services
Differential Revision: https://reviews.freebsd.org/D40866
Send an SCTP Abort message if we're refusing a connection, just like we
send a RST for TCP.
MFC after: 3 weeks
Sponsored by: Orange Business Services
Differential Revision: https://reviews.freebsd.org/D40864
Basic state tracking for SCTP. This means we scan through the packet to
identify the different chunks (so we can identify state changes).
MFC after: 3 weeks
Sponsored by: Orange Business Services
Differential Revision: https://reviews.freebsd.org/D40862
This function is always available, even if the SCTP or SCTP_SUPPORT options
are not set.
That lets us remove an ifdef, and also means we improve pf's SCTP handling
when the options are not set.
MFC after: 3 weeks
Sponsored by: Orange Business Services
Differential Revision: https://reviews.freebsd.org/D40911
Actions applied to a processed packet come in case of stateless
firewalling from a rule or in case of statefull firewalling from a
state. The state obtains the actions from a rule when it is created by a
rule or by pfsync. The logic for deciding if actions come from a rule or
a state is spread across many places in pf.
There already is struct pf_rule_actions in struct pf_pdesc and thus it
can be used as a central place for storing actions and their parameters.
OpenBSD does something similar: they also store the actions in struct
pf_pdesc and have no variables in pf_test() but they use separate
variables instead of a structure. By using struct pf_rule_actions we can
simplify the code even further. Applying of actions is done *only* in
pf_rule_to_actions() no matter if for the legacy scrub rules or for the
normal match / pass rules. The logic of choosing if rule or state
actions are used is applied only once in pf_test() by copying the whole
struct.
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D41009
The variable storing the direction of a processed packet is passed
around to many functions. Most of those functions already have a pointer
to struct pf_pdesc which also contains the direction. By using the one
in struct pf_pdesc we can reduce the amount of arguments passed around.
Reviewed by: kp
Sponsored by: InnGames GmbH
Differential Revision: https://reviews.freebsd.org/D41008
Explicitly add pfsync as a know upper layer protocol so we don't
automatically discard pfsync packets (carried over IPv6).
net.inet6.ip6.fw.deny_unknown_exthdrs defaults to 1, so even if
net.inet.ip.fw.default_to_accept is set to 1 we'd discard pfsync (over
IPv6).
Reviewed by: ae
Differential Revision: https://reviews.freebsd.org/D40973
This is disabled by default since it potentially changes the behavior of
existing filter rule sets. To enable this extra filter for packets being
delivered locally, use:
sysctl net.pf.filter_local=1
service pf restart
PR: 268717
Reviewed-by: kp
MFC-after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D40373
Remove the name conflict between the pfsync_defer_tmo variable and
function.
This worked fine in kernels with VIMAGE (the default), but not in those
without.
Reported by: des@
Sponsored by: Rubicon Communications, LLC ("Netgate")
Add the net.pfsync.defer_delay sysctl to allow the defer timeout (i.e.
how long pf holds onto packets waiting for the peer to ack the new
state) to be changed.
This is intended to make testing of the defer code more robust, by
allowing longer timeouts to mitigate scheduling/measurement jitter.
Sponsored by: Rubicon Communications, LLC ("Netgate")
The value stored in pf_mtag->tag comes from "tag" and "match tag"
keywords in pf.conf and must not be abused for storing other
information. A ruleset with enough tags could set or remove the bits
responsible for PF_TAG_SYNCOOKIE_RECREATED.
Move this syncookie status to pf_mtag->flags. Rename this and other
related constants in a way that will prevent such mistakes in the
future. Move PF_REASSEMBLED constant to mbuf.h and rename accordingly
because it's not a flag stored in pf_mtag, but an identifier of a
different m_tag. Change the value of the constant to avoid conflicts
with other m_tags using MTAG_ABI_COMPAT.
Rename the variables in pf_build_tcp() and pf_send_tcp() in to reduce
confusion.
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D40587
Use the already populated PFE_SKIP_DST_ADDR and extend the skip
infrastructure to also skip on IP source/destination addresses.
This should make evaluating the rules slightly faster.
Reported by: R. Christian McDonald <rcm@rcm.sh>
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D40567
When we clean up a wf2q+ queue we need to ensure that we remove it from
the correct heap. If we leave a queue pointer behind in an unexpected
heap we'll later write to it, causing a use-after-free and unpredictable
panics.
Teach the dummynet heap code to verify that we're removing the correct
object so we can safely attempt to remove objects not contained in the
heap.
Remove a to-be-removed queue from all heaps.
Also don't continue the enqueue function if we're not finding the queue
on the idle heap as we'd expect.
While here also remove the empty heap warning, because this is now
expected to happen.
See also: https://redmine.pfsense.org/issues/14433
Sponsored by: Rubicon Communications, LLC ("Netgate")
If we route-to (or dup-to/reply-to) we re-run pf_test(), which will also
create states for the connection.
This means that we may end up matching a different (i.e. not the state
that was created by the route-to rule) state, without the attributes
(such as dummynet pipes/queues) set by the route-to rule.
Address this by inheriting the pf_rule_actions from the route-to rule
while evaluating the connection again in pf_test(). That is, we set
default pf_rule_actions based on the route-to rule for the new
evaluation. The new rule may still overrule these, but if it does not
have such actions the route-to actions are applied.
Do the same for IPv6 rules in pf_test6()/pf_route6().
See also: https://redmine.pfsense.org/issues/14039
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D40340
Make struct pfsync_state contents configurable by sending out new
versions of the structure in separate subheader actions. Both old and
new version of struct pfsync_state can be understood, so replication of
states from a system running an older kernel is possible. The version
being sent out is configured using ifconfig pfsync0 … version XXXX. The
version is an user-friendly string - 1301 stands for FreeBSD 13.1 (I
have checked synchronization against a host running 13.1), 1400 stands
for 14.0.
A host running an older kernel will just ignore the messages and count
them as "packets discarded for bad action".
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39392
In the Ethernet rules we held the PF_RULES lock while we called
ip_dn_io_ptr() (i.e. dummynet). That meant that we could end up back in
pf while still holding the PF_RULES lock.
That's not immediately fatal, because that lock is recursive, but still
not ideal.
There also appear to be scenarios where this can actually trigger
deadlocks.
We don't need to hold the PF_RULES lock, as long as we make a local copy
of the data we need from the rule (in this case, the action and
bridge_to target). It's safe to keep the struct ifnet pointer around,
because we remain in NET_EPOCH.
See also: https://redmine.pfsense.org/issues/14373
MFC after: 1 week
Reviewed by: mjg
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D40067
State deletions are sent over pfsync using struct pfsync_del_c.
Remove the code for receiving state deletions using struct pfsync_state
as such deletions are never sent. Rename functions and constants so that
only the "compressed" versions remain.
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D40004
The SPDX folks have obsoleted the BSD-2-Clause-FreeBSD identifier. Catch
up to that fact and revert to their recommended match of BSD-2-Clause.
Discussed with: pfg
MFC After: 3 days
Sponsored by: Netflix
uma_zfree() can be called on a NULL pointer. Simplify the pf code a
little by removing the redundant checks.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Functions manipulating source nodes can fail due to various reasons like
memory allocation errors, hitting configured limits or lack of
redirection targets. Ensure those errors are properly caught and
propagated in the code. Increase the error counters not only when
parsing the main ruleset but the NAT ruleset too.
Cherry-picked from development of D39880
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39940
Reduce number of hashing operations when handling source nodes by always
having a pointer to the hash row mutex in the source node. Provide
macros for handling and asserting the mutex. Calculate the hash only
once in pf_find_src_node() and then use this hash in subsequent
operations.
Cherry-picked from development of D39880
Reviewed by: kp, mjg
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39888
Similar to the PF_TAG_DUMMYNET we must also clear the route tag if
dummynet didn't keep the packet. In that case we'd continue immediately
and there'd be no need for the route tag. Keeping it could lead to
unexpected routing of traffic.
See also: 27407a6adc
See also: https://redmine.pfsense.org/issues/14055
Sponsored by: Rubicon Communications, LLC ("Netgate")
Make Ethernet rules more similar to the usual layer 3 rules by also
allowing ridentifier and labels to be set on them.
Reviewed by: kp
Sponsored by: Rubicon Communications, LLC ("Netgate")
Packet Mark is an analogue to ipfw tags with O(1) lookup from mbuf while
regular tags require a single-linked list traversal.
Mark is a 32-bit number that can be looked up in a table
[with 'number' table-type], matched or compared with a number with optional
mask applied before comparison.
Having generic nature, Mark can be used in a variety of needs.
For example, it could be used as a security group: mark will hold a security
group id and represent a group of packet flows that shares same access
control policy.
Reviewed By: pauamma_gundo.com
Differential Revision: https://reviews.freebsd.org/D39555
MFC after: 1 month
Both pf_rules_lock and pf_ioctl_lock only ever affect one vnet, so
there's no point in having these locks affect other vnets.
(In fact, the only lock in pf that can affect multiple vnets is
pf_end_lock.)
That's especially important for the rules lock, because taking the write
lock suspends all network traffic until it's released. This will reduce
the impact a vnet running pf can have on other vnets, and improve
concurrency on machines running multiple pf-enabled vnets.
Reviewed by: zlei
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39658
Introduce the OpenBSD syntax of "scrub" option for "match" and "pass"
rules and the "set reassemble" flag. The patch is backward-compatible,
pf.conf can be still written in FreeBSD-style.
Obtained from: OpenBSD
MFC after: never
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D38025
It only served to complicate cleanup, and added no value.
While here drop packets in pfsync_defer_tmo() if we don't have a syncif,
rather than just leaving them on the queue.
Reviewed by: markj
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39248
The pd_tmo callout has an associated mutex, which we must hold while
calling callout_stop().
Reported by: markj
Reviewed by: markj
MFC after: 3 days
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39223
We can't do anything if ip6_output() fails, other than discard the
packet which ip6_output() already does for us.
Mark the return value as ignored.
Reported by: emaste, Coverity
Sponsored by: Rubicon Communications, LLC (Netgate)
pfsync_undefer_state() takes the bucket lock, but could get called from
places (e.g. from pfsync_update_state() or pfsync_delete_state()) where
we already held the lock.
As it can also be called from places where we don't yet hold the lock
create new locked variant for use when the lock is already held. Keep
using pfsync_undefer_state() where the lock must still be taken.
PR: 268246
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC (Netgate)
The callout for pfsync_defer_tmo() is created with
CALLOUT_RETURNUNLOCKED, because while the callout framework takes care
of taking the lock we want to run a few operations outside of the lock,
so we unlock ourselves.
However, if `sc->sc_sync_if == NULL` we return without releasing the
lock, and leak the lock, causing later deadlocks.
Ensure we always release the bucket lock when we exit pfsync_defer_tmo()
PR: 268246
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC (Netgate)
Link-local traffic needs to have a scope embedded before it's passed on
to ip6_output(). Do so in pf_refragment6(), because when we end up here
in the output path we may have passed through ip6_output() already
(before being reassembled), where the scope would have been removed.
Re-embed the scope so that link-local traffic is sent correctly.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39062