No subject


Thu Nov 23 16:36:19 EST 2017


tarball as 3.13.  The FAQ on the website is a version or so behind.

---Paste Begins---

3.13 --faq-- --snort-- --faq-- --snort-- --faq-- --snort-- --faq--
Q: How does rule ordering work?

A: Marty has answered this many times on the snort-users mailing list.  Here
is
   an excerpt from a post on Thu, 22 Feb 2001 00:31:53 -0500, titled "Re:
   [Snort-users] order of evaluation of rules"

Currently, the data structures that store Snort rule data are the
RuleTreeNodes (RTN) and the OptTreeNodes (OTN).  These data structs are
stored in a two dimensinal linked list structure with the RTNs forming
the top row of the "Array" and the OTNs forming the columns under the
RTNs.  Here's an ASCII illustration from the infamous "lisapaper":

  RTN                   RTN                    RTN
  --------------        --------------         -----
 | Chain Header |      | Chain Header |      | Chai
 |              |      |              |      |
 | Src IP       |      | Src IP       |      | Src
 | Dst IP       |----->| Dst IP       |----->| Dst   .....
 | Src Port     |      | Src Port     |      | Src
 | Dst Port     |      | Dst Port     |      | Dst
 |              |      |              |      |
  --------------        --------------         -----
         |                     |
         |                     |
         |                     |
  OTN   \|/            OTN    \|/
  -------V------       --------V-------
 | Chain Option  |    | Chain Option   |
 |               |    |        :       |
 | Content       |             :
 | TCP Flags     |             :
 | ICMP Data     |
 | Payload Size  |
 | etc.          |
 |               |
  ---------------
         |
         |
         |
   OTN  \|/
  -------V------
 | Chain Option |
 |              |
 | Content      |
 | TCP Flags    |
 | ICMP data    |
 | Payload Size |
 | etc.         |
 |              |
  --------------
         |
         |

Rules with similar rule headers (i.e. all the CGI rules, the old stealth
port scan detection rules, most of the rules that focus on any single
service, etc) are grouped under a single RTN for the sake of efficiency
and the applicable OTNs are hung below them.  For instance, if you have
three rules like this:

alert tcp any any -> $HOME 80 (content: "foo"; msg: "foo";)
alert tcp any any -> $HOME 80 (content: "bar"; msg: "bar";)
alert tcp any any -> $HOME 80 (content: "baz"; msg: "baz";)

They all get grouped under the same RTN and the OTNs are "hung" beneath
them like this:


  RTN
 --------------------
|  SIP: any          |
|  SP: any           |
|  DIP: $HOME        |
|  DP: 80            |
 --------------------
          |
          |
  OTN    \|/
 ---------v----------
| content: foo       |
| msg: foo           |
 ---------------------
          |
          |
  OTN    \|/
 ---------v----------
| content: bar       |
| msg: bar           |
 ---------------------
          |
          |
  OTN    \|/
 ---------v----------
| content: baz       |
| msg: baz           |
 ---------------------

This is an efficient way to do things because we only need to check the
data in the RTN once with this method.  There is actually another
dimension to this array: the function pointer list.  Each node in the
"array" has a linked list of function pointers attached to it.  The
functions in this list are the tests that need to be done to determine
whether the data in the current packet matches the current rule node's
information.  Having this function pointer list gives us great
efficiency and flexibility: we don't need to perform tests for things
the current rule doesn't contain (e.g. "any" ports/IPs, packet content
on non-content rules, etc).  It also allows us to analyze the packet
with any function without having to make major modifications to the
whole program (which was the case in versions prior to version 1.5).

There are a couple of implications of this architecture.  For the sake
of this discussion on rules ordering, the one we're interested in is
that rule order is tricky to figure out.  For instance

alert tcp any any -> $HOME 80 (content: "foo"; msg: "foo";)
alert tcp any any -> $HOME 1:1024 (flags: S; msg: "example";)
alert tcp any any -> $HOME 80 (flags: S; msg: "Port 80 SYN!";)
alert tcp any any -> $HOME 80 (content: "baz"; msg: "baz";)

gets built like this:


  RTN                            RTN
 --------------------           --------------------
|  SIP: any          |         |  SIP: any          |
|  SP: any           |-------->|  SP: any           |
|  DIP: $HOME        |         |  DIP: $HOME        |
|  DP: 80            |         |  DP: 1-1024        |
 --------------------           --------------------
          |                              |
          |                              |
  OTN    \|/                            \|/
 ---------v----------           ---------v----------
| content: foo       |         | flags: S           |
| msg: foo           |         | msg: example       |
 --------------------           --------------------
          |
          |
  OTN    \|/
 ---------v----------
| flags: S           |
| msg: Port 80 SYN!  |
 --------------------
          |
          |
  OTN    \|/
 ---------v----------
| content: baz       |
| msg: baz           |
 --------------------

Note that all three of the port 80 rules will be checked before the
"1:1024" rule due to the order in which the applicable RTN has been
created.  This is because the rules parser builds the first chain header
for port 80 traffic and sticks it on the rules list, then on the next
rule it sees that a new chain header is required, so it gets built and
put in place.  In this case you would intuitively expect to get the
"example" message and never see the "Port 80 SYN!", but the opposite is
true.

----end paste---



-----
Erek Adams
Nifty-Type-Guy
TheAdamsFamily.Net





More information about the Snort-users mailing list