[Snort-users] announcement & questions: user space firewall

Martin Roesch roesch at ...421...
Tue Nov 28 21:44:51 EST 2000

Hi Todd,

Two words: Bad ass. :)

Comments in-line....

Todd Lewis wrote:
> I have modified snort to support its use as a user-space firewall.
> This work was done using netfilter' IP queue support under Linux-2.4.

Interesting, I wonder if we could get it to interact with something like
ip-filter in a similar way?

> My modifications right now are sort of hacky and should definitely
> be considered proof-of-concept.  I have a plan, which I outline below,
> for integrating this support properly into snort.  I release this
> patch not so that people will use it, but to engender discussion.
> That said, the patch is GPL'd, and anyone who would like to is free
> to use it.

Hey, some people say all of Snort is kind of hacky. :O


> I would like to make two major changes to the snort core to formalize
> this support.  I think that with these changes, this functionality
> should not affect the normal use of snort at all, and there are positive
> side-effects of the proposed changes as well.  I would very much like
> to hear other developers' opinions of these changes.
> I propose that a single rule begin with a set of one or more actions,
> rather than one and only one action as it is now.  I think that this
> change is necessary even without my modifications; the fact that alert
> implicitly calls log is pretty gross, and as more actions are added to
> snort, the ability to combine them is important.
> The syntax that I propose is a comma-delimited sequence of actions,
> just like Martin's multiple-network support.  It would look something
> like this:
> alert,log,block tcp any any -> any (msg:"Foo";)
> To implement this, I would like to change RuleTreeNode.type from an
> enumeration to a bit-field.  The logic in the core would then read:
>         if (RuleTreeNode.type & ACTION_ALERT)
>                 alert(packet);
>         if (RuleTreeNode.type & ACTION_LOG)
>                 log(packet);
>         if (RuleTreeNode.type & ACTION_BLOCK)
>                 block(packet);
> or, even better:
>         for(action=actions[0];action=action++;action!+NULL){
>                 if(RuleTreeNode.type & action.flag)
>                         action.jackson(packet);
>         }
> (Personally, I think that the present behaviour of alert is wrong
> and should be replaced with "alert,log".  Since this would not be
> reverse-compatible, you could call it "alert2,log" and then denigrate
> the usage of "alert".  This change is not really a big issue, but it
> would set a good example on how to use the multiple action support.)

Ok, this doesn't look like it'd be too terribly hard to implement.  One
interesting thing to consider is the interaction that this will have with
Andrew Baker's multi-level alerts that will be coming out in Snort 1.7.

This also adds layers of complexity to the whole packet
handling/storing/manipulation code if we're going to do rule correlation later
on.  This is something we should add after 1.7 ships.

The existing structure of doing alerts with auto-logging is an artifact of
Snort's early days.  

BTW, (speaking of the early days) Snort's Open Source release 2nd anniversary
is coming up on the 22nd of December.  It's 2nd birthday was on the 18th of
this month.

> pcap is not the only way to get packets.  I would like to abstract out the
> package acquisition mechanism, convert pcap into the first such engine,
> and then take my libipq stuff and make that into an engine.

Good idea, we're also talking about abstracting the decoding system for 1.7+. 
Pluggable decoders are something that'll be highly desirable with this
implementation since we can have data handed to us in (potentially) several
formats.  There's also been talk of making Snort work on non-packet data as
well, but that's way off in the future.

> snort would default to pcap, or whatever else the builder wants the
> default to be.  The engine could then be set either via a command-line
> argument or via a config file entry.
> (Not that I want to do this now, but my personal preference is that these
> engines be dynamically-loadable shared objects.  I used this approach for
> drivers for a DNS server called Dents that I helped develop.  Then again,
> I believe that snort's plugins should be loaded in the same way.  I know
> that this raises portability problems, so I'm not going to tackle it for
> now, but if others are interested, I can certainly help in this work.
> I am intentionally proposing this interface in such a way that it is
> amenable to being used via loadable modules later.)

Yes, we're going to switch to this after version 1.7.  At the rate we're
adding in major architectural changes, we might want to call the following
release 2.0. :)  I need to get up to speed on how the dlopen() et al.
functions work and look at what it's going to take to get this way of doing
things implemented in Snort.  

When we're done with this phase of the development, Snort will truly become a
flexible packet analysis framework that you attach functionality to.  It
should be pretty interesting to see how it turns out. :)

> The high points of this new interface are as follows:
> - The module would export init() and close() routines for, well,
>   initialization and closing.
> - Each module would basically emulate the pcap packet loop.
> - The module would identify the media type from which it is acquiring
>   packets.  This allows the core to chose the proper grinder routine for
>   processing packets.
> - The module would advertise the actions that it supports.  Thus, if you are
>   attempting to use the "deny" action with the pcap engine, snort can warn
>   you that it's not supported.
> - The module would be configured by passing it a configuration line from the
>   config file, similar to how plugins are configured now.

This all sounds reasonable.

> Future work:
> - This interface only supports one connection per engine.  It would be nice
>   to use session identifiers to differentiate among different connections.
>   This would require for the loop to be outside of the engine and for
>   the engines to export enough functionality to fit into an external
>   select loop, or something.  Complicated, and since snort doesn't support
>   this presently anyway, ignored for now.

What do you mean by one connection per engine?  One data source (e.g. pcap)?

> Here's the interface as I have it now:
>      #define DEVTYPE_RAW        0
>      #define DEVTYPE_ETH        1
>      #define DEVTYPE_TR         2
>      #define DEVTYPE_FDDI       3
>      #define DEVTYPE_SLIP       4
>      #define DEVTYPE_PPP        5
>      #define DEVTYPE_NULL       6
>      #define DEVTYPE_I4LRAWIP   7
>      #define DEVTYPE_I4LCISCOIP 8
>      typedef struct paengine {
>         char *name; /* name of the paengine, e.g., "pcap" */
>         int (*configure)(char * config); /* config file entry for engine; 0 on
>                                           * success, other on error */
>         int (*init)(void); /* initialize driver; 0 on success */
>         int (*loop)(void (*)(Packet *, struct pcap_pkthdr *, u_char *));
>                        /* loop function for driver; takes a grinder as an
>                         * argument. 0 on success, other on failure. */
>         int (*close)(void); /* close driver; 0 on success */
>         int dev_type; /* number of the device type; called after configure() */
>         int capabilities; /* caps of the driver; called after configure() */
>      } paengine;
> My plan is for each engine to be implemented in a separate C file and for
> that file to export a single symbol, which is this struct for that engine.
> snort will, for now, have a hard-coded array of these structs, with
> "#ifdef" statements around each.  snort will default to using the pcap
> engine, but if you specify an alternative engine, then it will iterate
> through these paengine's until it finds one where paengine->name matches
> your request and then use that.
> Again, I plan on taking the existing pcap code and converting it into
> one of these engines and then taking the netfilter stuff and making that
> into a second engine.  I hope to rope one of the few FreeBSD fanatics
> here into writing an engine to support divert sockets.

Ok, this will require some changes in the decoders, as well as some of the
plugins.  We're pretty tightly bound to pcap right now in the TCP stream
reassembler and the defragger, plus the layer 2 decoders all expect a
pcap_pkth to be handed in.  We'll probably want to change them to something
more like this:

void DecodeFoo(struct snort_timeval *ts, u_int32_t cap_length, u_int8_t *pkt)

Where ts is the packet timestamp, cap_length is the amount of data being
handed to the decoder, and *pkt is the pointer to the data.  Pretty straight

The plugins that use pcap headers explicitly right now will have to be
modified to switch to the new scheme.  The defrag plugin should be changed to
use memory a little more efficiently in the future anyway, so this will be a
good time to get things straightened out.

As the decoders become plugins, we'll have to encapsulate their functionality
a little more highly, associating the printout routines directly with the
decoders that they service and making the decode/printout phase of things more
of a "best effort" mechanism where the packet dumps are printed as deeply into
the packet's structure as decoded data is available for.

Here's a question: can this firewall code control whether packets are
forwarded or dropped by other interfaces?  If it can, we can take a stab at
doing the first gateway IDS, which would be extremely righteous.... :)

> And then I'd like to make two minor changes:
> I have to add a flag to decode.h:Packet in order to record the firewall
> verdict on a packet.  This should be completely unobtrusive to normal
> usage of snort with the pcap engine, or even in non-firewall mode with
> netfilter.

Piece of cake.

> I will probably need some help with the auto* stuff to get this integrated
> properly.  I plan to program this with all of the #ifdef's I need in
> the code and, by default, have it all turned off.

Which auto* stuff?  I'll help where I can.

> Thanks to the other kind folks at SecureWorks for not whining while I
> work on this.

You SecureWorks guys have been turning out some good stuff lately!


Martin Roesch
roesch at ...421...

More information about the Snort-users mailing list