How to block all ports except 80,443 with iptables?

156,682

Solution 1

First the ! is the NOT symbol.

iptables -A INPUT -p tcp -m tcp -m multiport ! --dports 80,443 -j DROP

Second, the rules you wrote may not have the expected results. You drop everything including the response to the connection on port 80. Therefore, you will not be able to connect to it says for the purposes of a web server.

These rules allow RELATED and ESTABLISHED connections so a web server should function, if that is in fact what your trying to do.

iptables -A INPUT -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT
<insert further allowed list here>
iptables -A INPUT -m conntrack -j ACCEPT  --ctstate RELATED,ESTABLISHED
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -j DROP
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -j DROP
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -j DROP

So its now 2022 and I thought I would update this briefly.

iptables -A INPUT -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT
<insert further allowed list here>
iptables -A INPUT -m conntrack -j ACCEPT  --ctstate RELATED,ESTABLISHED
iptables -A INPUT -j DROP
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -j DROP
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -j DROP

This update acknowledges that "-m state" is depreciated.

Solution 2

# Set the default policy of the INPUT chain to DROP
iptables -P INPUT DROP

# Accept incomming TCP connections from eth0 on port 80 and 443
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT

This should give you what you need

Solution 3

You can set your default action to DROP, and then create exception rules to allow 80 and 443, like so:

# Setting default policies:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Exceptions to default policy
iptables -A INPUT -p tcp --dport 80 -j ACCEPT       # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT      # HTTPS

iptables will go through the list of 'exceptions' until it finds a match. It will then perform the action specified by the -j parameter (ACCEPT in this case). If it doesn't find a match, it will fall back to the default policy and drop the packet.

Note that with this workaround any sub-domains will be locked out. For example with this method you will have it working on www.mydomain.com all right but your subdomain let's say www.sub.mydomain.com will not open for DNS errors.

Share:
156,682

Related videos on Youtube

user71169
Author by

user71169

Updated on September 18, 2022

Comments

  • user71169
    user71169 over 1 year

    Blocking all ports(in and out) is easy but it's hard with the word "except". I don't know any rules that satisfies the condition.

    PS: I know this question is nothing new. But in fact, I didn't find anything helps. So, help me pls!

    • user71169
      user71169 almost 10 years
      I do this: iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -I INPUT -p tcp --dport 80 -j ACCEPT ------ It's not work!
  • user71169
    user71169 almost 10 years
    It should be work but it's not. I'm so confuse.
  • mtak
    mtak almost 10 years
    What doesn't work? Does it allow all incoming packets, or none? Can you update your question with the output of iptables -nvL?
  • user71169
    user71169 almost 10 years
    Sorry! It's not me, someone did that :)) Yep, You sure like I am but It's not work. That why I have to make the question.
  • Cristian Ciupitu
    Cristian Ciupitu almost 10 years
    Shouldn't ! be escaped like this \!, if the Bash shell is used?
  • cybernard
    cybernard almost 10 years
    @CristianCiupitu No it should not need to be escaped. You may have something weird going on, but on my bash I don't need to escape it.
  • Cristian Ciupitu
    Cristian Ciupitu almost 10 years
    By the way the port numbers could be replaced with names from services i.e. http and https.
  • user71169
    user71169 almost 10 years
    I checked output of "iptables -nvL" to see packages in connection. It seems to work, your rules. But I can't check It's really work or not except using some apps which using those ports. An App use a port doesn't mean It use that port only. So, any suggest to check?
  • Cristian Ciupitu
    Cristian Ciupitu almost 10 years
    @cybernard, yes, you're right. A plain ! doesn't need to be escaped. Sorry about the false alarm.
  • cybernard
    cybernard almost 10 years
    @user71169 Yes. grc.com/x/ne.dll?bh0bkyd2 Click Proceed to have shields up scan the ports. It does not matter how many ports an app tries to use as my rules will prevent the traffic from reaching the other ports even if they are open/active.
  • Ashesh
    Ashesh over 8 years
    Don't do this over ssh.
  • Mohd Shahid
    Mohd Shahid almost 8 years
    I ran the first command and I got disconnected from terminal which was used by ssh port. I am no longer able to login. what to do?
  • cybernard
    cybernard almost 8 years
    @MohammadShahid Rules are not permanent automatically, reboot and it will be gone and you can login. You need to add 22 to the list of ports if you want to maintain a ssh connection.
  • Maximilian Ast
    Maximilian Ast over 7 years
    Remember if you are connected through SSH you should open TCP port 22
  • jjxtra
    jjxtra over 5 years
    I thought DROP had the higher priority?
  • James Little
    James Little about 5 years
    Yes don't forget about your SSH port, probably should add your SSH port before you set the default policy to drop. ;)
  • Elijah Lynn
    Elijah Lynn about 4 years
    Would love to see an annotated version of this answer, with comments above each line explaining what is going on.
  • Tristan CHARBONNIER
    Tristan CHARBONNIER about 2 years
    Ok, it seems both -m conntrack and -m state are, in latest kernel, doing the same ("state" is deprecated and is "aliased" to "conntrack"). My question is why do we need this (state/conntrack) line in the INPUT chain? I mean, the line just above we ACCEPT everything with destination port 80/443. So why should we also accept connection with RELATED/ESTABLISHED states without taking care of port?
  • cybernard
    cybernard about 2 years
    @TristanCHARBONNIER The reason we have RELATED,ESTABLISHED alone is because we want ALL ports to be covered by this. Why? Because when a web server receives a connection request, it hands connect off to a random port number so port 80 is free to handle the next request. Also if the system is being used for anything else like web browsing, or even system updates the connection will also use a RANDOM port number. Therefore RELATED,ESTABLISHED can not have fixed port numbers.
  • cybernard
    cybernard about 2 years
    @TristanCHARBONNIER Regarding the "state" part, my original answer was posted in 2014, but now in 2022 if you have a modern version of IPTABLES then you make replace the "state" with "conntrack" references. So, if anyone comes through and is still using an OLD version of iptables they know what they have to do to succeed.