On 2013/05/01 09:01, Franco Fichtner wrote:
> Hi Stuart,
>
> On May 1, 2013, at 1:11 AM, Stuart Henderson <[email protected]> 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 ;)