Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
de46175
smtp: add firewall progress states
jasonish Jun 30, 2026
ebbe9a7
smtp: complete transactions by progress state
jasonish Jul 3, 2026
0118ba2
smtp: handle pipelined replies on owning tx
jasonish Jul 7, 2026
fddc9e2
smtp: don't create transaction for trailing quit
jasonish Jul 8, 2026
2f075e8
htp: remove duplicate entries in the event table
victorjulien Jun 13, 2026
56b3ece
detect/file: remove unused registration fields
victorjulien Jun 8, 2026
d8b869f
detect/file.data: reduce scope for MPM datatype
victorjulien Jun 13, 2026
628b0b2
detect/parse: tighten hook parsing
victorjulien Jun 10, 2026
52577df
app-layer: minor code cleanup for GetStateProgress
victorjulien Jun 12, 2026
df4bacc
app-layer/parser: remove misleading comment
victorjulien Jun 12, 2026
b7c8636
app-layer: cleanup inspect id getter
victorjulien Jun 13, 2026
46d39d0
http/xff: harden code against http in detection-only
victorjulien Jun 25, 2026
5011437
detect/alert: split append func per packet/tx
victorjulien Jun 26, 2026
7b71e22
detect: move packet alert logic into helper
victorjulien Jun 30, 2026
c3bef92
detect: extend app-layer-protocol to accept a pipe-separated value list
yashda Jul 8, 2026
e379d17
http2: split progress per direction
catenacyber Jun 1, 2026
7bfb577
http2: global txs are unidirectional
catenacyber Jun 2, 2026
2ea3afc
http2: replace state todrop with a dedicated boolean
catenacyber Jun 2, 2026
8933283
bindgen: add stddef
victorjulien Jul 10, 2026
3316da4
app-layer: start of substate API support
victorjulien Jun 16, 2026
8b26d63
detect: support per tx sub states
victorjulien Jun 6, 2026
99f3b8f
detect/parse: initial substate support
victorjulien Jun 17, 2026
2a96758
detect/app-layer-event: support sub-state progress handling
victorjulien Jun 11, 2026
e8abfa9
output/tx: support substate completion flags
victorjulien Jun 11, 2026
f6bc591
http2: split transaction state machines
victorjulien Jun 6, 2026
a822738
detect/parse: initial http2 substate support
victorjulien Jun 17, 2026
079782c
detect/file: register http/2 with sub-state
victorjulien Jun 8, 2026
c486a4c
detect/http2: don't double register engines
victorjulien Jun 8, 2026
91c76f7
detect/dns: register keywords for DOH2 as well
victorjulien Jun 8, 2026
3e5d5f7
detect/http: register keywords for HTTP/2
victorjulien Jun 8, 2026
e7b5240
detect: change how DOH2 inspection works
victorjulien Jun 8, 2026
c9ef3bf
output/dns: update for DOH2 change
victorjulien Jun 8, 2026
fe2f9d0
http2: mark HTTP2TxProgress and HTTP2TxGlobalProgress as AppLayerState
victorjulien Jun 14, 2026
05bcc64
http2: register names for states per sub-state
victorjulien Jun 15, 2026
00dadae
detect/firewall: policy for substates
victorjulien Jun 13, 2026
a44fb56
detect/parse: parse sub state hooks
victorjulien Jun 16, 2026
07b4674
http2: set event on frame types not allowed on stream id
victorjulien Jun 18, 2026
0cd2e8d
http2: update push promise to account for stream id 0 filtering
victorjulien Jun 18, 2026
57aec26
detect/parse: don't setup sub states if protocol doesn't support it
victorjulien Jun 18, 2026
35369aa
app-layer: for sub state API treat DOH2 as HTTP/2
victorjulien Jun 20, 2026
4156641
detect/parse: allow bigger protocol/hook specifications
victorjulien Jun 20, 2026
7f8fb20
detect/firewall: implement app policy as hash table
victorjulien Jun 21, 2026
ab7767b
detect/firewall: add default alert signature to policy object
victorjulien Jun 22, 2026
164754d
detect/mpm: don't register engines for disabled protocols
victorjulien Jun 25, 2026
22f3d1e
detect: add debug validation checks
victorjulien Jun 24, 2026
957bcb9
app-layer: use macro for progress ceiling
victorjulien Jun 25, 2026
feb9d86
detect/alert: store sub-state in PacketAlert
victorjulien Jun 26, 2026
e11bb03
eve/alert: add sub state output
victorjulien Jun 26, 2026
512a186
detect/firewall: support lte mode for substate
victorjulien Jun 29, 2026
3208779
detect/firewall: support substate in analyzer
victorjulien Jun 21, 2026
6bdbd83
detect: give clear errors for http2 w/o substate
victorjulien Jun 30, 2026
41b60bc
detect: add debug validation checks to assert assumptions
victorjulien Jun 30, 2026
532770a
detect/firewall: harden policy lookup logic
victorjulien Jun 30, 2026
67339d0
eve/alert: clean up state logging
victorjulien Jul 1, 2026
9af776f
eve/alert: log sub state progress values
victorjulien Jul 1, 2026
f179816
detect: sync prefilter and app inspect alproto logic
victorjulien Jul 1, 2026
9bd5a75
http2: rename state *start to *started
victorjulien Jul 1, 2026
fc99592
doh2: do not enable parser if http2 is disabled
victorjulien Jul 2, 2026
ee79d0d
app-layer: check if protocol is enabled for sub state callbacks
victorjulien Jul 2, 2026
0350bc4
detect/firewall: avoid passing state match for policy
victorjulien Jul 2, 2026
aaa49d9
detect: use sub state to select inspect engines
victorjulien Jul 2, 2026
33e0be0
output/tx: allow registering logging at substate
victorjulien Jul 8, 2026
5053634
detect: strict validation of buffers
victorjulien Jul 9, 2026
94296e8
app-layer: add substate support to list hooks
victorjulien Jul 9, 2026
f1775f1
yaml/firewall: expand firewall options explanation
jufajardini May 29, 2026
3c04da1
detect/firewall: address HTTP/1 policies as http1
Jul 28, 2026
488a6da
detect/firewall: group policies under packet and app nodes
Jul 28, 2026
7da45e2
detect/firewall: add default-policy to policy config
Jul 28, 2026
5368ee3
detect/firewall: validate action scope against the hook class
Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/userguide/devguide/extending/app-layer/transactions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Rule Matching
Transaction progress is also used for certain keywords to know what is the minimum state before we can expect a match: until that, Suricata won't even try to look for the patterns.

