1

This question has been asked countless times. A few weeks ago I managed to get this working between this ServerFault post and this Digital Ocean blog post. I must be missing something simple.

My goal is to simply forward packets between two interfaces performing NAT along the way. Specifically, I want to forward packets between a public interface and an external USB NIC.

I made sure the Kernel was configured to allow port forwarding:

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

As well as interface-specific forwarding configurations:

net.ipv4.conf.enp0s20u4u3.forwarding = 1
net.ipv4.conf.eno1.forwarding = 1

The iptables rules I created are:

iptables -t nat -A PREROUTING -i eno1 --protocol tcp --destination-port 10000 -j DNAT --to-destination 192.168.10.2:1234
iptables -A FORWARD -i eno1 -o enp0s20u4u3 --protocol tcp --destination-port 1234 -j ACCEPT
iptables -t nat -A POSTROUTING -o enp0s20u4u3 --protocol tcp --source 192.168.10.2 --source-port 1234 -j SNAT --to-source 192.168.10.1

I then tried testing this configuration by attempting to establish a TCP connection over port 10000 (if my external IP was 192.168.2.50).

$ nc -v 192.168.2.50 10000
nc: connect to 192.168.2.50 port 10000 (tcp) failed: Connection refused

This behavior makes sense if my rule entries were incorrect. So, I dumped the rule statistics

$ iptables -t nat -L -v
Chain PREROUTING (policy ACCEPT 15 packets, 2885 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  eno1   any     anywhere             anywhere             tcp dpt:ndmp to:192.168.10.2:1234

Chain INPUT (policy ACCEPT 15 packets, 2885 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 SNAT       tcp  --  any    enp0s20u4u3  192.168.10.2         anywhere             tcp spt:search-agent to:192.168.10.1

So, the inbound TCP packets are not matching against the first PREROUTING chain rule. I am unsure where the mistake is; the first rule is so simple. The idea is:

Inbound traffic for 192.168.2.50:10000 gets NAT'd to 192.168.10.2:1234 on a private interface.

  • 1. You don't need the FORWARD ACCEPT rule, the FORWARD chain is in ACCEPT by default (except if you changed it). 2. tcpdump is quite useful to know, what exactly happened to your packets (both on the internal and on the external interface). 3. You don't have to overwrite the source (although it is possible), the connection tracking + the default route normally solves that. – peterh Jan 24 '17 at 13:41
  • @peterh, The network traffic seems fine, albeit short (because the connection is denied). the inclusion of SNAT seemed to make sense considering my private IP address is not the same as my external facing one. – sherrellbc Jan 24 '17 at 14:21
  • Check if the ip and port were well overwritten... if they were, it should work. Check both on the incoming and on the outgoing interface. – peterh Jan 24 '17 at 14:41
  • @peterh, How can this be done? The connection is being refused by the host. I am under the impression this implies the packet never made it through the kernel net filter, so it never gets forwarded to the private interface. Packet inspection on private interface produces no results. Packet inspection on the public interface only shows the initial connection to port 10000. – sherrellbc Jan 24 '17 at 14:44
  • 1) also refused packets are useful, you know if they at least went out or not. If yes, you can see if their dst ip and port were well written or not 2) you can modify your config step by step and see what happens. 3) something should have been sent, or you hadn't got a connection refused, but a connection timeout after a long wait. Check what was it. 4) You can also use the LOG target of the iptables, and check what was logged by a dmesg. – peterh Jan 24 '17 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.