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
ling
  • 303
  • 1
  • 2
  • 13
  • You also need to accept established / related incoming traffic using something like `-A INPUT -m state -- state ESTABLISHED,RELATED -j ACCEPT` – Lenniey May 08 '19 at 14:16

2 Answers2

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.

Ryan Gibbons
  • 998
  • 9
  • 20
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
ling
  • 303
  • 1
  • 2
  • 13
  • This will only work for HTTP traffic, no HTTPS or anything else. And why do you set the default policy two times? – Lenniey May 08 '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 08 '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 08 '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 08 '19 at 14:34