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

I'm trying to transparently route traffic of one Xen VM through another, like so:

-------      192.168.250.4          192.168.250.3     ---------
| VM1 |   <-----------------bridged---------------->  | VM2   |  <-----> Internet
-------                                               | with  |
                                                      | squid |
                                                      | proxy |
                                                      ---------

Don't ask why, just experimenting with iptables. I'm able to successfully route HTTP traffic through VM2's Squid proxy (transparent mode) with

iptables -t nat -A PREROUTING -p tcp --dport 80 –s ! 192.168.250.3 -j REDIRECT --to-port 3128

but how can I simply pass through all other traffic? Already tried this config but it gives me "Connection refused" errors when trying to access the Internet from VM1 (192.168.250.4):

vm2:~# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
# route outgoing udp traffic
DNAT       udp  -- !192.168.250.3        0.0.0.0/0           udp dpt:!80 to:192.168.250.3
# route outgoing tcp traffic
DNAT       tcp  -- !192.168.250.3        0.0.0.0/0           tcp dpt:!80 to:192.168.250.3
# this is the working squid rule
REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 3128

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
# route incoming traffic
SNAT       all  --  0.0.0.0/0            192.168.250.3       to:192.168.250.4 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

What is wrong here? I already read lots of tutorials but most don't work properly... (BTW: /proc/sys/net/ipv4/ip_forward is 1)

share|improve this question

2 Answers 2

Rather than using REDIRECT, try DNAT and SNAT. Try this:

iptables -t nat -I PREROUTING -d 192.168.250.3 -j DNAT --to-destination 192.168.250.4 iptables -t nat -I POSTROUTING -s 192.168.250.4 -j SNAT --to-source 192.168.250.3

share|improve this answer
    
Makes perfect sense, but that didn't work. VM1 still cannot connect to any IP/port outside 192.168.250.* - not even ping. I added a "-j LOG" rule and when doing wget 192.168.2.124 from VM1, VM2's stdout says IN= OUT=eth0 SRC=192.168.250.4 DST=192.168.2.124 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=50447 DF PROTO=TCP SPT=2133 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0. Looks like the outgoing SYN - but no other packets (like incoming packets) get logged. Do I need anything else than /proc/sys/net/ipv4/ip_forward = 1?? –  AndiDog Jan 26 '10 at 10:05
    
OK I answered my own question. The problem about your solution was that SNAT must rewrite the source IP to the external IP, not the internal IP (192.168.250.3). Thanks for the help, +1 –  AndiDog Jan 26 '10 at 13:47
    
Great, glad you got it working. –  Scott Forsyth - MVP Jan 26 '10 at 14:18
up vote 0 down vote accepted

I finally found the correct way to do it:

NAT-ing outgoing connections (VM1 --> Internet/intranet) works with source rewriting (SNAT):

iptables -t nat -A POSTROUTING -s 192.168.250.4 -j SNAT --to-source 192.168.2.125

where 192.168.2.125 is the current external IP of VM2 (must not be the internal address). As that IP is assigned by DHCP in my case, the rule must be changed to do SNAT on the dynamic IP. This is done by the MASQUERADE command:

iptables -t nat -A POSTROUTING -s 192.168.250.4 -j MASQUERADE

The final iptables config now looks like this (other tables/chains are empty):

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  192.168.250.4        0.0.0.0/0
share|improve this answer

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.