As seen in ``DetectAppLayerMpmRegister`` that has ``int progress`` as parameter, and ``DetectAppLayerInspectEngineRegister``, which expects ``int tx_min_progress``, for instance. In the code snippet,
``HTTP2StateDataClient``, ``HTTP2StateDataServer`` and ``0`` are the values passed to the functions - in the last
``HTTP2ProgData``, ``HTTP2ProgData`` and ``0`` are the values passed to the functions - in the last
example, for ``FTPDATA``,
the existence of a transaction implies that a file is being transferred. Hence the ``0`` value.

Expand All @@ -86,14 +86,14 @@ the existence of a transaction implies that a file is being transferred. Hence t
.
DetectAppLayerMpmRegister("file_data", SIG_FLAG_TOSERVER, 2,
PrefilterMpmFiledataRegister, NULL,
ALPROTO_HTTP2, HTTP2StateDataClient);
ALPROTO_HTTP2, HTTP2ProgData);
DetectAppLayerMpmRegister("file_data", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmFiledataRegister, NULL,
ALPROTO_HTTP2, HTTP2StateDataServer);
ALPROTO_HTTP2, HTTP2ProgData);
.
.
DetectAppLayerInspectEngineRegister("file_data",
ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, HTTP2StateDataServer,
ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, HTTP2ProgData,
DetectEngineInspectFiledata, NULL);
DetectAppLayerInspectEngineRegister(
"file_data", ALPROTO_FTPDATA, SIG_FLAG_TOSERVER, 0, DetectEngineInspectFiledata, NULL);
Expand Down
67 changes: 48 additions & 19 deletions doc/userguide/firewall/firewall-design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Application layer tables
~~~~~~~~~~~~~~~~~~~~~~~~

If applayer is available, rules from the following tables apply. The tables for the
application layer are per app layer protocol and per protocol state. e.g. ``http:request_line``.
application layer are per app layer protocol and per protocol state. e.g. ``http1:request_line``.


.. table::
Expand Down Expand Up @@ -327,28 +327,57 @@ of :ref:`engine analysis<config:engine-analysis>`.
Default policies
================

Each hook has a default policy. By default ``packet:filter`` enforces a ``drop:packet`` policy and the
``app:filter`` hooks applies ``drop:flow``.
Each hook has a default policy applied to traffic that no firewall rule handled.
By default ``packet.filter`` enforces ``drop:packet``, ``packet.pre-flow`` and
``packet.pre-stream`` enforce ``accept:hook``, and every ``app`` hook enforces
``drop:flow``.

The policies can be configured in ``firewall`` block in the config.

Example for ``packet:filter``, to use reject instead of drop::
Defaults are configured in the ``firewall.policies`` block. A ``default-policy``
may be given at several levels; for any hook the most specific present setting
wins::

firewall:
policies:
packet-filter: [ "reject:packet" ]


Example for DNS::
default-policy: ["accept:hook"] # global fallback (all hooks)
packet:
default-policy: ["drop:packet"] # fallback for packet hooks
filter: ["drop:packet"]
pre-flow: ["accept:hook"]
pre-stream: ["accept:hook"]
app:
default-policy: ["drop:flow"] # fallback for all app hooks
dns:
default-policy: ["drop:flow"] # fallback for dns hooks
request-started: ["accept:hook"]
request-complete: ["drop:flow", "alert"]
response-started: ["accept:tx"]

Protocols whose hooks are grouped into sub states, such as HTTP/2, take an extra
level for the sub state name::

firewall:
policies:
dns:
request-started: ["accept:hook"]

# Drop and alert on all DNS requests that are not allowed in
# firewall.rules.
request-complete: ["drop:flow", "alert"]

# Accept all responses.
response-started: ["accept:tx"]
app:
http2:
default-policy: ["drop:flow"] # fallback for all http2 hooks
stream:
default-policy: ["drop:flow"] # fallback for http2 stream hooks
request-started: ["accept:hook"]
global:
request-started: ["accept:hook"]

Precedence:

* packet hook: ``packet.<hook>`` > ``packet.default-policy`` >
``policies.default-policy`` > built-in (``drop:packet`` or ``accept:hook``)
* app hook: ``app.<proto>.<hook>`` > ``app.<proto>.default-policy`` >
``app.default-policy`` > ``policies.default-policy`` > built-in (``drop:flow``)
* app hook in a sub state: ``app.<proto>.<sub state>.<hook>`` >
``app.<proto>.<sub state>.default-policy`` > ``app.<proto>.default-policy`` >
``app.default-policy`` > ``policies.default-policy`` > built-in (``drop:flow``)

An action scope must be valid for the hook it is applied to. For example,
defining ``accept:tx`` as a global default policy will fail to start Suricata,
because ``packet`` policies do not accept ``tx``.
Cover such hooks with a more specific setting so the incompatible default never
reaches them.
59 changes: 30 additions & 29 deletions doc/userguide/firewall/firewall-example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,36 @@ HTTP example with partially using default policies

firewall:
policies:
http:
request-started:
- "accept:hook"
request-line:
- "drop:flow"
- "alert"
request-headers:
- "drop:flow"
- "alert"
request-body:
- "accept:hook"
request-trailer:
- "accept:hook"
request-complete:
- "accept:hook"

response-started:
- "accept:hook"
response-line:
- "drop:flow"
- "alert"
response-headers:
- "accept:hook"
response-body:
- "accept:hook"
response-trailer:
- "accept:hook"
response-complete:
- "accept:hook"
app:
http1:
request-started:
- "accept:hook"
request-line:
- "drop:flow"
- "alert"
request-headers:
- "drop:flow"
- "alert"
request-body:
- "accept:hook"
request-trailer:
- "accept:hook"
request-complete:
- "accept:hook"

response-started:
- "accept:hook"
response-line:
- "drop:flow"
- "alert"
response-headers:
- "accept:hook"
response-body:
- "accept:hook"
response-trailer:
- "accept:hook"
response-complete:
- "accept:hook"


::
Expand Down
92 changes: 91 additions & 1 deletion doc/userguide/rules/app-layer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ Match on the detected app-layer protocol.

Syntax::

app-layer-protocol:[!]<protocol>(,<mode>);
app-layer-protocol:[!]<protocol>[,<qualifier>]...;
app-layer-protocol:[!]<proto1>|<proto2>[|...|<protoN>][,<qualifier>]...;

Each ``<qualifier>`` is either a ``<mode>`` (at most one, see below) or the
``exact`` option, in any order.

Examples::

Expand All @@ -21,6 +25,12 @@ Examples::
app-layer-protocol:http,to_server; app-layer-protocol:tls,to_client;
app-layer-protocol:http2,final; app-layer-protocol:http1,original;
app-layer-protocol:unknown;
app-layer-protocol:unknown|tls;
app-layer-protocol:unknown|tls|http;
app-layer-protocol:!tls|http;
app-layer-protocol:tls|http,either;
app-layer-protocol:dns,exact;
app-layer-protocol:tls|dns,either,exact;

A special value 'failed' can be used for matching on flows in which
protocol detection failed. This can happen if Suricata doesn't know
Expand All @@ -42,12 +52,92 @@ By default, (if no mode is specified), the mode is ``direction``.
.. note:: when negation is used, like ``!http``, it will not match on the
"unknown" state in the flow.

Protocol equivalences and the ``exact`` option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default a value matches its related protocols as well as itself. For
example ``http`` matches ``http1`` and ``http2``, ``dns`` also matches
``doh2`` (DNS over HTTP/2), and ``dcerpc`` also matches ``smb``. This is the
long-standing behaviour and keeps existing rules working.

Add the ``exact`` qualifier to match strictly, with no equivalences: the
flow's protocol must equal the configured value exactly. ``exact`` applies to
all values in the list and can be combined with a mode::

app-layer-protocol:dns,exact; # matches dns only, not doh2
app-layer-protocol:tls|dns,either,exact;

Because ``exact`` disables all equivalences, the generic ``http`` value is not
expanded to ``http1``/``http2`` either. A flow is never classified as the
generic ``http``, so ``app-layer-protocol:http,exact`` can never match and is
rejected at rule load; use ``http1`` or ``http2`` instead.

Here is an example of a rule matching non-http traffic on port 80:

.. container:: example-rule

alert tcp any any -> any 80 (msg:"non-HTTP traffic over HTTP standard port"; flow:to_server; app-layer-protocol:!http,final; sid:1; )

Multi-value form
~~~~~~~~~~~~~~~~

The ``app-layer-protocol`` keyword also accepts a pipe-separated (``|``) list
of protocol values. A rule matches when the flow's resolved application-layer
protocol equals **any** value in the list (logical OR).

Syntax::

app-layer-protocol:[!]<proto1>|<proto2>[|...|<protoN>](,<mode>);

Using ``|`` for the list keeps the optional trailing ``,<mode>`` qualifier
unambiguous, so the single-value ``<protocol>,<mode>`` form is unchanged.

Examples::

app-layer-protocol:unknown|tls;
app-layer-protocol:unknown|tls|http;
app-layer-protocol:tls|http,either;
app-layer-protocol:!tls|http;

The ``unknown|<proto>`` detection-window idiom
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When Suricata has not yet classified a flow's protocol (the "detection
window"), the flow's app-layer protocol is ``unknown``. Once protocol
detection completes, the protocol transitions to its classified value
(e.g., ``tls``, ``http``). Including ``unknown`` in a multi-value list
allows a single rule to cover both the detection window and the confirmed
protocol::

app-layer-protocol:unknown|tls;

This rule matches during the detection window (while the protocol is still
``unknown``) **and** after classification (when the protocol is ``tls``).
If the flow is classified to a protocol not in the list (e.g., ``http``),
the rule stops matching once the protocol is classified; in firewall mode the
flow is then handled by the default policy if no other rule accepts it.

Negated multi-value (NOR semantics)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When the multi-value form is negated with ``!``, it implements NOR semantics
across the entire list: the rule matches when the resolved application-layer
protocol is **known** AND matches **none** of the listed values.

Example::

app-layer-protocol:!tls|http;

This matches when the flow's protocol is known and is neither ``tls`` nor
``http`` (e.g., it matches ``dns``, ``ssh``, ``smtp``, etc.).

.. note:: Negated multi-value rules do not match during the detection window
(when the protocol is still ``unknown``). This prevents false positives
before protocol classification is complete.

.. note:: The value ``unknown`` cannot appear in a negated list. The parser
rejects ``!unknown`` and ``!unknown|tls`` at rule-load time.

.. _proto-detect-bail-out:

Bail out conditions
Expand Down
8 changes: 8 additions & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ Deprecations
Upgrading to 8.0.5
------------------

Keyword Changes
~~~~~~~~~~~~~~~

- HTTP2 keywords have now better progress defined, with the http2 transaction progress
being split per direction. This means that some rules should match sooner,
some rules will have less false negatives, and some rules will trigger once per transaction
instead of twice (one time for each direction)

Other Changes
~~~~~~~~~~~~~

Expand Down
4 changes: 4 additions & 0 deletions etc/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -8276,6 +8276,10 @@
"type": "object",
"additionalProperties": true
},
"sub_state": {
"type": "string",
"description": "Transaction type or sub state."
},
"suricata_version": {
"type": "string"
},
Expand Down
4 changes: 3 additions & 1 deletion rust/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ include = [
"FtpRequestCommand",
"FtpStateValues",
"FtpDataStateValues",
"HTTP2TransactionState",
"HTTP2TxProgress",
"HTTP2TxGlobalProgress",
"HTTP2TxType",
"DataRepType",
]

Expand Down
12 changes: 12 additions & 0 deletions rust/src/applayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ pub struct AppLayerTxData {
///
detect_progress_ts: u8,
detect_progress_tc: u8,
#[doc = " Type of transaction. Meaning is defined by the parser. Used to\n select a state machine. 0 means it is not used."]
pub tx_type: u8,
#[doc = " End of TX progress values\n\n toserver end of tx progress value"]
pub tx_type_eop_ts: u8,
#[doc = " toclient end of tx progress value"]
pub tx_type_eop_tc: u8,

de_state: *mut DetectEngineState,
pub events: *mut core::AppLayerDecoderEvents,
Expand Down Expand Up @@ -198,6 +204,9 @@ impl AppLayerTxData {
flags: 0,
detect_progress_ts: 0,
detect_progress_tc: 0,
tx_type: 0,
tx_type_eop_ts: 0,
tx_type_eop_tc: 0,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
txbits: std::ptr::null_mut(),
Expand Down Expand Up @@ -225,6 +234,9 @@ impl AppLayerTxData {
detect_progress_ts: 0,
detect_progress_tc: 0,
flags,
tx_type: 0,
tx_type_eop_ts: 0,
tx_type_eop_tc: 0,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
txbits: std::ptr::null_mut(),
Expand Down
Loading
Loading