Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying a little bit of security by obscurity here and I want to do the following for a number of services (i.e. MySQL):

  • Let the services definitely run on localhost on their default port
  • Block remote access to the default port on public interfaces
  • Allow remote access to the services through an alternative port (i.e. 53306 for MySQL) for the sake of some customers

I've tried using iptables and REDIRECT or DNAT through a number of combinations to no avail, and using SSH tunnels is too technical for the customers to do.

Any help would be appreciated!

share|improve this question
Just for the record, running nmap -sV on a large port range will often still show the program responding to that port. This kind of security works somewhat against automated scans, but not so much against intentional attacks. – Halfgaar Jan 24 '11 at 9:36
Thanks for the tip, I've already considered that but I'm trying to get the best of both worlds. I'll be adding another one or two layers of security afterwards. – priestjim Jan 24 '11 at 9:48

You can try the following rules.

iptables -A INPUT -i eth0 -p tcp --dport 3306 -j DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 53306 -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 53306 -j DNAT --to-destination :3306

Assuming eth0 is the public interface. You will be able to access mysql port locally using


Don't forget to allow the output traffic and related (after connection establish).

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

Please, note that you may need to customise these rules for your needs. I am just trying to help. If your machine is publicly accessible without a network firewall, you should carefully study the firewall rules.

share|improve this answer
Already tried this exact configuration but didn't work...Neither local or remote access is possible in 53306. – priestjim Jan 24 '11 at 9:49
I am assuming mysql on the localhost as the firewall. Is this your case? If you are stil unable to connect, please post more details. – Khaled Jan 24 '11 at 9:53
MySQL is running with no bind-address so it's listening on all interfaces. The firewall rules are also local. Connecting from localhost to 3306 works fine, connecting either from localhost or remotely to 53306 fails. – priestjim Jan 24 '11 at 10:26
Have another look on the answer. – Khaled Jan 24 '11 at 10:32
Thanks for your suggestions, but I've already setup the firewall that way (it's still in a test environment so the rules are not yet complete)! tcpdump says it doesn't get past the SYN handshake... – priestjim Jan 24 '11 at 11:26
up vote 1 down vote accepted

I finally figured it out. For anyone who might care, here's what I did (please note that this is not a complete firewall configuration but just the lines needed to achieve what is described in the OP):

  • Mark all the packets that come through the mangle target destined to port 33306 (replace your alternative port here and your mark number if you wish)

    iptables -t mangle -A PREROUTING ! -i lo -p tcp -m tcp --dport 33306 -j MARK --set-mark 96

  • Redirect the packets to their legitimate port in the nat target

    iptables -t nat -A PREROUTING ! -i lo -p tcp -m tcp --dport 33306 -j REDIRECT --to-port 3306

  • Allow in 3306 only the packages that bring the mark with them

    iptables -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -t filter -A INPUT -i lo -j ACCEPT
    iptables -t filter -A INPUT ! -i lo -m tcp -p tcp --dport 3306 -m mark --mark 96 -j ACCEPT
    iptables -t filter -A INPUT ! -i lo -m tcp -p tcp --dport 3306 -j DROP

share|improve this answer

You need to use the REDIRECT target for this since you are sending the traffic to another port on the same server. Assuming your server's IP address is the command syntax would be:

iptables -t nat -A PREROUTING -p tcp -m tcp -d --dport 53306 -j REDIRECT --to-ports 3306

Or you could do it for all traffic inbound on an interface using the -i argument instead of the -d with IP address.

You will also need to allow the traffic to port 3306 on the INPUT chain:

iptables -A INPUT -p tcp -m tcp --dport 3306 -m state --state NEW -j ACCEPT
share|improve this answer
Wouldn't this also allow incoming connections to port 3306 on every interface? This is something I am trying to avoid! – priestjim Jan 25 '11 at 8:00

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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