IPTables Configuration – Allow Outgoing MySQL Connections Only

iptables

I have a server which doesn't allow connections to mysql from external sources – all of my databases and connections take place on localhost. The default policy of iptables is to drop connections for any ports that I don't specify (currently I don't have port 3306 specified in my iptable rules, so all connections to this port are dropped).

That's fine, but now I'd like to connect to a mysql database located externally on Amazon RDS.

Port 3306 can be opened up to the outside world as follows:

iptables -t filter -A INPUT -p tcp --sport 3306 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 3306 -j ACCEPT

This allows me to connect to the database on Amazon RDS, however it also allows remote connections to databases on my server.

What do I need to do to allow my server to connect to the database on Amazon, but restrict external connections to the databases on my server?

Also bear in mind that the IP address of my Amazon RDS instance can change periodically I believe.

Best Answer

Take advantage of the state engine:

iptables -t filter -A OUTPUT -p tcp --dport 3306 -j ACCEPT
iptables -t filter -A INPUT -p tcp --sport 3306 -m state --state ESTABLISHED -j ACCEPT

or in later versions of iptables

iptables -t filter -A OUTPUT -p tcp --dport 3306 -j ACCEPT
iptables -t filter -A INPUT -p tcp --sport 3306 -m conntrack --ctstate ESTABLISHED -j ACCEPT

This is exactly what the state engine exists to do: allow traffic which meets various criteria (eg, protocol, source port) but is also part of an existing connection (as it defines connection). The upshot is that the outgoing TCP SYN packet to a particular external IP address on destination port 3306, from a local ephmeral port, will create a state table entry for that particular combination of IP addresses and port numbers, and only return traffic with the same combination of addresses and ports will be permitted through, and only for the duration of that connection.