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
