Snort can take more active role in securing network by sending active
responses to shutdown offending sessions. When active responses is
enabled, snort will send TCP RST and ICMP unreachable when
dropping a TCP session and ICMP unreachable packets for UDP.

==== Changes from Snort 2.9

* stream5_global:max_active_responses and min_response_seconds are now
active.max_responses and active.min_interval.

* Response actions were removed from IPS rule body to the rule action
in the header.  This includes react, reject, and rewrite (split out of
replace which now just does the detection part). These IPS actions are
plugins.

* drop and block are synonymous in Snort 2.9 but in Snort 3.0 drop means
don't forward the current packet only whereas block means don't forward
this or any following packet on the flow.

==== Configure Active

Active response is enabled by configuring one of following IPS action
plugins:

    react = { }
    reject = { }

When these active responses are not configured the default configuration
is used.

Active responses will be performed for reject, react or rewrite IPS rule
actions, and response packets are encoded based on the triggering packet.
TTL will be set to the value captured at session pickup.

Configure the number of attempts to land a TCP RST within the session's
current window (so that it is accepted by the receiving TCP).  This
sequence "strafing" is really only useful in passive mode.  In inline mode
the reset is put straight into the stream in lieu of the triggering packet
so strafing is not necessary.

Each attempt (sent in rapid succession) has a different sequence number.
Each active response will actually cause this number of TCP resets to be
sent. TCP data is multiplied similarly. At most 1 ICMP unreachable is sent,
iff attempts > 0.


Device IP will perform network layer injection.  It is probably a better
choice to specify an interface and avoid kernel routing tables, etc.

dst_mac will change response destination MAC address, if the device is
eth0, eth1, eth2 etc. Otherwise, response destination MAC address is
derived from packet.

Example:

    active =
    {
        attempts = 2,
        device = "eth0",
        dst_mac = "00:06:76:DD:5F:E3",
    }


==== Reject

IPS action reject perform active response to shutdown hostile network
session by injecting TCP resets and ICMP unreachable for TCP
connections, and ICMP unreachable packets for UDP.

Example:

    reject = { reset = "both", control = "all" }

    local_rules =
    [[
    reject tcp ( msg:"hostile connection"; flow:established, to_server;
    content:"HACK!"; sid:1; )
    ]]

    ips =
    {
        rules = local_rules,
    }


==== React

IPS action react enables sending an HTML page on a session and then
resetting it.

The headers used are:

    "HTTP/1.1 403 Forbidden\r\n" \
    "Connection: close\r\n" \
    "Content-Type: text/html; charset=utf-8\r\n" \
    "Content-Length: 438\r\n" \
    "\r\n"

The page to be sent can be read from a file:

    react = { page = "customized_block_page.html", }

or else the default is used:

    "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\r\n" \
    "    \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\r\n" \
    "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\r\n" \
    "<head>\r\n" \
    "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n" \
    "<title>Access Denied</title>\r\n" \
    "</head>\r\n" \
    "<body>\r\n" \
    "<h1>Access Denied</h1>\r\n" \
    "<p>You are attempting to access a forbidden site.<br />" \
    "Consult your system administrator for details.</p>\r\n" \
    "</body>\r\n" \
    "</html>\r\n"

Note that the file contains the message body only. The headers will be added
with an updated value for Content-Length. For HTTP/2 traffic Snort will
translate the page to HTTP/2 format.

Limitations for HTTP/2:

* Packet will be injected against the last processed stream id.

* Injection triggered while server-to-client flow of traffic is in a middle
of a frame is not supported. The traffic will be blocked, but the page will
not be injected/displayed.

When using react, payload injector must be configured as well.
Also Snort should be in ips mode, so the rule is triggered on the client
packet, and not delayed until the server sends ACK. To achieve this use
the default normalizer. It will set normalizer.tcp.ips = true.
Example:

    react = { page = "my_block_page.html" }
    payload_injector = { }
    normalizer = { }

    local_rules =
    [[
    react http ( msg:"Unauthorized Access Prohibited!"; flow:established,
    to_server; http_method; content:"GET"; sid:1; )
    ]]

    ips =
    {
        rules = local_rules,
    }

React has debug trace functionality. It can be used to get traces in case
injection is not successful.
To turn it on:

    trace =
    {
        modules = { react = { all = 1 } }
    }


==== Rewrite

IPS action "rewrite" enables overwrite packet contents based on "replace"
option in the rules. Note that using "rewrite" action without "replace"
option will raise corresponding rule alert, but will not overwrite the
packet payload.

For example:

    local_rules =
    [[
    rewrite tcp 10.1.1.87 any -> 10.1.1.0/24 80
    (
        sid:1000002;
        msg:"test replace rule";
        content:"index.php", nocase;
        replace:"indax.php";
    )
    ]]

    ips =
    {
        rules = local_rules,
    }

this rule replaces the first occurrence of "index.php" with "indax.php",
and "rewrite" action updates that packet.

Content and replacement are aligned to the right side of the matching
content and are limited not by the size of the matching content, but
by the boundaries of the packet.

  Example:

    rewrite http any any -> any any
    (
        msg:"Small replace";
        content:"content";
        replace:"text";
        sid:1000002;
    )

  this rule replaces "malicious content" to "malicious context".

  Example:

    rewrite http any any -> any any
    (
        msg:"Big replace";
        content:"content";
        replace:"y favorite page!";
        sid:1000002;
    )

  this rule replaces "malicious content" to "my favorite page!".

Be aware that after the match there should be enough room left for the
"replace" content in the matched packet. If there is not enough space
for the "replace" content the rule will not match.

"replace" works for raw packets only. So, TCP data must either fit
under the "pkt_data" buffer requirements or one should enable detection
on TCP payload before reassembly: search_engine.detect_raw_tcp=true.
For example:

  Rule that does not require search_engine.detect_raw_tcp=true:

    rewrite udp any any -> any any
    (
        msg:"TEST 1";
        sid:1000002;
        content:"attack";
        replace:"abc123";
    )

  Rule that does require search_engine.detect_raw_tcp=true:

    rewrite http any any -> any any
    (
        msg:"TEST 2";
        content:"/content.html";
        replace:"/replace.html";
        sid:1000002;
    )
