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 have a server running on my local network that acts as a router for the computers in my network. I want to achieve now that outgoing TCP requests to certain IP addresses are tunnelled through an SSH connection, without giving the people from my network the possibility to use that SSH tunnel to connect to arbitrary hosts.

The approach I had in mind until now was to have an instance of redsocks listening on localhost and to redirect all outgoing requests to the IP addresses I want to divert to that redsocks instance. I added the following iptables rule:

iptables -t nat -A PREROUTING -p tcp -d 1.2.3.4 -j DNAT --to-destination 127.0.0.1:12345

Apparently, the Linux kernel considers packets coming from a non-127.0.0.0/8 address to an 127.0.0.0/8 address as “Martian packets” and drops them. What worked, though, was to have redsocks listen on eth0 instead of lo and then have iptables DNAT the packets to the eth0 address instead (or using a REDIRECT rule). The problem about this is that then every computer on my network can use the redsocks instance to connect to every host on the internet, but I want to limit its usage to a certain set of IP addresses only.

Is there any way to make iptables DNAT packets to 127.0.0.1? Otherwise, does anyone have an idea how I could achieve my goal without opening up the tunnel to everyone?

Update: I have also tried to change the source of the packets, without any success:

iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.0/24 -d 1.2.3.4 -j SNAT --to-source 127.0.0.1
iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.0/24 -d 127.0.0.1 -j SNAT --to-source 127.0.0.1
share|improve this question
    
Did you solve this issue? I have the same problem as you. Thx –  tmow Jan 22 '13 at 14:59

2 Answers 2

You cannot do this trick with 127/8 network as it is treaded specially inside linux kernel. But you can create dummy network interface, assign ip address to it, bind your service to this address and do NAT.

root@vm8583:~# ip link add bogus type dummy
root@vm8583:~# sysctl net.ipv4.conf.eth0.arp_ignore=3
root@vm8583:~# ip addr add 10.0.0.1/32 bogus scope host
root@vm8583:~# ip link set bogus up
root@vm8583:~# ip link show bogus
4: bogus: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT 
    link/ether 5e:8b:38:f3:46:ce brd ff:ff:ff:ff:ff:ff

Note, you may need to set net.ipv4.conf.eth0.arp_ignore=3 so your server won't answer to ARP requests for 10.0.0.1 incoming via eth0:

arp_ignore - INTEGER
    Define different modes for sending replies in response to
    received ARP requests that resolve local target IP addresses:
. . .
    3 - do not reply for local addresses configured with scope host,
    only resolutions for global and link addresses are replied
    4-7 - reserved
share|improve this answer

You could try disabling reverse path filtering instead (which AFAICT is what is meant by the term "martian"). You can do this with echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter as root. (You may be able to only disable it on the lo interface, but I would try disabling it completely at first.)

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.