[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Possible Setup



Realistically,
this kind of layer 7 stuff can be done in at least two ways:
1) Like spamd (or a transparent proxy) that is redirects all traffic
on a particular port (e.g. tcp/25) to another IP and port that is
services by a userland application. The application then communicates
as appropriate.  Communication down the original redirected stream
get appropriately redirected, but new communication links need some
trickery.
2) Like Snort (or othe BPF application) that sniffs the traffic off
the interface, reassembles the frames into streams (like a proper
TCP stack does) and then requires trickery to reply down the same
comms channel, and a little more should other ports need opening.
Option 1 is much simpler, but has the problem that you must know what
port to initially intercept.  Option 2 effectly listens to all network
traffic - so could examine web traffic running on tcp/12345, but unless
you just want to reach by blocking the traffic, rather than
communicating man-in-middle style, you work is cut out.
Dom
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dom De Vitto                                       Tel. 07855 805 271
http://www.devitto.com                         mailto:[email protected]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Where do you want to go today?  Same as every day.... Windows Update.
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of
Daniel Hartmeier
Sent: Tuesday, June 29, 2004 12:11 AM
To: cloper
Cc: [email protected]
Subject: Re: Possible Setup
On Mon, Jun 28, 2004 at 03:16:15PM -0700, cloper wrote:
> drop in log quick on $ext_if layer 7 "edonkey login"
> drop in log quick on $ext_if layer 7 "aim send message"
While for applications TCP is a byte stream protocol, packet filters (as the
name implies) operate on a lower level. They do not see payload as an
ordered stream, but see individual packets containing chunks of payload. In
general, the payload is broken into chunks at arbitrary borders, chunks can
arrive in non-sequential order and there can be gaps and overlaps.
So, if you look at these individual packets as they pass through, you can't
really 'look for the string "edonkey"' inside the stream. All you could do
is look for the string inside one packet's payload.
But that's generally useless, as
  a) the string could be broken into multiple packets by chance
     legitimately (not very likely, but it will occur)
  b) the sender can intentionally break the string into multiple
     packets to bypass the filter (very likely and very easy to
     do), send chunks out of order or create overlaps.
  c) there will be many unexpected false positives. If you had the
     above rules in place, you wouldn't have been able to send your
     email, would you? If you'd browse the lists archive over HTTP,
     you couldn't load the page containing this reply. There's an
     endless list of protocols that might legally contain these
     strings, and you can't rely on P2P protocols to not use arbitrary
     ports.
If you'd be happy with that, this would be easy to hack into pf. Just add a
char array to struct pf_rule, make pfctl parse the search arguments into
rules, and have the kernel search for the arguments inside each packet. But
given a)-c), it will prove useless, IMO.
A P2P client can cause a string to get split up using one or two lines of
simple userland socket option fiddling. I wouldn't be surprised if some of
them already do that just for this purpose. If they don't, their next
releases will for sure. Either you have a solid reliable solution, or you
write code that will be useless in two months when the opponents catch up.
So, you'll end up wanting to reassemble packets into streams before
searching for strings. And you'll end up adding protocol awareness to the
code (so a HTML document containing the sequence "edonkey login"
sent over HTTP doesn't match). Restricting rules to ports won't help much,
as P2P protocols intentionally use port 80 and HTTP-alike protocols exactly
to get through firewalls and proxies more easily.
You'll find that a single simple piece of code won't do, instead you'll need
to implement stateful logic for all protocols you don't want to block
outright.
Once you're there, you'll find that doing this in kernel makes it
  a) harder (writing your own TCP reassembly in kernel is certainly
     more complex than just getting a stream in userland).
  b) more dangerous (mistakes easily produce remotely exploitable
     crashes or kernel compromises)
compared to doing the same in userland as application level proxies.
The most simple and reliable solution, in the end, would be to pick existing
proxies for the protocols you need to forward (like squid for
HTTP) and add the filtering there, if they do not already support such
features.
I think the idea of layer 7 filtering in packet filters is popular because
it appears to make things simple (just block "edonkey login"
in the packet filter and be done, no need to think about different protocols
etc.), but it's just flawed. Feel free to prove me wrong, but I won't spend
time writing code just to prove the point that the idea doesn't work. :)
Daniel