LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Networking (https://www.linuxquestions.org/questions/linux-networking-3/)
-   -   iptables redirection (https://www.linuxquestions.org/questions/linux-networking-3/iptables-redirection-580406/)

mallikk_in 08-28-2007 08:57 AM

iptables redirection
 
Hi,

i have something quite simple: I have one host with an ipaddress and one NIC.
now I would like that certain ports of that machine (25/80/110/143/443)
would be redirected to some other machine , because that one is replacing
the other, and I do not wish that there is any interruption in traffic.

so machine A has: 192.168.10.1 and one NIC
and machine B has: 192.168.10.2 and one NIC.

now i'm reading things like:
iptables -t nat -A PREROUTING -d 192.168.10.1 -p tcp \
--dport 80 -j DNAT --to-destination 192.168.10.2

which doesn't work.

what does work is something like:
iptables -t nat -A OUTPUT -d 192.168.10.1 -j DNAT --to \
192.168.10.2

but thats only for traffic which comes from the host itself, not for
foreign traffic that is going to the host.

hope someone can help me.

blackhole54 08-29-2007 02:28 AM

Quote:

Originally Posted by mallikk_in (Post 2873352)
now i'm reading things like:
iptables -t nat -A PREROUTING -d 192.168.10.1 -p tcp \
--dport 80 -j DNAT --to-destination 192.168.10.2

That looks right to me. I believe these packets still have to traverse the FORWARD chain in the filter table. Could there be something in the FORWARD chain blocking your packets?

Viewing the packet counts for the various rules can sometimes be a useful tool for debugging. To see the packet counts, use the -v option with iptables:

Code:

iptables -t nat -nvL | less
iptables -nvL | less


MisterProper 08-29-2007 09:07 PM

Well I have similiar problem in that I need to redirect smtp request from a primary machine with one NIC to a second machine.
I have partially solved the problem by using the following basic iptable's script (see below). You can use it for your problem by changing IPs, port and network interface.
The problem, now, is that the second machine logs SMTP requests as coming from the primary machine, and not from the client machine.
This occurs because of the third rule (POSTROUTING with SNAT), but this rule is needed to redirect properly requests.
So if someone knows how to solve this problem, he is welcome ..

#!/bin/sh

SERVER_IP=10.211.55.6 # Primary machine
FORWARD_TO_IP=10.211.55.2 # Second machine
PORT=25
IFACE=eth0

case "$1" in
start)
iptables -t nat -A PREROUTING -i $IFACE -p tcp --dport $PORT -j DNAT -d $SERVER_IP --to $FORWARD_TO_IP:$PORT
iptables -t filter -A FORWARD -p tcp --dport $PORT -d $FORWARD_TO_IP -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o $IFACE -p tcp -d $FORWARD_TO_IP --dport $PORT -j SNAT --to-source $SERVER_IP
iptables -t nat -A OUTPUT -p tcp --dport $PORT -d $SERVER_IP -j DNAT --to-destination $FORWARD_TO_IP:$PORT
;;
stop)
iptables -t nat -F PREROUTING
iptables -t nat -F POSTROUTING
iptables -t nat -F OUTPUT
iptables -F FORWARD
;;
restart)
sh $0 stop
sleep 1
sh $0 start
;;
show)
iptables -t nat -L PREROUTING
iptables -L FORWARD
iptables -t nat -L POSTROUTING
iptables -t nat -L OUTPUT
;;
*)
echo "$0 start|stop|restart|show"
;;
esac

blackhole54 08-29-2007 10:55 PM

Quote:

Originally Posted by MisterProper (Post 2875190)
The problem, now, is that the second machine logs SMTP requests as coming from the primary machine, and not from the client machine.
This occurs because of the third rule (POSTROUTING with SNAT), but this rule is needed to redirect properly requests.

Are you sure you need that 3rd rule? The only thing it should do is exactly what you don't want done -- change the source address. I think DNAT should work fine w/o the SNAT. (If I am wrong, could somebody explain it to me?)

EDIT: just as I posted it occurred to me: W/o the SNAT, the $FORWARDED_TO_IP will send the responses directly back to the originating machine instead of through $SERVER_IP. Still, is this a problem?

EDIT2: I may have gotten myself in trouble by thinking out loud before thinking this through. It now seems to me that if $FORWARDED_TO_IP sends the message directly to the originating machine, then the returning packet will come from a different IP address than the original packet was sent to. Which would be a problem. It still might be able to be made right w/o SNAT, but I have decided I should do some experiments rather than speculate. I will post back when I have done that, but it may be a while.

EDIT3: I have done some quick experiments using DNAT without using SNAT. They seem to confirm what I (eventually) was thinking: the nat tables code will handle everything properly if the return packets are forced to go through the machine that did the DNATing. But if the return packets are not forced through the DNATing machine, then the originating machine will get back packets from a different address than it sent packets to, and the operation will fail.

I am getting tired, and won't be posting the details tonight. But if it has not been rendered irrelevant by other people's subsequent posts, then within 24 hours I hope to post the details of my experiments along with tcpdump output showing what is going on. See the last edited time below for the current time.

blackhole54 08-30-2007 11:10 PM

Results of DNAT w/o SNAT
 
OK, here are the results of the DNAT experiments I did. These were done on an existing network of arguably curious topology (for historical reasons). But the topology, in fact worked well for these experiments. I DNATted ssh connections since that infrastructure was already in place, and I DNATted non-existent IP addresses so that the ssh clients wouldn't already have an opinion about what should be at that address. Doing that is a little contorted, but illustrates the principles anyway.

The network consists of 4 computers. Boxes A and D each have one NIC on the 192.168.1.0 subnet. Box C has one NIC on the 192.168.2.0 subnet and box B has an NIC on each subnet and acts as a router between them.

The following entries were made to the PREROUTING table on box B. No SNAT rules were added. I added a rule for each subnet so I could force the packets through this box by specifying an address on the opposite subnet from the originating computer.

Code:

[root@boxB root]# iptables -t nat -A PREROUTING -p tcp -d 192.168.2.104 --dport 22 -j DNAT --to-destination 192.168.1.dd
[root@boxB root]# iptables -t nat -A PREROUTING -p tcp -d 192.168.1.105 --dport 22 -j DNAT --to-destination 192.168.1.dd

EXPERIMENT 1

This experiment used the following setup:

C <----- 192.168.2.0/24 -----> B <----- 192.168.1.0/24 -----> D


The command ssh 192.168.1.105 was issued on box-C and is successfully DNATted to box-D at 192.168.1.dd as shown in the following tcpdumps from box-B. (I am not showing the client output, but the connection was successful.)

The un-DNATted packets on 192.168.2.0/24 subnet:

Code:

[root@boxB root]# tcpdump -nni eth1 tcp port 22
tcpdump: listening on eth1
18:46:21.bb97648 192.168.2.cc.46909 > 192.168.1.105.22: S 769519417:769519417(0) win 5840 <mss 1460,sackOK,timestamp 465999 0,nop,wscale 2> (DF)
18:46:21.bb98937 192.168.1.105.22 > 192.168.2.cc.46909: S 784959128:784959128(0) ack 769519418 win 5792 <mss 1460,sackOK,timestamp 461725 465999,nop,wscale 2> (DF)
18:46:21.bb99204 192.168.2.cc.46909 > 192.168.1.105.22: . ack 1 win 1460 <nop,nop,timestamp 465999 461725> (DF)
18:46:21.407647 192.168.1.105.22 > 192.168.2.cc.46909: P 1:39(38) ack 1 win 1448 <nop,nop,timestamp 461727 465999> (DF)
18:46:21.407928 192.168.2.cc.46909 > 192.168.1.105.22: . ack 39 win 1460 <nop,nop,timestamp 466001 461727> (DF)
18:46:21.408036 192.168.2.cc.46909 > 192.168.1.105.22: P 1:39(38) ack 39 win 1460 <nop,nop,timestamp 466001 461727> (DF)
18:46:21.409340 192.168.1.105.22 > 192.168.2.cc.46909: . ack 39 win 1448 <nop,nop,timestamp 461728 466001> (DF)

The DNATted packes on 192.168.1.0/24 subnet:

Code:

[root@boxB root]# tcpdump -nni eth0 tcp port 22 and not host 192.168.1.aa
tcpdump: listening on eth0
18:46:21.bb98249 192.168.2.cc.46909 > 192.168.1.dd.22: S 769519417:769519417(0) win 5840 <mss 1460,sackOK,timestamp 465999 0,nop,wscale 2> (DF)
18:46:21.bb98584 192.168.1.dd.22 > 192.168.2.cc.46909: S 784959128:784959128(0) ack 769519418 win 5792 <mss 1460,sackOK,timestamp 461725 465999,nop,wscale 2> (DF)
18:46:21.bb99511 192.168.2.cc.46909 > 192.168.1.dd.22: . ack 1 win 1460 <nop,nop,timestamp 465999 461725> (DF)
18:46:21.407301 192.168.1.dd.22 > 192.168.2.cc.46909: P 1:39(38) ack 1 win 1448 <nop,nop,timestamp 461727 465999> (DF)
18:46:21.408332 192.168.2.cc.46909 > 192.168.1.dd.22: . ack 39 win 1460 <nop,nop,timestamp 466001 461727> (DF)
18:46:21.408761 192.168.2.cc.46909 > 192.168.1.dd.22: P 1:39(38) ack 39 win 1460 <nop,nop,timestamp 466001 461727> (DF)
18:46:21.409029 192.168.1.dd.22 > 192.168.2.cc.46909: . ack 39 win 1448 <nop,nop,timestamp 461728 466001> (DF)

Note that box-B not only DNATted the outgoing packets from 192.168.1.105 to 192.168.1.dd, as instructed, but that it also automatically SNATted the return packets from 192.168.1.dd back to 192.168.1.105, so everything looks normal to box-C. Yet since we didn't SNAT the outgoing packets, box-D saw the packets as originating from box-C, as it should.


EXPERIMENT 2

Here I attempt to DNAT from box-A to box-D (which are both on the same subnet) addressing the outgoing packets to 192.168.2.104. This will route the packets to box-B which will DNAT them. But because box-A and box-D are on the same subnet, you will see the return packets not going through box-B, and therefore the source address will be box-D. Since box-A did not send anything to box-D, it will reset the connection and the attempt fails. (The ssh client just sits there doing nothing.)

These packets are monitored on box-A, and you can see the mismatch of the address between packets going out and coming back, and box-A reseting the connection (port 51914 was carrying a different ssh connection, so I suppressed its packets).

Code:

[root@boxA user]# tcpdump -nni eth0 tcp port 22 and not tcp port 51914
Kernel filter, protocol ALL, datagram packet socket
tcpdump: listening on eth0
03:54:26.520419 > 192.168.1.aa.1023 > 192.168.2.104.22: S 2256561412:2256561412(0) win 16060 <mss 1460,sackOK,timestamp 2617428 0,nop,wscale 0> (DF)
03:54:26.521266 < 192.168.1.dd.22 > 192.168.1.aa.1023: S 4061241480:4061241480(0) ack 2256561413 win 5792 <mss 1460,sackOK,timestamp 4774665 2617428,nop,wscale
2> (DF)
03:54:26.521434 > 192.168.1.aa.1023 > 192.168.1.dd.22: R 2256561413:2256561413(0) win 0
03:54:29.516302 > 192.168.1.aa.1023 > 192.168.2.104.22: S 2256561412:2256561412(0) win 16060 <mss 1460,sackOK,timestamp 2617728 0,nop,wscale 0> (DF)
03:54:29.517094 < 192.168.1.dd.22 > 192.168.1.aa.1023: S 4064237113:4064237113(0) ack 2256561413 win 5792 <mss 1460,sackOK,timestamp 4775414 2617728,nop,wscale
2> (DF)
03:54:29.517256 > 192.168.1.aa.1023 > 192.168.1.dd.22: R 2256561413:2256561413(0) win 0


EXPERIMENT 3

This is a variation on experiment 2. Here I modify the routing table on box-D to tell it to route packets to box-A via box-B instead of directly:

Code:

root@boxD:~# route -n
Kernel IP routing table
Destination    Gateway        Genmask        Flags Metric Ref    Use Iface
192.168.1.aa    192.168.1.bb    255.255.255.255 UGH  0      0        0 eth0
192.168.2.0    192.168.1.bb    255.255.255.0  UG    0      0        0 eth0
192.168.1.0    0.0.0.0        255.255.255.0  U    0      0        0 eth0
0.0.0.0        192.168.1.aa    0.0.0.0        UG    0      0        0 eth0

