I'm facing the following issue with Linux kernel 4.10-28-generic, embedded in Ubuntu-16.04.02-LTE. My machine has two ethernet adapters, namely the following ones:

enp0s3: (internal network)
enp0s8: (external network)

In the internal network, connected to enp0s3, there is an FTP server and a telnet server I want to access from the external network connected through enp0s8.
The FTP mode is requested to be active.

To accomplish this task I use the following iptables rules:

modprobe nf_conntrack_ftp  
modprobe nf_nat_ftp  
sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"  

## Masquerade settings
iptables -A POSTROUTING -t nat -o enp0s3 -j MASQUERADE
iptables -A POSTROUTING -t nat -o enp0s8 -j MASQUERADE  

## ftp rules
iptables -t nat -I PREROUTING  -p tcp -m tcp --dport 20         -i enp0s8 -j DNAT --to-destination 
iptables -t nat -I PREROUTING  -p tcp -m tcp --dport 21         -i enp0s8 -j DNAT --to-destination
iptables -t nat -I PREROUTING  -p tcp -m tcp --dport 1024:65535 -i enp0s8 -j DNAT --to-destination

## telnet rules
iptables -t nat -I PREROUTING -p tcp -m tcp --dport 23 -i enp0s8 -j DNAT --to-destination`

These rules work well with Ubuntu-10, that has Linux kernel 2.6.32-38-generic, but with the new kernel data connection can't be established: when the client issues the PORT command, the server receives the IP address of the external network and not that of the internal one. According to "netstat" running on server side, it seems that the module "nf_nat_ftp" is not working well, that is it does not substitute the client IP address (external address) with that of the input interface enp0s8, (internal address) before forwarding the command to the server. For this reason the server get stuck trying to establish a connection with the external IP address (SYN state).
No problem with the FTP working in passive mode and with telnet connection as well.

Could you give me a suggestion to overcome this issue? Is it a regression or am I expected to change my iptables rules according to some new requirements?

Thank you in advance!

Best regards, Stefano

1 Answer 1


I already answered it at superuser.com

Basically newer kernels ( >= 4.7 ) are deprecating the automatic helper module's port assignment in favor of explicit rules.

Short fix to get the old behaviour:

echo 1 > /proc/sys/net/netfilter/nf_conntrack_helper

Better long term fix (requiring more work but giving better control):

See the CT target description in the iptables-extensions(8) man page for further information.`

and read also this blog for examples:


IMPORTANT NOTE: many of your FTP rules don't make any sense (you need only the 2nd rule). For example there's no such --dport 20. Ever. Active FTP uses source port 20, never destination port 20. The nf_conntrack_ftp/nf_nat_ftp handle all this already. Don't attempt to nat related connections at all, that's the helper's job.

If you're firewalling, in the firewall rules (filter not nat) you only need the usual -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT (but read the blog about this too for the long term solution). Perhaps you didn't put all of your rules, or you just don't use any firewall?

  • This deprecated (for many years) feature has been removed in kernel 6.0 . Using iptables' (or alt. nftables') explicit port helper assignment is now mandatory.
    – A.B
    Nov 28, 2022 at 6:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .