# How to open ftp ports in iptables?

## bpaddock

I have a restrictive firewall on my server been working fine for web access on port 80.

Now I'm trying to get vsftpd running.  My google fu is failing me on how to get iptables setup to allow ftp.

If I do nmap example.com from inside the server machine via ssh nmap shows that port 21 is open.

If I do nmap example.com from outside of the box only port 80 is open.

From allowing local loop back?

Here are my iptable rules.  What is wrong with the FTP ones?

```
*filter

#  Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0

-A INPUT -i lo -j ACCEPT

-A INPUT -d 127.0.0.0/8 -j REJECT

#  Accept all established inbound connections

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allow all outbound traffic - you can modify this to only allow certain traffic

-A OUTPUT -j ACCEPT

#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).

-A INPUT -p tcp --dport 80 -j ACCEPT

#-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allow SSH connections

#

#  The -dport number should be the same port number you set in sshd_config

#

-A INPUT -p tcp -m state --state NEW --dport 2222 -j ACCEPT

#  Allow ping

-A INPUT -p icmp -j ACCEPT

# FTP:

-A INPUT  -p tcp -m tcp --dport 21 -m conntrack --ctstate ESTABLISHED -j ACCEPT -m comment --comment "Allow ftp connections on port 21"

-A OUTPUT -p tcp -m tcp --dport 21 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT -m comment --comment "Allow ftp connections on port 21"

-A INPUT  -p tcp -m tcp --dport 20 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow ftp connections on port 20"

-A OUTPUT -p tcp -m tcp --dport 20 -m conntrack --ctstate ESTABLISHED -j ACCEPT -m comment --comment "Allow ftp connections on port 20"

#  Log iptables denied calls

-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

#  Drop all other inbound - default deny unless explicitly allowed policy

-A INPUT -j DROP

-A FORWARD -j DROP

COMMIT

```

----------

## Hu

Your port 80 rule matches without regard to connection state, so it matches NEW and ESTABLISHED.  Your ftp-inbound rule does not allow NEW, so outside systems cannot start a new connection to your ftp server.  If they somehow had one anyway, then your rule would allow them to keep using it.  Is this meant to be an ftp client or ftp server?  Your INPUT rules are for an ftp server, but your OUTPUT rules are for an ftp client.

----------

## bpaddock

 *Hu wrote:*   

> Your port 80 rule matches without regard to connection state, so it matches NEW and ESTABLISHED.  Your ftp-inbound rule does not allow NEW, so outside systems cannot start a new connection to your ftp server.  If they somehow had one anyway, then your rule would allow them to keep using it.  Is this meant to be an ftp client or ftp server?  Your INPUT rules are for an ftp server, but your OUTPUT rules are for an ftp client.

 

I'm trying to get vsftpd up as a server.

Clearly I'm not an iptables expert.

What do you suggest?

----------

## Hu

I suggest not using FTP.  It is not a firewall friendly protocol.  TLS is not a standard feature on the connection, although some clients can negotiate it with the right extensions.

If you must use FTP, ensure that the server only allows passive mode.  Allow incoming connections to ftp and ftp-data for types NEW, ESTABLISHED.  If your OUTPUT policy is ACCEPT, then you do not need any OUTPUT rules related to the ftp server.

----------

## lost+found

You might be interested in using this as a starting point:

