1

I'm trying to configure a new server's iptable. Here are my rules inside a firewall.sh script that I execute:

#!/bin/bash

# Ports recap:
# ---- web: 80, 443
# ---- mail: 25 (smtp), 465 (smtps), 143 (imap), 993 (imaps), 110 (pop), 995 (pops)
# ---- ssh: 22
# ---- ftp: 20


# Allowed tcp ports
ALLOWED_TCP="80 443 22 20 25 465 143 993 110 995"
ALLOWED_TCP="80 443 22"





# Flush the filter table from INPUT or OUTPUT
iptables -F


# Permit loopback interface traffic (because our host is not a router)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT


# Drop invalid traffic (good idea since we use the connexion track module)
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP


# Allow icmp traffic (ping)
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT



for port in $ALLOWED_TCP
do
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
done


# Allow DNS traffic
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT


# Permit no more than 50 concurrent connections from the same ip address to our web server
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 50 -j DROP


# Allow all outgoing valid traffic 
iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT


# Set the default policy to drop
iptables -P INPUT DROP
iptables -P OUTPUT DROP

The problem with those rules is that then when I try to do:

apt-get install iptables-persistent

And then confirm with Y, the download freezes. I've done some tests and I know that without those rules the apt-get command works just fine, so I know there is something wrong with my iptables rules, but I can't figure what. Any idea? (basically I have the same problem as apt-get not working with iptables)

UPDATE

I did a few tests, and this works (I removed the INPUT DROP policy at the end), however, I still don't get what in the INPUT is causing problems.

@Ryan Gibbons, yes my first ALLOWED_TCP line is just a template in case I want to activate more ports (only the second line is considered

#!/bin/bash

# Ports recap:
# ---- web: 80, 443
# ---- mail: 25 (smtp), 465 (smtps), 143 (imap), 993 (imaps), 110 (pop), 995 (pops)
# ---- ssh: 22
# ---- ftp: 20


# Allowed tcp ports
ALLOWED_TCP="80 443 22 20 25 465 143 993 110 995"
ALLOWED_TCP="80 443 22 53"





# Flush the filter table from INPUT or OUTPUT
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F


# Permit loopback interface traffic (because our host is not a router)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT


# Drop invalid traffic (good idea since we use the connexion track module)
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP


# Allow icmp traffic (ping)
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT



for port in $ALLOWED_TCP
do
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
done




# Permit no more than 50 concurrent connections from the same ip address to our web server
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 50 -j DROP


# Allow all outgoing valid traffic 
iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT


# Set the default policy to drop
#iptables -P INPUT DROP
iptables -P OUTPUT DROP
1
  • You also need to accept established / related incoming traffic using something like -A INPUT -m state -- state ESTABLISHED,RELATED -j ACCEPT – Lenniey May 8 '19 at 14:16
2

First off, ALLOWED_TCP block is only going to be 80 443 and 22 as it's over riding the first definition.

# Allowed tcp ports
ALLOWED_TCP="80 443 22 20 25 465 143 993 110 995"
ALLOWED_TCP="80 443 22"

Next you only use these in allowing on the INPUT, meaning incoming to the server

for port in $ALLOWED_TCP
do
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
done

Then you never define what's allowed out from the server in OUTPUT besides DNS and related traffic,

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

and

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

Then set default policy to drop outbound

iptables -P OUTPUT DROP

It might be as simple as in your for loop to add another line for adding those ALLOWED_TCP to OUTPUT while keeping your outbound filtering.

0

Actually I had a typo, the only error I had was using tcp for DNS (instead of udp).

So this script below will work just fine (and for those interested, I learned that syntax here: https://www.udemy.com/linux-security-the-complete-iptables-firewall-guide/):

@Ryan Gibbons, yes my first ALLOWED_TCP line is just a template in case I want to activate more ports (only the second line is considered)

UPDATE: fix typo UPDATE2: fixed problem with apt install fail2ban

#!/bin/bash

# Ports recap:
# ---- web: 80, 443
# ---- mail: 25 (smtp), 465 (smtps), 143 (imap), 993 (imaps), 110 (pop), 995 (pops)
# ---- ssh: 22
# ---- ftp: 20


# Allowed tcp ports
ALLOWED_TCP="80 443 22 20 25 465 143 993 110 995"
ALLOWED_TCP="80 443 22"





# Flush the filter table from INPUT or OUTPUT
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F


# Permit loopback interface traffic (because our host is not a router)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT


# Drop invalid traffic (good idea since we use the connexion track module)
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP


# Allow icmp traffic (ping)
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT



for port in $ALLOWED_TCP
do
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
done



# https://ubuntuforums.org/showthread.php?t=1441483
# DNS
iptables -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
iptables -A INPUT -p udp -m udp --sport 53 -j ACCEPT

# apt-get
iptables -A INPUT -p tcp --sport 80 -j ACCEPT




# Permit no more than 50 concurrent connections from the same ip address to our web server
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 50 -j DROP


# Allow all outgoing valid traffic 
iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT


# Set the default policy to drop
iptables -P INPUT DROP
iptables -P OUTPUT DROP
4
  • This will only work for HTTP traffic, no HTTPS or anything else. And why do you set the default policy two times? – Lenniey May 8 '19 at 14:17
  • So that I can execute the script many times without being blocked outside the server (I did a few tests, and I blocked myself a couple of times, so I figured that since the script is only called once on every reboot, it doesn't matter if I "spend" two more lines defining a policy that I override later in the same script). In other words, as soon as I execute the script for the second time, the policy is still set on DROP, and I get blocked out, whereas with those two first lines, the policy is forced to ACCEPT before and so the rest of the script can continue. – ling May 8 '19 at 14:28
  • 443 is actually https, so it would cover http, https and ssh (but yes, nothing else, but that's just a configurable template...). – ling May 8 '19 at 14:29
  • I meant your added # apt-get iptables -A INPUT -p tcp --sport 80 -j ACCEPT line from before your edit... – Lenniey May 8 '19 at 14:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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