This is how to make sure active AND passive FTP work flawlessly with IPtables, in this case, on CentOS. In this case it was for a DirectAdmin server.
You have to look up in your ftpd config which passive FTP ports your daemon uses and use those. In my case the portrange was 35000-35999.
This is /etc/sysconfig/iptables
# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#active and passiev ftp
-A RH-Firewall-1-INPUT -p tcp --syn --dport 21 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --syn --dport 20 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --syn --dport 35000:35999 -j ACCEPT
#ssh only for me
-A RH-Firewall-1-INPUT -s 1.2.3.4 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
#other useful ports available to the public
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 110 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 2222 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
Now we have to make sure some iptables modules are loaded.
Edit /etc/sysconfig/iptables-config
Make sure this line is looking like this:
IPTABLES_MODULES="ip_conntrack_netbios_ns ip_nat_ftp ip_conntrack_ftp"
Restart your iptables and test your ftp connection. It should work as expected.