And it initially worked! Box-B automatically SNATted the returning packets so that box-A saw them as coming from the address it sent packets to. But the fly in the ointment is box-B sent icmp to box-D telling it that it should be sending those packets directly to box-A. When box-D does this, box-B can no longer SNAT the return address and box-A resets the connection. I seem to not have saved that tcpdump output for this :( .

CONCLUSION

When packets are DNATted in the PREROUTING chain, the computer tracks that connection and if the return packets come back to that computer, it transparently SNATs the returning packets such that the originating machine sees them as returning from the address it originally sent packets to. Additionally, the recipient machine sees the source address of the originating machine. So the DNATting is transparent to both originating and destination boxes.

However, if the return packets do not pass through the DNATting machine, then the originating machine sees a different IP address and the connection fails. This can be overcome by SNATting as MisterProper did, which will force the packet through the DNATting machine, and everything will work. The price is that the destination box now sees the address of the DNATting box rather than the originating box.

So MisterProper, if you can configure things such that the return packets always go through the box with the DNAT command, then you won't have to use the SNAT command and your server will see the correct source address.

mallikk_in 08-31-2007 01:25 AM

redirection
 
I have the situation like this

user<-------------->linux<--------------->policyserver

in this set up if any user tries to access linux server i have to redirect him to policy server for some policies checking.I tried with ur rules but it is not working.what are the rules should add in linux server.please can help me.

blackhole54 08-31-2007 03:25 AM

Quote:

Originally Posted by mallikk_in (Post 2876493)
I tried with ur rules but it is not working.

Are all three computers (that you illustrated) on the same subnet? Your first post on this thread makes it look like everything is on the 192.168.10.0/24 subnet. If that is so, the only thing I know to do is use an SNAT command like MisterProper showed. But remember that if you do that, the policy server will see the source address as being from the computer designated linux rather from user.

To do that, using the IP addresses and port you listed in your first post, I believe the following should work:

Code:

iptables -t nat -A PREROUTING -d 192.168.10.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.10.2
iptables -t nat -A POSTROUTING  -d 192.168.10.2 -p tcp --dport 80 -j SNAT --to-source 192.168.10.1

If the computer are not on the same subnet such that the computer you designated linux is acting as a router between the subnets, then you should not need the SNAT command.

If you are still having problems, I would suggest:
  • Make sure the packets are not blocked on the netfilter FORWARD chain
  • Use iptables -t nat -nvL and look at packet counts to verify packets are matching the rules
  • Use tcpdump to see what is actually happening with the packets

mallikk_in 08-31-2007 05:34 AM

redirection
 
my scenario is like this


user-192.168.1.2---eth0-.3-linuxserver-.2-eth1----192.168.2.3-policy server

if user trying to connect linux server i have to redirect him to policy server.user and policy server should be able to communicate with each other.

blackhole54 08-31-2007 09:55 PM

Since they are not on the same subnet, the packets between user and policy server should have to travel through the linux server. (There is not a another route the packets can get from policy server back to user, is there?) Therefore, you should not need the SNAT rule.

If it is not working, try the suggestions I made at the end of post #7.

mallikk_in 09-01-2007 07:19 AM

thank you very much for ur help.it is working with ur rules.thank you.

MisterProper 09-01-2007 02:46 PM

problem solved
 
Hi blackhole54
Your solution to force outgoing packets from Box D to reroute throught Box B, as descripted in your experiment 3, is a very original solution !
I have try to use similar solution, and its work now ! Thanks a lot !
But obviously this solution will apply to all outgoing packets... is there no way to only force rerouting packets for a specific port ?
Thx again
Mister Proper

blackhole54 09-02-2007 01:00 AM

Quote:

Originally Posted by MisterProper (Post 2878021)
Your solution to force outgoing packets from Box D to reroute throught Box B, as descripted in your experiment 3, is a very original solution !
I have try to use similar solution, and its work now ! Thanks a lot !

I wished I had saved the tcpdump output on experiment 3 (but I was too lazy to redo it). But in case you missed it, ultimately the connection failed in experiment 3. The first few packets that came back were fine. But as I understand it (perhaps misunderstand it) when a machine such as box-B reroutes an incoming packet back to the same subnet, in addition to rerouting the packet, it sends an icmp packet back to the originating machine telling it where it should have routed the packet in the first place. That appears to be what happened here. After the first few packets, which went through box-B and were automatically SNATted, box-D started sending the packets directly to box-A, with what box-A considered the wrong source address, causing the connection to fail. If you have come up with a solution to that, I would be interested in hearing it. But be careful and make sure the solution is really working. It ultimately failed for me.

Quote:

But obviously this solution will apply to all outgoing packets... is there no way to only force rerouting packets for a specific port ?
I think you can, but I am much too green wrt the iproute2 utilities to tell you how. But I think I have read where you can mark packets with iptables (mangle table?) and then use the iproute2 tools to route them. You might want to search LQ for info about iproute2. I believe I have seen somebody post a link about how you do some of this magic.

@mallikk_in,

I am glad you got things working.


All times are GMT -5. The time now is 11:52 PM.