```
*raw

:PREROUTING ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

[0:0] -A PREROUTING -p tcp -m tcp --dport 21 -j CT --helper ftp

[0:0] -A PREROUTING -j ACCEPT

[0:0] -A OUTPUT -p tcp -m tcp --dport 21 -j CT --helper ftp

[0:0] -A OUTPUT -j ACCEPT

COMMIT

*filter

:INPUT DROP [0:0]

:FORWARD DROP [0:0]

:OUTPUT DROP [0:0]

[0:0] -A INPUT -s 127.0.0.1/32 -i lo -j ACCEPT

[0:0] -A INPUT -s 123.123.123.123/32 -i lo -j ACCEPT

[0:0] -A INPUT -d 255.255.255.255/32 -i eth0 -j DROP

[0:0] -A INPUT ! -d 123.123.123.123/32 -i eth0 -j DROP

[0:0] -A INPUT -p tcp -m multiport --dports 0:19,22:1023 -j DROP

[0:0] -A INPUT -p udp -m multiport --dports 0:1023 -j DROP

[0:0] -A INPUT -d 123.123.123.123/32 -i eth0 -p tcp -m tcp --dport 21 --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ACCEPT

[0:0] -A INPUT -d 123.123.123.123/32 -p tcp -m conntrack --ctstate RELATED -m helper --helper ftp -m tcp --dport 50000:50400 -j ACCEPT

[0:0] -A INPUT -i eth0 -p tcp -m conntrack --ctstate RELATED -m helper --helper ftp -m tcp --dport 1024:65535 -j ACCEPT

[0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

[0:0] -A INPUT -j DROP

[0:0] -A OUTPUT -d 127.0.0.1/32 -o lo -j ACCEPT

[0:0] -A OUTPUT -d 123.123.123.123/32 -o lo -j ACCEPT

[0:0] -A OUTPUT -d 255.255.255.255/32 -o eth0 -j DROP

[0:0] -A OUTPUT ! -s 123.123.123.0/23 -o eth0 -j DROP

[0:0] -A OUTPUT -o eth0 -p icmp -m icmp ! --icmp-type 8 -j DROP

[0:0] -A OUTPUT -s 123.123.123.123/32 -o eth0 -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

[0:0] -A OUTPUT -p tcp -m multiport --dports 0:19,22:24,26:52,54:79,81:109,111:118,120:142 -j REJECT --reject-with icmp-port-unreachable

[0:0] -A OUTPUT -p tcp -m multiport --dports 144:442,444:586,588:872,874:994,996:1023 -j REJECT --reject-with icmp-port-unreachable

[0:0] -A OUTPUT -p udp -m multiport --dports 0:52,54:122,124:1023 -j REJECT --reject-with icmp-port-unreachable

[0:0] -A OUTPUT -s 123.123.123.123/32 -o eth0 -p tcp -m multiport --dports 21,25,53,80,110,119,143,443,587,873,995,1755,1935,3690,9418 -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ACCEPT

[0:0] -A OUTPUT -s 123.123.123.123/32 -o eth0 -p udp -m multiport --dports 53,123 -m conntrack --ctstate NEW -j ACCEPT

[0:0] -A OUTPUT -o eth0 -p tcp -m conntrack --ctstate RELATED -m helper --helper ftp -m tcp --dport 1024:65535 -j ACCEPT

[0:0] -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

[0:0] -A OUTPUT -j REJECT --reject-with icmp-port-unreachable

COMMIT
```

123.123.123.123 = your ip

50000:50400 is a pure-ftpd port setting

It's pretty restrictive, but FTP client and server connections (passive and active) still work fine. I'm using pure-ftpd as the FTP server.

Also use safe settings for the FTP server, ofc.

Cheers!

----------

## Scotty49

I know, this thread is quite old, but indeed it was one of the first results when searching for gentoo, ftp and iptables.

So, if someone should stumble upon it, I would just like to add one more remark which took me quite a while until I savvied it:

IPTables + Connection Tracking (Conntrack) + FTP will not work properly, if you use FTP via TLS.

The reason I missed is quite simple: In order to perform connection tracking correctly (hence finding RELATED network traffic), the FTP data have to be introspected by iptables. This just isn't possible if the data is encrypted via TLS.

So, in a case like mine, you would have two options:

a) Disable TLS in favor of working and secure connection tracking

b) Do not rely on connection tracking, but instead open the FTP ports according to your configuration in iptables without using the "RELATED" state

IMHO there is no way to get both of them working at the same time.   :Sad: 

----------

## Ant P.

If it's a private FTP server you could just put it behind a single-use Wireguard VPN, sidestepping all the conntrack and certificate headaches entirely. That wasn't an option 5 years ago.

----------

## Scotty49

Great idea, thank you!

----------

