Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I will be awarding a +100 bounty to the correct answer once it is available in 48 hours

Is there a way to redirect traffic set to go out of the server to another IP, back to the server on localhost (preferably as if it was coming from the original destination)?

I'd basically like to be able to set up my own software that listens on say, port 80, and receives traffic that was sent to say, 1.2.3.4.

So as an example with some code. Here would be the server:

my $server = IO::Socket::INET->new(

    LocalAddr => '127.0.0.1',
    LocalPort => '80',
    Listen => 128,

);

And that would receive traffic from the following client:

my $client = IO::Socket::INET->new(

    PeerAddr => 'google.com',
    PeerPort => '80',

)

So rather than having the client be connecting to google.com, it would be connecting to the server I have listening on localhost for that same server.

My intention is to use this to catch malware connecting to remote hosts.

I don't specifically need the traffic to be redirected to 127.0.0.1, but it needs to be redirected to an IP the same machine can listen to.

Edit: I've tried the following, and it doesn't work--

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:80
iptables -t nat -A POSTROUTING -j MASQUERADE
share|improve this question

2 Answers 2

up vote 4 down vote accepted
+100

You want to use the iptables REDIRECT target.

iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 80 -j REDIRECT

The iptables manpage specifies a single option to REDIRECT that allows you to change the port.

That option is --to-ports.

EDIT: OUTPUT chain

share|improve this answer
    
It doesn't work for what I'm trying to do. It looks to me like that takes any traffic on port 80 to 1.2.3.4 and changes the port to something else, but it still goes to 1.2.3.4. I need it to go to localhost on the same machine the request originates from. –  GoldenNewby Apr 5 '12 at 5:34
    
That's what REDIRECT does. It redirects the packet to the machine itself by changing the destination IP to the primary address of the incoming interface (locally-generated packets are mapped to the 127.0.0.1 address). –  dmourati Apr 5 '12 at 5:39
    
Clear out all your iptables rules and just set the one I mentioned above to verify. –  dmourati Apr 5 '12 at 5:40
    
Is it possible to have the peerhost for the client show as 1.2.3.4 instead of the server's ip? –  GoldenNewby Apr 5 '12 at 6:55
    
Sorry for the delay in the promised bounty, I'll be awarding it one I can (at least 24 hours). –  GoldenNewby Apr 11 '12 at 22:08

As far as i understand, you could use the TPROXY iptables feature and IP_TRANSPARENT sockets to achieve a fully transparent redirect (without involving NAT). In that way your application will create a special socket which will accept traffic even if the destination IP was another box, and then use the iptables rules to redirect the traffic with destination port 80 on port 80 of the first local interface, without altering it at all.

iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp -d 1.2.3.4 --dport 80 -j TPROXY --on-port 80

This is used in Squid Proxy in order to operate in fully transparent mode without doing any NATting, thus not altering a single byte of the packet. Remember that you have to use a special socket for that, otherwise it won't work!

Just in case, extract from Kernel docs on how to open a tproxy socket:

fd = socket(AF_INET, SOCK_STREAM, 0);
/* - 8< -*/
int value = 1;
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
/* - 8< -*/
name.sin_family = AF_INET;
name.sin_port = htons(0xCAFE);
name.sin_addr.s_addr = htonl(0xDEADBEEF);
bind(fd, &name, sizeof(name));
share|improve this answer
    
I didn't test it in a new application, but squid is doing fine :) Any issues arise check the squid documentation, as it apply the most for what are you trying to do: [link] wiki.squid-cache.org/ConfigExamples/FullyTransparentWithTPROXY –  Martino Dino Apr 5 '12 at 7:20
    
I wasn't able to get this working-- is the socket option required for the client and the server? –  GoldenNewby Apr 5 '12 at 19:15
    
No, it simply "sniffs" for all the traffic directed to that port regardless of IP dst or dst port etc. But looking back this applies to traffic going trough your box and not originating from it. You should be able to adapt the "sniffer" socket binarytides.com/blog/… from that website –  Martino Dino Apr 6 '12 at 9:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.