I want to build a spam appliance... it will run an application which
accepts SMTP connections, opens its own connection to a back-end MTA,
and acts as an application relay in real time, forwarding the SMTP
exchange (not at the packet level) from the incoming connection to
the MTA, while possibly making some changes to the data being forwarded.

What I have so far is the app... which works, but currently is not
transparent.  When you connect to it you do so by connecting to the
IP of the spam filter, and it in turn initiates a connection to the
local MTA.  The remote sender connects to our spam filter, and the local
MTA sees its connection as coming from the spam filter.

Now to make it transparent, I need two things, one of which I now have.

Using OpenBSD/PF I can allow the remote sender to attempt to connect
to the real MTA IP, and I intercept it using a transparent bridge
which has rdr rules set up to redirect the incoming SMTP connection
to localhost.  My spamfilter app runs bound to localhost and accepts
the connection coming in on $ext_if.  It asks /dev/pf for the original
IP address that the remote client called, and uses that to make its
own connection to the back end MTA.

The second crucial part is the one I don't know how to do, or even if
it is possible.  My spamfilter app must open a connection to the real
MTA on $int_if, and have an SMTP exchange with it, but the MTA *must*
see the source IP address of the original remote caller - not the IP
address of my spamfilter box.

I think one way to do this is using libnet and creating fake packets,
but it looks *really* difficult to set up an entire TCP conversation
out and get replies back using this interface.  I've read the docs and
if it is possible, it's not obvious how.

I'm hoping there's an easier way for me to initiate an outgoing connection
from my spamfilter box on the internal interface to the local MTA.  It
would seem likely that there's something possible by using rdr and nat?

Obviously we normally go out of our way to stop spoofing, whereas here
we actually want to spoof, so I know that I would have to turn off
features like antispoof, but are there other problems that might make
this impossible?  For example I don't want to always NAT my own server
as the spoofed address when contacting the MTA, because the remote
server might legitimately want to talk to that server on some other
port.  (For example our mail server also supports ssh for remote users)
This requirement rules out some of the other spoofing tricks such as
the ones at http://www.medasys.com/company/fr/mis/securite/avisoct02.htm

The main reason that this full transparency is required is so that
the local MTA can deny third-party relaying in the same way that it
normally does based on the IP of the caller.  We don't want the
spam filter to have to do that relay blocking because it is intended
to run in a spam appliance which can be placed in front of any MTA,
without requiring any local configuration such as teaching it the IP
addresses of acceptable local clients etc.

So, any way this might be possible using relatively simple pf tricks,
that will allow me to write an app that opens a socket and has a normal
conversation?  Or do I have to go the low-level packet assembly route,
with all the hassles of getting low-level replies and reassembling
the conversation myself?


Graham

Reply via email to