Sendmail doesn't work with iptables, even though smtp and dns are allowed

I have sendmail installed on Ubuntu 10.04 solely for the use of the php mail() function. This works fine unless iptables is running (I've been using sendmail [email protected] to test this).

I think that I have allowed SMTP and DNS (the script I am using to test iptables rules is below, in my version are the actual IPs of my hosts nameservers), but to no avail!

iptables --flush

iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Postgres
iptables -A INPUT -p tcp --dport 5432 -j ACCEPT

# Webmin
iptables -A INPUT -p tcp --dport 10000 -j ACCEPT

# Ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT

# sendmail
iptables -A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT

# DNS
iptables -A INPUT -p udp --sport 53 -s <nameserver1> -j ACCEPT
iptables -A INPUT -p udp --sport 53 -s <nameserver2> -j ACCEPT
iptables -A INPUT -p tcp --sport 53 -s <nameserver1> -j ACCEPT
iptables -A INPUT -p tcp --sport 53 -s <nameserver2> -j ACCEPT

iptables -A OUTPUT -p udp --dport 53 -d <nameserver1> -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -d <nameserver2> -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -d <nameserver1> -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -d <nameserver2> -j ACCEPT


iptables -A INPUT -j DROP

# Add loopback
iptables -I INPUT 1 -i lo -j ACCEPT

Currently you have:

iptables -A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT

Which allows:

  • packets to your sendmail in,
  • packets from your port 25 out, but only for already established connections (so only connections from the outside).

For outgoing E-mails, you need your sendmail to be able to connect to the outside world.

So you'll need something like this as well:

iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT

Please make sure you don't become an open relay.


I am assuming you will be connecting to a relay (smarthost) to send mail and don't need any incoming mail. If not, will have more work to do. Automated systems tend not to have well configured email services which can result in their mail being dropped or sent to the spam bucket.

You may want to use conntrack to handle established connections. This simplifies the rest of your rules as you only need to worry about new connections in the rest of the rules.

iptable -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptable -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Your rules before your ping entries look good.

Your rules need to cover outgoing traffic

iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

Your ICMP rules seem incomplete

iptables -A INPUT -p icmp --icmp-type 3/4 -j ACCEPT 
iptables -A INPUT -p icmp --icmp-type 11 -j ACCEPT 
iptables -A OUTPUT -p icmp --icmp-type 3/4 -j ACCEPT 
iptables -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT 
iptables -A OUTPUT -p icmp --icmp-type 11 -j ACCEPT