On 2013/05/01 09:01, Franco Fichtner wrote:
> Hi Stuart,
> 
> On May 1, 2013, at 1:11 AM, Stuart Henderson <st...@openbsd.org> wrote:
> 
> > On 2013/05/01 00:16, Franco Fichtner wrote:
> >> 
> >> Yes, I am proposing a lightweight approach: hard-wired regex-like
> >> code, no allocations, no reassembly or state machines.  I've seen
> >> far worse things being put into Kernels and I assure you that I do
> >> refrain from putting in anything that could cause segmentation
> >> faults, sleeps, or other non-suitable behaviour.
> > 
> > Would it be fair to describe it as a bit more complex than osfp,
> > but not hugely so?
> 
> Not sure if that's a fitting comparison; and I know too little OSPF
> to answer.

I should have expanded the acronum to make it clear - osfp i.e. the
OS fingerprinting code (pf_osfp.c).

> Let me try another route.  The logic consists of an array
> of application detection functions, which can be invoked via their
> respective IP types.  There's 32 bits of external state for the
> table and a single hook into the application detection.  And the
> detection for TLS/SSL3.0 follows.  I have really tried to condense
> it down to the bare minimum.
> 
> LI_DESCRIBE_APP(tls)
> {
>         struct tls {
>                 uint8_t record_type;
>                 uint16_t version;
>                 uint16_t data_length;
>         } __packed *ptr = (void *)packet->app.raw;
>         uint16_t decoded;
> 
>         if (packet->app_len < sizeof(struct tls)) {
>                 return (0);
>         }
> 
>         decoded = be16dec(&ptr->data_length);
> 
>         if (!decoded || decoded > 0x4000) {
>                 /* no empty records possible, also <= 2^14 */
>                 return (0);
>         }
> 
>         switch (ptr->record_type) {
>         case 20:        /* change_cipher_spec */
>         case 21:        /* alert */
>         case 22:        /* handshake */
>         case 23:        /* application_data */
>                 break;
>         default:
>                 return (0);
>         }
> 
>         switch (be16dec(&ptr->version)) {
>         case 0x0300:    /* SSL 3.0 */
>         case 0x0301:    /* TLS 1.0 */
>         case 0x0302:    /* TLS 1.1 */
>         case 0x0303:    /* TLS 1.2 */
>                 break;
>         default:
>                 return (0);
>         }
> 
>         return (1);
> }

This type of thing looks sane to me, but others will want to comment. (I'll
point others at your posts at http://lastsummer.de/category/technology/
too :-)

> >> Would a protocol like BGP have a bright future in relayd(8)?
> >> I don't know enough, maybe Reyk can clear this up?
> >> 
> >> L7 filtering is cute, but ipfw-classifyd isn't maintained, DPI in
> >> Linux netfilter is not hitting it off, and there really is no
> >> BSD DPI.  Franky, I don't care which way to go, but I believe
> >> that pf(4) is a suitable candidate.  I especially like the one-
> >> rule-to-rule-them-all approach.  Adding a keyword "app" to
> >> pf.conf(5) seems like the simplest solution -- much like "proto"
> >> does deal with IP types.
> >> 
> >> And talking about complexity: 1000 LOC for 25 protocols.  I'm afraid
> >> it can't be simplified any more than this.
> > 
> > What sort of protocols do you think could be reasonably handled by
> > this approach, and what would be too complicated?
> 
> Good question!  Text protocols are easy, RFCs and open implementations
> are generally easy.  Anything too commercial/proprietary, especially
> in binary, is more guessing than anything else and may not be worth
> the effort.  I don't see "world of warcraft" happening as a supported
> application.  This is what I have done so far (by no means free of
> errors, though):
> 
> -- BitTorrent
> -- Gnutella
> -- Network Basic Input Output System
> -- Telecommunication Network
> -- Hypertext Transfer Protocol
> -- Post Office Protocol (Version 3)
> -- Internet Message Access Protocol
> -- Simple Mail Transfer Protocol
> -- Session Traversal Utilities for NAT
> -- Dynamic Host Configuration Protocol
> -- Point-to-Point Tunneling Protocol
> -- Lightweight Directory Access Protocol
> -- Simple Network Management Protocol
> -- Secure Shell
> -- File Transfer Protocol
> -- Session Initiation Protocol
> -- Domain Name System
> -- Real-time Transport Control Protocol
> -- Real-time Transport Protocol
> -- Routing Information Protocol
> -- Boarder Gateway Protocol
> -- Internet Key Exchange
> -- Datagram Transport Layer Security
> -- Transport Layer Security
> -- Concurrent Versions System
> 
> > There is definitely something appealing about being able to say, for
> > example, 'block proto tcp on port 443; pass proto tcp on port 443 app tls',
> > or 'block app ssh; pass proto tcp from <somehosts> to port 22 app ssh'
> > without a bunch more complexity involved in passing across to a separate
> > proxy (which would then need to implement its own completely separate
> > filtering and would, I think, not really be able to integrate with
> > things like PF tags and queue assignment)...
> 
> Yes, that would be one scenario.  I like to think of lightweight packet
> inspection as application "tagging".  That's the first stage.  Second
> stage is a real parser/proxy/endpoint.  It's not a security functionality
> per se, but it can help to break down the workload.  It doesn't care
> aboute IP versions, ports (mostly ;) ), different flavours ("netbios"
> could be session, datagram, and name service as one for example), and so
> forth.

So another example might be: "pass proto tcp app $someapp divert-packet
$someproxy", with $someproxy handling the second stage?

> > Basically what I'm wondering if it's possible to go far enough to be
> > useful whilst keeping the complexity down to a level which is sane
> > and simple enough that it can be carefully audited.
> 
> That is my concern as well and I have kept that in mind while working
> on the code.  The current state of the art in DPI is somewhat messy,
> so that's the reason for me to improve on it.

Yes, this is clearly a less messy approaach than opendpi ;)

Reply via email to