Firewall basics
Contents
Set IP preference
If you enable IPv6 then that will be the default.
You can override that and set IPv4 as the default protocol:
vim /etc/gai.conf
About line 54, un-comment the following line:
#
# For sites which prefer IPv4 connections change the last line to
#
precedence ::ffff:0:0/96 100
Enable modules
First things first! Before writing any rule you have to enable the required modules in your current O.S.
- Note -
If your server is hosted over Internet then you're probably using a custom Kernel (such as OVH, Tripnet, ...). In that case most modules are already enabled.
MODPROBE=`which modprobe`
echo -e " "
echo -e "-----------------------------"
echo -e " Enable networking modules"
echo -e "-----------------------------"
# IPv4
echo " ... IPv4"
$MODPROBE ip_tables
$MODPROBE iptable_filter
$MODPROBE iptable_mangle
# Allow to use state match
$MODPROBE ip_conntrack
# IPv6
echo " ... IPv6"
$MODPROBE ip6_tables
$MODPROBE ip6table_filter
$MODPROBE ip6table_mangle
# Allow NAT
echo " ... NAT"
$MODPROBE iptable_nat
# Allow active / passive FTP
echo " ... FTP"
$MODPROBE ip_conntrack_ftp
$MODPROBE ip_nat_ftp
# Allow log limits
echo " ... burst limit"
$MODPROBE ipt_limit
Network features
Now that you've enable some modules, you need to choose which Network's features you're gonna use or not.
IPTABLES=`which iptables`
IP6TABLES=`which ip6tables`
echo -e " "
echo -e "------------------------"
echo -e " Set network features"
echo -e "------------------------"
echo " ... Enable common Linux protections"
# Avoid broadcast echo
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# avoid TCP SYN Cookie
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# protection against bogus responses
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
# Avoid IP Spoofing (discard non routable IP@)
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done
# Avoid ICMP redirect
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 0 > /proc/sys/net/ipv6/conf/all/accept_redirects
# Avoid Source Routed
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 0 > /proc/sys/net/ipv6/conf/all/accept_source_route
## Check TCP window
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling
## Avoid DoS
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
## Adjust TTL value
echo 64 > /proc/sys/net/ipv4/ip_default_ttl
# Port forwarding in general
echo " ... Enable forwarding"
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
Default policy
Attacks types
As a reminder, there are 3 different kind of attacks:
- INPUT = intrusion. Someone want something from your computer, NOW.
- OUTPUT = disclosure. Someone want something from your computer or network - and you might give it LATER.
- FORWARD = get access. someone want something from your network. ... Or even worse: they will use your computer to perform attacks on your behalf!
You can read more about each attack over Internet.
Linux script
This is how you defined a default policy.
Note:
- You have to adjust the policy to your own settings
- You should NOT set the INPUT in ACCEPT mode. That's risky!
IPTABLES=`which iptables`
IP6TABLES=`which ip6tables`
echo -e " "
echo -e "------------------------"
echo -e " Flush existing rules "
echo -e "------------------------"
$IP6TABLES -F
$IP6TABLES -X
$IPTABLES -F
$IPTABLES -X
$IPTABLES -t filter -F
$IPTABLES -t filter -X
# delete NAT rules
$IPTABLES -t nat -F
$IPTABLES -t nat -X
# delete MANGLE rules (packets modifications)
$IPTABLES -t mangle -F
$IPTABLES -t mangle -X
$IP6TABLES -t mangle -F
$IP6TABLES -t mangle -X
echo -e " "
echo -e "------------------------"
echo -e " Default policy"
echo -e "------------------------"
echo -e " || --> OUTGOING reject all "
echo -e " --> || INCOMING reject all "
echo -e " --> || --> FORWARDING reject all (each redirection manual needs configuration)"
# INCOMING = avoid intrusions
# OUTGOING = avoid disclosure of sensitive / private data
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP
$IP6TABLES -P INPUT DROP
$IP6TABLES -P FORWARD DROP
$IP6TABLES -P OUTPUT DROP
echo -e " ... Reject invalid packets"
$IPTABLES -A INPUT -p tcp -m state --state INVALID -j DROP
$IPTABLES -A INPUT -p udp -m state --state INVALID -j DROP
$IPTABLES -A INPUT -p icmp -m state --state INVALID -j DROP
$IPTABLES -A OUTPUT -p tcp -m state --state INVALID -j DROP
$IPTABLES -A OUTPUT -p udp -m state --state INVALID -j DROP
$IPTABLES -A OUTPUT -p icmp -m state --state INVALID -j DROP
$IPTABLES -A FORWARD -p tcp -m state --state INVALID -j DROP
$IPTABLES -A FORWARD -p udp -m state --state INVALID -j DROP
$IP6TABLES -A INPUT -p tcp -m state --state INVALID -j DROP
$IP6TABLES -A INPUT -p udp -m state --state INVALID -j DROP
$IP6TABLES -A INPUT -p icmp -m state --state INVALID -j DROP
$IP6TABLES -A OUTPUT -p tcp -m state --state INVALID -j DROP
$IP6TABLES -A OUTPUT -p udp -m state --state INVALID -j DROP
$IP6TABLES -A OUTPUT -p icmp -m state --state INVALID -j DROP
$IP6TABLES -A FORWARD -p tcp -m state --state INVALID -j DROP
$IP6TABLES -A FORWARD -p udp -m state --state INVALID -j DROP
echo " ... Avoid spoofing and local subnets"
# Reserved addresses. We shouldn't received any packets from them!
### TODO #### Adjust these values
$IPTABLES -A INPUT -s 10.0.0.0/8 -j DROP
#$IPTABLES -A INPUT -s 172.16.0.0/12 -j DROP
#$IPTABLES -A INPUT -s 192.168.0.0/16 -j DROP
$IPTABLES -A INPUT -s 169.254.0.0/16 -j DROP
## Localhost
echo -e " ... Allow localhost"
$IPTABLES -A INPUT ! -i lo -s 127.0.0.0/24 -j DROP
$IPTABLES -A OUTPUT ! -o lo -d 127.0.0.0/24 -j DROP
$IPTABLES -A FORWARD -s 127.0.0.0/24 -j DROP
$IP6TABLES -A INPUT ! -i lo -s ::1/128 -j DROP
$IP6TABLES -A OUTPUT ! -o lo -d ::1/128 -j DROP
$IP6TABLES -A FORWARD -s ::1/128 -j DROP
## IPv6 security
# No IPv4 -> IPv6 tunneling
echo " ... Do not allow IPv4 @ tunnel in IPv6 !! Use native IPv6 instead !!"
$IP6TABLES -A INPUT -s 2002::/16 -j DROP # 6to4 tunnels
$IP6TABLES -A FORWARD -s 2002::/16 -j DROP
$IP6TABLES -A INPUT -s 2001:0::/32 -j DROP # Teredo tunnels
$IP6TABLES -A FORWARD -s 2001:0::/32 -j DROP
# Block IPv6 protocol in IPv4 frames
echo " ... Block IPv6 protocol in IPv4 frames"
$IPTABLES -A INPUT -p 41 -j DROP
$IPTABLES -A OUTPUT -p 41 -j DROP
$IPTABLES -A FORWARD -p 41 -j DROP
## Stateful connections
echo -e " ... Keep ESTABLISHED connections "
$IPTABLES -A INPUT -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
$IP6TABLES -A INPUT -m state --state ESTABLISHED -j ACCEPT
$IP6TABLES -A FORWARD -m state --state ESTABLISHED -j ACCEPT
$IP6TABLES -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
echo -e " ... Keep RELATED connections (required for FTP by example)"
$IPTABLES -A INPUT -m state --state RELATED -j ACCEPT
$IPTABLES -A FORWARD -m state --state RELATED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state RELATED -j ACCEPT
$IP6TABLES -A INPUT -m state --state RELATED -j ACCEPT
$IP6TABLES -A FORWARD -m state --state RELATED -j ACCEPT
$IP6TABLES -A OUTPUT -m state --state RELATED -j ACCEPT
Protocol(s) enforcement
IPTABLES=`which iptables`
IP6TABLES=`which ip6tables`
echo -e " "
echo -e "------------------------"
echo -e " Protocols enforcement"
echo -e "------------------------"
echo -e " ... Layer 2: ICMP v4"
# ICMP packets should not be fragmented
$IPTABLES -A INPUT --fragment -p icmp -j DROP
# Limit ICMP Flood
$IPTABLES -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 0 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 3 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT
# Avoid common attacks ... but blocks ping :(
# [Network, Host, Protocol, Port] unreacheable + [Destination Host, Destination network] prohibited
#$IPTABLES -A OUTPUT -p icmp --icmp-type 3 -j DROP
echo -e " ... Layer 2: ICMP v6 "
# Feedback for problems
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 1 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 2 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 3 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 4 -j ACCEPT
# Router and neighbor discovery
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 133 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 134 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 135 -j ACCEPT
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 136 -j ACCEPT
$IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 133 -j ACCEPT
$IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 134 -j ACCEPT
$IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 135 -j ACCEPT
$IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 136 -j ACCEPT
# Ping requests
$IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT
$IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT
echo " ... Layer 4: TCP # check packets conformity"
# INCOMING packets check
# All new incoming TCP should be SYN first
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
# Avoid SYN Flood (max 3 SYN packets / second. Then Drop all requests !!)
$IPTABLES -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
# Avoid fragment packets
$IPTABLES -A INPUT -f -j DROP
# Check TCP flags -- flag 64, 128 = bogues
$IPTABLES -A INPUT -p tcp --tcp-option 64 -j DROP
$IPTABLES -A INPUT -p tcp --tcp-option 128 -j DROP
echo " ... Layer 4: TCP # Avoid NMAP Scans"
# XMAS-NULL
$IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# XMAS-TREE
$IPTABLES -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# SYN/RST Scan
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# SYN/FIN Scan
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# SYN/ACK Scan
#$IPTABLES -A INPUT -p tcp --tcp-flags ALL ACK -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -j DROP
# FIN/RST Scan
$IPTABLES -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
# FIN/ACK Scan
$IPTABLES -A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -j DROP
# ACK/URG Scan
$IPTABLES -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP
# FIN/URG/PSH Scan
$IPTABLES -A INPUT -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -j DROP
# Stealth XMAS Scan
$IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
# XMAS-PSH Scan
$IPTABLES -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
# End TCP connection
$IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN -j DROP
# Ports scans
$IPTABLES -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
Allow services and network protocols
DHCP
DHCP client:
IPTABLES=`which iptables`
# DHCP client >> Broadcast IP request
$IPTABLES -A OUTPUT -p udp -d 255.255.255.255 --sport 68 --dport 67 -j ACCEPT
$IPTABLES -A INPUT -p udp -s 255.255.255.255 --sport 67 --dport 68 -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 67 -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 68 -j ACCEPT
DNS
This will allow your computer to perform DNS requests:
IPTABLES=`which iptables`
IP6TABLES=`which ip6tables`
$IPTABLES -A OUTPUT -p udp --dport 53 -m limit --limit 100/s -j ACCEPT
$IPTABLES -A OUTPUT -p udp --sport 53 -m limit --limit 100/s -j ACCEPT
$IPTABLES -A INPUT -p udp --sport 53 -m limit --limit 100/s -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 53 -m limit --limit 100/s -j ACCEPT
$IP6TABLES -A OUTPUT -p udp --dport 53 -m limit --limit 100/s -j ACCEPT
$IP6TABLES -A OUTPUT -p udp --sport 53 -m limit --limit 100/s -j ACCEPT
$IP6TABLES -A INPUT -p udp --dport 53 -m limit --limit 100/s -j ACCEPT
$IP6TABLES -A INPUT -p udp --sport 53 -m limit --limit 100/s -j ACCEPT
LAN communication
To allow communication in the local network, without any restrictions:
IPTABLES=`which iptables`
IP_LAN_V4="172.16.50.0/24"
IP_LAN_V6="2001:DB8:1::1"
# Allow LAN communication
if [ ! -z "$IP_LAN_V4" ]
then
echo -e " ... Allow LAN communication - IP v4"
$IPTABLES -A INPUT -s $IP_LAN_V4 -d $IP_LAN_V4 -j ACCEPT
$IPTABLES -A OUTPUT -s $IP_LAN_V4 -d $IP_LAN_V4 -j ACCEPT
# Allow forwarding within the LAN
$IPTABLES -A FORWARD -s $IP_LAN_V4 -j ACCEPT
fi
if [ ! -z "$IP_LAN_V6" ]
then
echo -e " ... Allow LAN communication - IP v6"
$IP6TABLES -A INPUT -s $IP_LAN_V6 -d $IP_LAN_V6 -j ACCEPT
$IP6TABLES -A OUTPUT -s $IP_LAN_V6 -d $IP_LAN_V6 -j ACCEPT
# Allow forwarding within the LAN
$IP6TABLES -A FORWARD -s $IP_LAN_V6 -j ACCEPT
fi
Note: thanks to the ! -z operator if the variable is not set or "" then the rule will be skipped.
NTP (time syncronization) client
IPTABLES=`which iptables`
# NTP client
echo -e " ... Allow NTP time sync"
$IPTABLES -A OUTPUT -p udp --dport 123 -j ACCEPT
$IPTABLES -A INPUT -p udp --sport 123 -j ACCEPT
$IP6TABLES -A OUTPUT -p udp --dport 123 -j ACCEPT
$IP6TABLES -A INPUT -p udp --sport 123 -j ACCEPT
IPTABLES=`which iptables`
# SAMBA share
# Access filtering is done in /etc/samba/smb.conf
$IPTABLES -A INPUT -p udp --dport 137 -j ACCEPT # NetBios Name Service
$IPTABLES -A INPUT -p udp --dport 138 -j ACCEPT # NetBios Data Exchange
$IPTABLES -A INPUT -p tcp --dport 139 -j ACCEPT # NetBios Session + Samba
$IPTABLES -A INPUT -p tcp --dport 445 -j ACCEPT # CIFS - Partage Win2K and more
$IPTABLES -A INPUT -p tcp --dport 548 -j ACCEPT # Apple File Sharing Protocol
FTP client
IPTABLES=`which iptables`
# FTP client - base rules
$IPTABLES -A INPUT -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
# Active FTP
$IPTABLES -A INPUT -p tcp --sport 20 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT
# Passive FTP
$IPTABLES -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT