I am trying to configure iptables for ProFTPD on Debian 9. Access will be from within a LAN. There is no NAT involved.Based on what i have read so far, this doesn't warrant Passive FTP?

The only other incoming access is SSH, this will be restricted to a single source IP.

Outbound access is only required to apt package updates. I have not got around to putting the rules for this in place.

The rules mentioned here, get FTP working fine, but block all outbound traffic.

The present configuration is

-A INPUT -p tcp -m tcp --dport 22 -s xxx.xxx.xxx.xxx -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -s yyy.yyy.yyy.yyy/25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 20 -s yyy.yyy.yyy.yyy/25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --sport 1024:65535 --dport 20:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -p tcp -m tcp --dport 21 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 20 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 1024:65535 --dport 20:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Actually, your ruleset should be fine for outbound packets: the problem is that incoming responses to those packets are getting rejected.

The main problem is this line:

-A INPUT -p tcp -m tcp --sport 1024:65535 --dport 20:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

For example, when you're attempting to run a package update, the apt tool will send out a connection to a Debian mirror server, typically to destination port 80 for HTTP. The source port will be a random high port (certainly above 1024, let's say 12345).

The response to this packet is going to come back from the Debian mirror with the source and destination port numbers flipped around: the response's source port number will be 80 and destination port number will be 12345.

But your incoming rule will not match any incoming packets with source port lower than 1024, no matter whether they are new or already-established connections. As a result, you're sending connection requests out to port 80 but are deaf to any answers coming back from it.

I'd recommend the following as your first two INPUT rules:

-A INPUT -i lo -j ACCEPT    # accept anything from the loopback interface
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

The first line will accept anything that goes through the loopback interface, or in other words, processes within your own computer talking to each other using network protocols. When the traffic comes in via the loopback interface, the source is by definition on the same computer, so there is normally little reason to block them.

The second line accepts any valid incoming responses to any outgoing connections, and anything related to them (e.g. an ICMP error packet telling you what is wrong with a particular connection attempt). If the appropriate special connection tracking helper for FTP has been activated, this line will also take care of FTP data connections, whether active or passive. Read on...

(The -m state match you're using is obsolete and getting deprecated; my -m conntrack --ctstate ESTABLISHED,RELATED is basically the updated version of it.)

FTP connections will be much easier to handle if you invoke the appropriate connection tracking helper for them. This used to be automatic before, but then someone found a way to abuse the automatic helper selection and it had to be disabled.

So, tell the system that we expect any incoming connections from your network to your TCP port 21 to be valid FTP control connections:

-t raw -A PREROUTING -p tcp -s yyy.yyy.yyy.yyy/25 --dport 21 -j CT --helper ftp

As an incoming FTP control connection is established, the FTP conntrack helper will monitor any file transfer commands issued within it, and will automatically make the conntrack subsystem aware of any related FTP data connections, so that the earlier "ESTABLISHED,RELATED" rule will accept them and only them: no need to keep a wide range of ports open for potential FTP data connections any more!

When the FTP conntrack helper is in use, you'll no longer need any rules for port 20, nor any of your rules with --sport 1024:65535 or --dport 20:65535.

Attempts to hijack passive-FTP data connections will be automatically foiled too: the connection tracking subsystem will see that the hijacker's connection does not come from the same source as the FTP control connection that called for data transfer, and so the hijacking attempt will not get matched, and gets rejected by default.

If you are using FTP mirrors for your Debian updates, you'll want a similar handling for any outgoing FTP connections too. This can be done with:

-t raw -A OUTPUT -p tcp --dport 21 -j CT --helper ftp

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.