.. _firewall mode design: Firewall Mode Design ******************** .. note:: In Suricata 8 the firewall mode is experimental and subject to change. The firewall mode in Suricata allows the use of a ruleset that has different properties than the default "threat detection" rulesets: 1. default policy is ``drop``, meaning a firewall ruleset needs to specify what is allowed 2. firewall rules are loaded from separate files 3. firewall rules use a new action ``accept`` 4. firewall rules are required to use explicit action scopes and rule hooks (see below) 5. evaluation order is as rules are in the file(s), per protocol state Concepts ======== Firewall vs Threat Detection (TD) --------------------------------- The interaction between firewall and TD is concepualized as if they are 2 seperate instances, where the firewall instance runs first, and it passes along to the TD instance what is accepted by the firewall. This is reflected in the stats, where a packet accepted by the firewall is counted as ``firewall.accepted``. If it was also allowed by TD, it will additionally be counted as ``ips.accepted``. If it was dropped by firewall, only ``firewall.blocked`` will be incremented. No ``ips.*`` counter will be updated as conceptually the TD instance won't have seen the packet. Tables ------ A ``table`` is a collection of rules with different properties. These tables are built-in. No custom tables can be created. Tables are available within the scope of packet layer and application layer (if available). Each rule can define its own :ref:`action scope`. Packet layer tables ~~~~~~~~~~~~~~~~~~~ Rules categorized in the following tables apply to all packets. .. table:: +-----------------------+--------------------------------------------------------------------+----------------+--------------------------------+ | Table | Description | Default Policy | Rule Order | +=======================+====================================================================+================+================================+ | ``packet:pre_flow`` | Firewall rules to be evaluated before flow is created/updated | ``accept:hook``| As appears in the rule file | +-----------------------+--------------------------------------------------------------------+----------------+--------------------------------+ | ``packet:pre_stream`` | Firewall rules to be evaluated before stream is updated | ``accept:hook``| As appears in the rule file | +-----------------------+--------------------------------------------------------------------+----------------+--------------------------------+ | ``packet:filter`` | Firewall rules to be evaluated against every packet after decoding | ``drop:packet``| As appears in the rule file | +-----------------------+--------------------------------------------------------------------+----------------+--------------------------------+ | ``packet:td`` | Generic IDS/IPS threat detection rules | ``accept:hook``| Internal IDS/IPS rule ordering | +-----------------------+--------------------------------------------------------------------+----------------+--------------------------------+ 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``. .. table:: +----------------+--------------------------------------------------------------------------+----------------+--------------------------------+ | Table | Description | Default Policy | Rule Order | +================+==========================================================================+================+================================+ | ``app:filter`` | Firewall rules to be evaluated per applayer protocol and state | ``drop:flow`` | As appears in the rule file | +----------------+--------------------------------------------------------------------------+----------------+--------------------------------+ | ``app:td`` | App-layer IDS/IPS threat detection rules | ``accept:hook``| Internal IDS/IPS rule ordering | +----------------+--------------------------------------------------------------------------+----------------+--------------------------------+ .. _ips_action_scopes: Actions and Action Scopes ------------------------- Firewall rules require action scopes to be explicitly specified. accept ~~~~~~ ``accept`` is used to issue an accept verdict to the packet, flow or hook. * ``packet`` accept this packet * ``flow`` accept the rest of the packets in this flow * ``hook`` accept rules for the current hook/state, evaluate the next tables * ``tx`` accept rules for the current transaction, evaluate the next tables The ``accept`` action is only available in firewall rules. .. note:: some protocol implementations like ``dns`` use a transaction per direction. For those ``accept:tx`` will only accept packets that are part of that direction. drop ~~~~ ``drop`` is used to drop either the packet or the flow * ``packet`` drop this packet directly, don't eval any further rules * ``flow`` drop this packet as with ``packet`` and drop all future packets in this flow .. note:: unlike in threat detection mode rules, a ``drop`` in a firewall rule does not imply alert pass ~~~~ ``pass`` is not available as a primary firewall action, but can be used as a secondary action in firewall rules. The effect of the action will only apply to threat detection rules. alert ~~~~~ ``alert`` is not available as a primary firewall action, but can be used as a secondary action in firewall rules. The effect will be the creation of an alert event when the firewall rule matches. Multi action rules ~~~~~~~~~~~~~~~~~~ In firewall rules, multiple actions can be specified: a primary firewall action, followed by one or more secondary actions. Example:: accept:flow,pass:flow,alert tls:client_hello_done ... tls.sni; ... In this example the first action ``accept:flow`` is the primary firewall action. When the rule matches, the flow will be accepted. The secondary actions ``pass:flow`` and ``alert`` are evaluated in the context of the threat detection engine. .. note:: the secondary actions are only evaluated if the primary firewall action is accepted. This is different from the behavior of the ``pass`` action in threat detection mode. .. _rule-hooks: Explicit rule hook (states) --------------------------- In the regular IDS/IPS rules the engine infers from the rule's matching logic where the rule should be "hooked" into the engine. While this works well for these types of rules, it does lead to many edge cases that are not acceptable in a firewall ruleset. For this reason in the firewall rules the hook needs to be explicitly set. There are two types of hooks available based on the layer. Packet layer hooks ~~~~~~~~~~~~~~~~~~ * ``flow_start``: evaluate the rule only on the first packet in both the directions * ``pre_flow``: evaluate the rule before the flow is created/updated * ``pre_stream``: evaluate the rule before the stream is updated * ``all``: evaluate the rule on every packet Application layer hooks ~~~~~~~~~~~~~~~~~~~~~~~ The application layer states / hooks are defined per protocol. Each of the hooks has its own default-``drop`` policy, so a ruleset needs an ``accept`` rule for each of the states to allow the traffic to flow through. This is done in the protocol field of the rule. Where in threat detection a rule might look like:: alert http ... http.uri; ... In the firewall case it will be:: accept:hook http1:request_line ... http.uri; ... All available applayer hooks are available via commandline option ``--list-app-layer-hooks``. general ^^^^^^^ Each protocol has at least the default states. Request (``to_server``) side: * ``request_started`` * ``request_complete`` Response (``to_client``) side: * ``response_started`` * ``response_complete`` http ^^^^ For the HTTP protocol there are a number of states to hook into. These apply to HTTP 0.9, 1.0 and 1.1. HTTP/2 uses its own state machine. Available states: Request (``to_server``) side: * ``request_started`` * ``request_line`` * ``request_headers`` * ``request_body`` * ``request_trailer`` * ``request_complete`` Response (``to_client``) side: * ``response_started`` * ``response_line`` * ``response_headers`` * ``response_body`` * ``response_trailer`` * ``response_complete`` tls ^^^ Available states: Request (``to_server``) side: * ``client_in_progress`` * ``client_hello_done`` * ``client_cert_done`` * ``client_handshake_done`` * ``client_finished`` Response (``to_client``) side: * ``server_in_progress`` * ``server_hello`` * ``server_cert_done`` * ``server_hello_done`` * ``server_handshake_done`` * ``server_finished`` ssh ^^^ Available states are listed in :ref:`ssh-hooks`. Auto-accept prior states ^^^^^^^^^^^^^^^^^^^^^^^^ To avoid creating lots of boilerplate ``accept`` rules there is a special notation to have a rule accept not just the hook it matches in, but also the hooks before it. Example:: accept:flow tls:`. 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``. The policies can be configured in ``firewall`` block in the config. Example for ``packet:filter``, to use reject instead of drop:: firewall: policies: packet-filter: [ "reject:packet" ] Example for DNS:: 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"]