Table of Contents

Firewall Part 3

Firewall with iptables

In this part we will cover the topics listed below:

Masquerading

As we have only one ip address towards the internet (public ip) and multiple hosts, network internally, we need to hide all internal ips behind the public ip.

This is done by the following command:

user@firewall01:~ $ sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

Basic rules

To access the internet, following rules are the minimum to be configured, inclusive the logging.

user@firewall01:~ $ sudo iptables -A FORWARD -p udp -o ens33 --match multiport --dport 53 -m conntrack --ctstate NEW -j LOG --log-prefix "IPT " --log-level info
user@firewall01:~ $ sudo iptables -A FORWARD -p udp -o ens33 --match multiport --dport 53 -m conntrack --ctstate NEW -j ACCEPT
user@firewall01:~ $ sudo iptables -A FORWARD -p tcp -o ens33 --match multiport --dports 53,80,443 -m conntrack --ctstate NEW -j LOG --log-prefix "IPT " --log-level info
user@firewall01:~ $ sudo iptables -A FORWARD -p tcp -o ens33 --match multiport --dports 53,80,443 -m conntrack --ctstate NEW -j ACCEPT

Scripting

Now that we have some rules in place and sometimes order of rules matter, we should create a script, to configure or stop the firewall.

First of all, we create a new directory to store the scripts.

user@firewall01:~ $ mkdir -p scripts/firewall
user@firewall01:~ $ cd scripts/firewall

Firewall start script

fw-start.sh
#!/usr/bin/bash
# create variable for iptables
IPT=$(which iptables)
# Switch off routing
echo 0 > /proc/sys/net/ipv4/ip_forward
# Flush rules
$IPT -F
# Delete user defined chains
$IPT -X
# Flush table nat
$IPT -t nat -F
# Delete table nat
$IPT -t nat -X
# Set policy of INPUT chain to DROP
$IPT -P INPUT DROP
# Set policy of OUTOUT chain to DROP
$IPT -P OUTPUT DROP
# Set policy of FORWARD chain to DROP
$IPT -P FORWARD DROP
# Switch on conntrack for FORWARD
$IPT -A FORWARD -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT
$IPT -A FORWARD -m conntrack --ctstate=INVALID -j DROP
# Switch on conntrack for INPUT
$IPT -A INPUT -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT
$IPT -A INPUT -m conntrack --ctstate=INVALID -j DROP
# Switch on conntrack for OUTPUT
$IPT -A OUTPUT -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -m conntrack --ctstate=INVALID -j DROP
# Anti lock-out rule
$IPT -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j LOG --log-prefix "IPT " --log-level info
$IPT -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Allow local traffic for INPUT chain
$IPT -A INPUT -i lo -j ACCEPT
# Allow local traffic for FORWARD chain
$IPT -A FORWARD -i lo -o lo -j ACCEPT
# Allow all from firewall
$IPT -A OUTPUT -j ACCEPT
# Hide internal network behind gateway ip (SNAT)
$IPT -t nat -A POSTROUTING -o ens33 -j MASQUERADE
# Create chain for LOGGING
$IPT -N LOGGING
# Enable logging for DROP on INPUT
$IPT -A INPUT -j LOGGING
# Write to log
$IPT -A LOGGING -j LOG --log-prefix "IPT Drop: " --log-level info
# Drop packets
$IPT -A LOGGING -j DROP
# Enable logging for DROP on OUTPUT
$IPT -A OUTPUT -j LOGGING
# Write to log
$IPT -A LOGGING -j LOG --log-prefix "IPT Drop: " --log-level info
# Drop packets
$IPT -A LOGGING -j DROP
# make rules persitant
/usr/sbin/iptables-save > /etc/iptables/rules.v4
# Switch on routing
echo 1 > /proc/sys/net/ipv4/ip_forward

Firewall stop script

fw-stop.sh
#!/usr/bin/bash
# Echoing what is happening
echo "Stopping IPv4 firewall and allowing everyone..."
# Create var for ''iptables''
ipt=$(which iptables)
## Failsafe - die if /sbin/iptables not found
[ ! -x "$ipt" ] && { echo "$0: \"${ipt}\" command not found."; exit 1; }
# Set ''INPUT'' policy to ''ACCEPT''
$ipt -P INPUT ACCEPT
# Set ''FORWARD'' policy to ''ACCEPT''
$ipt -P FORWARD ACCEPT
# Set ''OUTPUT'' policy to ''ACCEPT''
$ipt -P OUTPUT ACCEPT
# Flush all rules
$ipt -F
# Delete all user defined chains
$ipt -X
# Flush all from table ''nat''
$ipt -t nat -F
# Delete table ''nat''
$ipt -t nat -X
# Flush all from table ''mangle''
$ipt -t mangle -F
# Delete table ''mangle''
$ipt -t mangle -X
# Flush all from table ''raw''
$ipt -t raw -F
# Delete table ''raw''
$ipt -t raw -X

bash aliases

Commands to control or show iptables can be very long. So I created a basic .bash_aliases to make it easier. Some of the aliases make sense later on ;-)

alias tulpe='sudo netstat -tulpne'
 
# Ubuntu package management 
alias saptd='sudo apt update'
alias saptdg='sudo apt update && sudo apt upgrade -y'
alias saptg='sudo apt upgrade'
alias sapti='sudo apt install'
 
# control bash
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias mnt="mount | grep '^/dev'"
alias redo='sudo $(history -p !!)'
alias myip='curl icanhazip.com'
 
# aliases for iptables
alias ipt='sudo iptables'
alias iptl='sudo iptables -n -v --line-number -L'
alias iptf='sudo iptables -F'
alias iptr='sudo netfilter-persistent reload'
alias ipts='sudo netfilter-persistent save'
 
# start & stop firewall
alias fwstart='sudo /home/user/scripts/fw-start.sh'
alias fwstop='sudo /home/user/scripts/fw-stop.sh'
 
# save revision in git
alias pushrev='/home/user/scripts/push-rev.sh'

End of part three

Firewall Part 1 - Firewall Part 2 - Firewall Part 3 - Firewall Part 4

Please stay tuned for the Fourth part, where we cover these topics: