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 am trying to use SSH to port forward windows machines local port 3389 to a redhat server on some arbitrary port (in the unprivileged region) I have protected behind a firewall, then forward the unprivileged port on the redhat server onto the users remote desktop. Essentially create a highly specalized VPN which only handles one task: Get users to their systems behind a firewall using an encrypted tunnel I have control over.

I know years ago this was possible using the command:

iptables -A OUTPUT -t nat --dport ${LOCAL UNPRIV PORT} \
           -j DNAT ${ANOTHER SYSTEM}:${REMOTE PORT}

but from what I read, it looks like that ability was removed, and I get the message in /var/log/messages

      kernel: NAT: no longer support implicit source local NAT 

I found resources which suggest that from kernel 2.6.X - 2.6.10, there was a way to enable this in the kernel using IP_NF_NAT_LOCAL, but apparently in more recent kernels its been removed. I have tried forwarding all local traffic so it will enter the PREROUTING chain, and have had limited success, and that just feels like a bad idea, because then I have to open the unprivileged port on the server so I can feed it back into the eth0 interface. I'm sure given more time I could figure out some sort of bizarre kludge, or workaround, but I would rather not hack up my firewall scripts that much. It seems like there must be a much easier way of doing this I'm not seeing. Any help or guidance the community could provide would be very helpful! Thanks in advance

share|improve this question
    
Why are you trying to forward local traffic? Your question seems to indicate you want to forward certain incoming traffic? –  Erik Mar 12 '11 at 0:22
    
I'm trying to forward local traffic because when you do ssh -L ${local port}:${remote host}:${remote port} ${remote server} it wont work if you enter remote host as an IP address off the same subnet of the system you are logging in from. So I have entered localhost for the remote system instead. This has the effect that the remote server I'm SSH'ing into thinks that the traffic is being generated locally. Hence whey I am using the OUTPUT routing chain. –  dynamphorous Mar 14 '11 at 15:30
add comment

migrated from superuser.com Mar 15 '11 at 14:11

This question came from our site for computer enthusiasts and power users.

2 Answers

up vote 4 down vote accepted

I'm not completely sure if I understood, but I think you're just in the wrong chain. :-) I was confused, too, when I used iptables the first time. But the way to forward the local port ${LOCAL UNPRIV PORT} is the statement below:

$IPT -t nat -A PREROUTING -i eth0 -p tcp --dport ${LOCAL UNPRIV PORT} 
     -j DNAT --to ${ANOTHER SYSTEM}:${REMOTE PORT}

It is a mixture between a semantic problem and the way netfilter works: In the old days forwarding a local port involved a connection to the box that is forwarding, plus a second connection to the destination. Iptables does this in one step. So instead of two connections - you are forwarding the the traffic to that port directly to the destination. Netfilter does all the sanity checks and bookkeeping: only packets that belong to a valid connection are NATted and can therefore be forwarded.

Enabling DNAT doesn't allow any packets to be forwarded. You also have to add a rule:

$IPT -N INET-PRIV
$IPT -A FORWARD -i eth0 -o eth1 -j INET-PRIV
$IPT -A FORWARD -j DROP

$IPT -A INET-PRIV -p tcp -d ${ANOTHER SYSTEM} --dport ${REMOTE PORT} -j ACCEPT

$IPT -A INET-PRIV -j DROP

And you have to enable forwarding of course.

echo "1" > /proc/sys/net/ipv4/ip_forward

Pro iptables: more secure, more flexible, less memory and CPU used per connection

Contra iptables: forwarding a connection from a internal machine to a internal machine (feed it back into the eth0) doesn't make sense with iptables (of course you can always connect directly), forwarding traffic that is generated locally doesn't work (a port forwarding daemon might help - but usually doesn't make sense)

Exactly this might be the problem: you try to use NAT on a non-router, so you should use a forwarding daemon or skip this extra port forwarding completely and do:

ssh -L 1234:${ANOTHER SYSTEM}:${REMOTE PORT} special-vpn-box

On special-vpn-box you can only allow incoming connections from the router and outgoing connections to ${ANOTHER SYSTEM}:${REMOTE PORT} using iptables. That way users of the special-vpn-box can only access ${ANOTHER SYSTEM}:${REMOTE PORT} and won't be able to do anything else if they aren't trusted.

share|improve this answer
    
I certainly have tried the ssh the way you described, with the automatically forwarding it to the next machine. So basically if the system behind the firewall has an IP of 192.168.0.2, then do ssh -L 3389:192.168.0.2:3389 to special vpn box. But what I'm left with is when you try to connect to 192.168.0.2 3389 it just says "no path to host" when you try telnet. I tried doing the configuration you suggested (which is pretty close to what I already have) but when i check /var/log/messages the packet never hit the PREROUTING rule (when i switch to log vs acept) –  dynamphorous Mar 14 '11 at 20:19
    
Can you please list your hosts, what you do on what host and how they are connected. I suspect we still don't talk about the same thing. –  Ganwell Mar 15 '11 at 11:37
    
Firstly Ganwell, thank you very much for your time. I really appreciate your help. Ok, here is my layout. I have a remote user, I will call ${RU}. I have a redhat server with an open ssh port in the firewall directed at it I will call ${RHS}, and a local system behind the firewall I will call ${LS}. I want to have ${RU}-->SSH-->${RHS}-->RDP-->${LS}. To do this I have been using ssh port forwarding to get to the ${RHS}, then trying to DNAT that apparent (to the ${RHS} "local" traffic onto the ${LS} on port 3389 (RDP). –  dynamphorous Mar 15 '11 at 15:39
    
I have tried to use output to DNAT the destination back to the address of eth0, then using postrouting to SNAT and also set that to eth0. Then I was going to use the prerouting chain to DNAT them to the correct source. Seems WAY too complex. However the output chain, if I DNAT them directly to the address of the ${LS}, it never hits the postrouting chain (I have tried various logging options, and they definitely never get there). And from my understanding, if they are not making it to the postrouting chain, they are not leaving the system. –  dynamphorous Mar 15 '11 at 15:49
    
Ok. I think I got the problem, you are doing DNAT on the ${RHS} System right? You can't DNAT traffic that is generated on the local system. You can DNAT on the firewall, but once you passed the firewall you don't need any port forwarding (DNAT) anymore. You just have to change: ssh -L 3389:192.168.0.2:3389 to ssh -L 3389:${LS}:3389 –  Ganwell Mar 15 '11 at 17:12
show 2 more comments
# Enable IP Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A PREROUTING  -p tcp \
--dport ${LOCAL UNPRIV PORT} -j DNAT --to-destination ${ANOTHER SYSTEM}:${REMOTE PORT}

iptables -t nat -A POSTROUTING -p tcp \
--dst ${ANOTHER SYSTEM} --dport ${REMOTE PORT} -j SNAT --to-source ${LOCAL SYSTEM}
share|improve this answer
add comment

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.