iptables port forwarding not working
I'm having a difficult time this week with networking! I have the following port forward set up on host 192.168.0.2 with iptables:
Code:
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 1912 -j DNAT --to-destination 192.168.0.58:3389 Code:
> telnet localhost 1912 |
When you telnet to localhost, no routing is involved. Hence, the packet isn't passing through the PREROUTING chain of the nat table.
Also, even if the forwarding had worked, what do you think the source IP of a packet destined for localhost might be? So even if the NAT setup worked and the kernel on the router was willing to forward the NATed packet to the other host, all you'd get would be complaints in the kernel log on the receiving side about "martians". |
Quote:
Code:
$ telnet 192.168.0.2 1912 Code:
iptables --append FORWARD --in-interface eth1 -j ACCEPT Since I'm not using localhost, what could still be the problem? Code:
> iptables -v -L -n -t nat |
Your port forwarding rule seems correct.
Try connecting from a host that is outside your network. The whole concept of port forwarding is to let an external host access a service/port on a host on your internal network. I personally doubt if it works like this. |
Quote:
The NATed packet arriving at 192.168.0.58 will have 192.168.0.3 as its source address, so naturally 192.168.0.58 will reply directly to 192.168.0.3 rather than sending the packet through 192.168.0.2 (the router). However, 192.168.0.3 sent a packet to 192.168.0.2, and isn't expecting a reply from 192.168.0.58. The reply packet is thus discarded, and the TCP stack on 192.168.0.3 will keep retrying a few times until the timeout threshold is reached. Port forwarding (destination NAT) requires two iptables rules: one rule in the PREROUTING chain of the nat table to alter the destination address (and possibly the port number) of the packet, and one rule in the FORWARD chain of the filter table to allow the altered packet to pass through the router. You have both of these in place. Additionally, you will need a rule in the POSTROUTING chain of the nat table if you want your setup to handle connections originating from same IP network as the destination host (often referred to as "hairpin nat" or "loopback nat"). In your case, the rule would look something like this: Code:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 192.168.0.58 -p tcp --dport 1912 -j SNAT --to-source 192.168.0.2 Technically, you could use the external IP address of the router as the "--to-source" address, or really any IP address outside the 192.168.0.0/24 network, but it's common practice to just use the local router IP. Also, you could leave out the "-p tcp --dport 1912" part of the rule if you want to handle multiple forwarded ports with a single rule. (And of course there will have to be a rule in the FORWARD chain of the filter table to handle return packets in general, typically one matching the ESTABLISHED and RELATED states, but that's true for any firewall/router setup and is not specific to port forwarding scenarios.) |
I had this port forwarding thing working very well before installing a Sonicwall firewall as the new gateway and router. Before that, 192.168.0.2 was the gateway/router with two network cards: eth0 - Internet facing; eth1 LAN. The rules which worked before were:
Code:
iptables -t nat -P POSTROUTING ACCEPT I have managed to get the Sonicwall to forward this 1912 port to 192.168.0.2. If I do 'nc -v -l -p 1912' on this host and telnet to it from the outside, I get a connect message. That part works. However, I'm not still able to fix up the firewall script on this host to get forwarding to .58. I was only trying to connect from within the LAN to eliminate the Sonicwall as the problem. But since I can connect to 1912 from the outside, I don't have to try messing with intra-LAN connections. I've modified my rules per Ser Olmy's advice (I think) as follows: Code:
iptables -t nat -P POSTROUTING ACCEPT |
IMHO this line is wrong :
Quote:
SNAT is used to masquerade if you have a static IP. In the first example it worked correctly. SNAT and -j MASQUERADE are two methods of sharing the internet connection, coupled with ip forwarding. Give the following a try and let me know : # echo 1 > /proc/sys/net/ipv4/ip_forward ( avoid iptables FORWARD chain temporarily) # iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE (where eth0 is your public interface) # iptables -t nat -A PREROUTING -p tcp -i eth0 -s 0/0 --dport 1912 -j DNAT --to-destination 192.168.0.58:3389 (enables PF) additionally you could try and substitute -d <your internet ip> with -i eth0 -s 0/0 This is all assuming your 192.168.0.2 is the router machine. Hope this helps. |
Quote:
Quote:
You can of course use it instead of the MASQUERADE target if the IP address of the outgoing interface never changes. |
Quote:
|
Quote:
I thought a few things were obvious (only because I've had my face in it for so long), but need clarification: Since adding the Sonicwall (192.168.0.1), host 192.168.0.2 is no longer the gateway or router. eth0 was the Internet facing interface, but is now no longer used at all. eth1 is on the same 192.168.0.0/24 subnet as the Sonicwall (192.168.0.1), which is now the gateway. There is no eth0 any more. Currently, all routing has been removed from 192.168.0.2 to the Sonicwall, but I want to forward certain ports from the Sonicwall to 192.168.0.2 (which does work) in order to let that host route them to other LAN hosts and, importantly, to capture the attempted break-in logs. So, given NO eth0, how should the following be fixed (on 192.168.0.2). It does not currently work: Code:
iptables -t nat -P POSTROUTING ACCEPT |
Quote:
Quote:
Code:
# Flush existing ruleset: Quote:
Quote:
:) |
Quote:
I created a firewall script of exactly your example, except to be as liberal as possible I did not default INPUT and FORWARD to DROP. I made them ACCEPT. Otherwise, I basically copy/pasted your example. Still no joy. With the following running on 192.168.0.2: Code:
tcpdump -tttt -l -nn portrange 1901-1914 and 'tcp[13] & 4 != 0' Code:
2019-03-22 15:21:19.337430 IP 192.168.0.2.1912 > 184.57.114.221.34966: Flags [R.], seq 0, ack 4106531947, win 0, length 0 Quote:
|
Quote:
Quote:
Quote:
But why filter on flags at all? Surely there's not that much incoming traffic on port 1912? Quote:
Try again, but look for the SYN flag (value 2) instead. Also, run these tests:
Quote:
|
Thanks for your patience!
You're right, I don't really need to mask the tcpdump packet. Here's what I've done to simply things: First, I tried with no firewall whatsoever running on 192.168.0.2. On that host I run 'nc -v -l -p 1912'. From a computer OUTSIDE this LAN, located many miles away, I run: telnet thathost.org 1912 On the target host I get, "connect to [192.168.0.2] from cpe-184-57-114-221.columbus.res.rr.com [184.57.114.221] 45540" So, I can definitely get to port 1912 on 192.168.0.2 from the outside. The Sonicwall is properly routing port 1912 to 192.168.0.2. From 192.168.0.2, if I run 'telnet 192.168.0.58 3389' (the Windows computer) I get: Code:
> telnet 192.168.0.58 3389 Code:
> telnet 192.168.0.3 3389 Next, I run the firewall commands per your previous suggestion, which are, if I understood correctly: Code:
iptables -F Code:
> iptables -L -v -n Code:
> tcpdump -tttt -l port 1912 Code:
$ telnet thathost.org 1912 So, 192.168.0.2 is seeing the request, but it's apparently NOT routing to the Windows (or Linux) computer. Finally, using your suggested tcpdump for the Windows host, I get: Code:
> tcpdump -v -i eth1 host 192.168.0.58 and tcp port 3389 (btw - for various configuration reasons, as recommended by security consultants, I do not want to enable eth0 on 192.168.0.2 directly to the Sonicwall. I want to get this working with eth1, if possible.) |
Later - tried disabling the firewall (Norton) on Windows 192.168.0.58. No difference in results. Also tried redirecting port 1914 to 3389 on Linux 192.168.0.3 where there is no firewall. Nothing on that host either.
|
Quote:
Code:
tcpdump -tttt -l -i eth1 tcp port 1912 or tcp port 3389 |
Did as you suggested:
Code:
> tcpdump -tttt -ln -i eth1 tcp port 1912 or tcp port 3389 |
Quote:
The POSTROUTING rule isn't catching packets from external hosts going to the Windows system, since it was only designed to handle the 2nd hairpin scenario (local PCs connecting to the Windows host via 192.168.0.2). Try adding this rule: Code:
iptables -t nat -A POSTROUTING -o eth1 -d 192.168.0.58 -p tcp --dport 3389 -j SNAT --to-source 192.168.0.2 |
Holy Firewall, Batman! That worked! You're a genius! I'll have to study this some more and incorporate it with my existing firewall, and route the other workstations in the same way.
To recap for the benefit of others: I want to do this because the new Sonicwall firewall/router/gateway apparently does not alert or counter-measure on brute-force attempts on RDP and VNC ports. I'm not certain they do so for their VPN either. I'm discussing this on the Sonicall forum. My 192.168.0.2 server has a counter-measure script to detect and block such attacks. Hence this thread. As a stripped-down iptables script, I've ended up with the following: Code:
# Flush existing ruleset: |
Possibly last question. I've configured several of the workstations, Windows, Linux and Mac. All work! This entails 4 iptables lines per workstation:
Code:
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 1912 -j DNAT --to-destination 192.168.0.58:3389 Code:
iptables -A FORWARD -i eth1 -d 192.168.0.4 -p tcp --dport 3389 -j ACCEPT Unfortunately, my 5900 redirects and 3389 redirects are interspersed, so I don't have clean ip ranges, but that's a task for another day. |
All times are GMT -5. The time now is 03:33 PM. |