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 ;)