Firewall basics

Revision as of 13:07, 16 August 2015 by WikiFreak (talk | contribs)



Set IP preference

If you enable IPv6 then that will be the default.


IPv6 Recommended solution : IPv6 is now available in a lot of places. It's time to use it!


IPv4 only If you don't want to use IPv6 you can force IPv4 mode. This is not recommended any-more! IPv6 is becoming bigger and bigger, you need to switch.


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!


Attacks types

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"
# Reject invalid packets
$IPTABLES -A INPUT -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IPTABLES -A INPUT -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -j DROP
$IPTABLES -A INPUT -p icmp -m state --state INVALID -m comment --comment "Reject invalid ICMP" -j DROP
$IPTABLES -A OUTPUT -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IPTABLES -A OUTPUT -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -j DROP
$IPTABLES -A OUTPUT -p icmp -m state --state INVALID -m comment --comment "Reject invalid ICMP" -j DROP
$IPTABLES -A FORWARD -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IPTABLES -A FORWARD -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -j DROP
    
$IP6TABLES -A INPUT -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IP6TABLES -A INPUT -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -j DROP
$IP6TABLES -A INPUT -p icmpv6 -m state --state INVALID -m comment --comment "Reject invalid ICMP6" -j DROP
$IP6TABLES -A OUTPUT -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IP6TABLES -A OUTPUT -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -j DROP
$IP6TABLES -A OUTPUT -p icmpv6 -m state --state INVALID -m comment --comment "Reject invalid ICMP6" -j DROP
$IP6TABLES -A FORWARD -p tcp -m state --state INVALID -m comment --comment "Reject invalid TCP" -j DROP
$IP6TABLES -A FORWARD -p udp -m state --state INVALID -m comment --comment "Reject invalid UDP" -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
$IPTABLES -A INPUT ! -i lo -s 127.0.0.0/24 -m comment --comment "Reject none loopback on 'lo'" -j DROP  
$IPTABLES -A OUTPUT ! -o lo -d 127.0.0.0/24 -m comment --comment "Reject none loopback on 'lo'" -j DROP
$IPTABLES -A FORWARD -s 127.0.0.0/24 -m comment --comment "Reject none loopback on 'lo'" -j DROP

$IP6TABLES -A INPUT ! -i lo -s ::1/128 -m comment --comment "Reject none loopback on 'lo'" -j DROP
$IP6TABLES -A OUTPUT ! -o lo -d ::1/128 -m comment --comment "Reject none loopback on 'lo'" -j DROP
$IP6TABLES -A FORWARD -s ::1/128 -m comment --comment "Reject none loopback on 'lo'" -j DROP
    

## IPv6 security
# No IPv4 -> IPv6 tunneling
$IP6TABLES -A INPUT -s 2002::/16 -m comment --comment "Reject 6to4 tunnels" -j DROP
$IP6TABLES -A FORWARD -s 2002::/16 -m comment --comment "Reject 6to4 tunnels" -j DROP
$IP6TABLES -A INPUT -s 2001:0::/32 -m comment --comment "Reject Teredo tunnels" -j DROP
$IP6TABLES -A FORWARD -s 2001:0::/32 -m comment --comment "Reject Teredo tunnels" -j DROP
    
# Block IPv6 protocol in IPv4 frames
$IPTABLES -A INPUT -p 41 -m comment --comment "Block IPv6 protocol in IPv4 frames" -j DROP
$IPTABLES -A OUTPUT -p 41 -m comment --comment "Block IPv6 protocol in IPv4 frames" -j DROP
$IPTABLES -A FORWARD -p 41 -m comment --comment "Block IPv6 protocol in IPv4 frames" -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"

    # ICMP packets should not be fragmented
    $IPTABLES -A INPUT --fragment -p icmp -m comment --comment "no ICMP fragments" -j DROP    
    # Limit ICMP Flood
    $IPTABLES -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -m comment --comment "ICMP flood protection" -j ACCEPT
    #$IPTABLES -A OUTPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT
    $IPTABLES -A OUTPUT -p icmp --icmp-type 0 -m comment --comment "echo reply" -j ACCEPT
    $IPTABLES -A OUTPUT -p icmp --icmp-type 3 -m comment --comment "destination unreachable" -j ACCEPT
    $IPTABLES -A OUTPUT -p icmp --icmp-type 8 -m comment --comment "echo request" -j ACCEPT    
    # Avoid common attacks ... but blocks ping
    #$IPTABLES -A OUTPUT -p icmp --icmp-type 3 -j DROP

    
    # Feedback for problems
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 1 -m comment --comment "destination unreachable" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 2 -m comment --comment "packet too big" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 3 -m comment --comment "time exceeded" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 4 -m comment --comment "parameter problem" -j ACCEPT
    
    # Router and neighbor discovery 
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 133 -m comment --comment "router sollicitation" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 134 -m comment --comment "router advertisement" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 135 -m comment --comment "neighbor sollicitation" -j ACCEPT
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 136 -m comment --comment "neighbor advertisement" -j ACCEPT
    
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 133 -m comment --comment "router sollicitation" -j ACCEPT
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 134 -m comment --comment "router advertisement" -j ACCEPT
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 135 -m comment --comment "neighbor sollicitation" -j ACCEPT
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 136 -m comment --comment "neighbor advertisement" -j ACCEPT
    
    # Ping requests
    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 128 -m comment --comment "echo request" -j ACCEPT
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 128 -m comment --comment "echo request" -j ACCEPT

    $IP6TABLES -A INPUT -p icmpv6 --icmpv6-type 129 -m comment --comment "echo reply" -j ACCEPT
    $IP6TABLES -A OUTPUT -p icmpv6 --icmpv6-type 129 -m comment --comment "echo reply" -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 -m comment --comment "new TCP connection check" -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 -m comment --comment "avoid TCP SYN flood" -j ACCEPT
    # Avoid fragment packets
    $IPTABLES -A INPUT -f -m comment --comment "no fragments" -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 common scans and TCP flags attacks"
    # XMAS-NULL
    $IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -m comment --comment "attack XMAS-NULL" -j DROP
    # XMAS-TREE
    $IPTABLES -A INPUT -p tcp --tcp-flags ALL ALL -m comment --comment "attack XMAS-tree" -j DROP
    # Stealth XMAS Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -m comment --comment "attack XMAS stealth" -j DROP

    # SYN/RST Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -m comment --comment "scan SYN/RST" -j DROP
    # SYN/FIN Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -m comment --comment "scan 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 -m comment --comment "scan SYN/ACK" -j DROP
    # FIN/RST Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -m comment --comment "scan FIN/RST" -j DROP
    # FIN/ACK Scan
    $IPTABLES -A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -m comment --comment "scan FIN/ACK" -j DROP
    # ACK/URG Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags ACK,URG URG -m comment --comment "scan ACK/URG" -j DROP
    # FIN/URG/PSH Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -m comment --comment "scan FIN/URG/PSH" -j DROP
    # XMAS-PSH Scan
    $IPTABLES -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -m comment --comment "scan XMAS/PSH" -j DROP
    # End TCP connection
    $IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN -m comment --comment "end TCP connection flag" -j DROP
    # Ports scans
    $IPTABLES -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "common scan FIN/SYN/RST/ACK SYN" -j DROP
    $IPTABLES -A INPUT -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -m comment --comment "common scan FIN/SYN/RST/ACK/PSH/URG NONE" -j DROP


Allow services and network protocols

DHCP

DHCP client:

IPTABLES=`which iptables`


# DHCP client >> Broadcast IP request 
$IPTABLES -A INPUT -p udp --sport 67:68 --dport 67:68 -m comment --comment "DHCP" -j ACCEPT 
$IPTABLES -A OUTPUT -p udp --sport 67:68 --dport 67:68 -m comment --comment "DHCP" -j ACCEPT


DNS

This will allow your computer to perform DNS requests:

IPTABLES=`which iptables`
IP6TABLES=`which ip6tables`

# DNS
$IPTABLES -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -m comment --comment "DNS UDP" -j ACCEPT
$IPTABLES -A INPUT -p tcp --sport 53 -m state --state ESTABLISHED -m comment --comment "DNS TCP" -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 53 -m state --state NEW,ESTABLISHED -m comment --comment "DNS UDP" -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 53 -m state --state NEW,ESTABLISHED -m comment --comment "DNS TCP" -j ACCEPT

$IP6TABLES -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -m comment --comment "DNS UDP" -j ACCEPT
$IP6TABLES -A INPUT -p tcp --sport 53 -m state --state ESTABLISHED -m comment --comment "DNS TCP" -j ACCEPT
$IP6TABLES -A OUTPUT -p udp --dport 53 -m state --state NEW,ESTABLISHED -m comment --comment "DNS UDP" -j ACCEPT
$IP6TABLES -A OUTPUT -p tcp --dport 53 -m state --state NEW,ESTABLISHED -m comment --comment "DNS TCP" -j ACCEPT


!! IMPORTANT !!!

If you ever loose Internet access after that you need to check your /etc/resolv.conf configuration and make sure you're using a valid DNS server.




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 INPUT -p udp --sport 123 -m state --state ESTABLISHED -m comment --comment "NTP (UDP)" -j ACCEPT
$IPTABLES -A INPUT -p tcp --sport 123 -m state --state ESTABLISHED -m comment --comment "NTP (TCP)" -j ACCEPT

$IPTABLES -A OUTPUT -p udp --dport 123 -m state --state NEW,ESTABLISHED -m comment --comment "NTP (UDP)" -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 123 -m state --state NEW,ESTABLISHED -m comment --comment "NTP (TCP)" -j ACCEPT


Samba file-share

IPTABLES=`which iptables`

# SAMBA share
# Access filtering is done in /etc/samba/smb.conf
$IPTABLES -A INPUT -p tcp --dport 135 -m comment --comment "DCE endpoint resolution" -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 137 -m comment --comment "NetBIOS Name Service" -j ACCEPT
$IPTABLES -A INPUT -p udp --dport 138 -m comment --comment "NetBIOS Datagram" -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 139 -m comment --comment "NetBIOS Session" -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 445 -m comment --comment "SMB over TCP" -j ACCEPT

$IPTABLES -A OUTPUT -p tcp --sport 135 -m state --state ESTABLISHED -m comment --comment "DCE endpoint resolution" -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 137 -m comment --comment "NetBios Name Service" -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 138 -m comment --comment "NetBios Data Exchange" -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 139 -m comment --comment "NetBios Session + Samba" -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 445 -m comment --comment "CIFS - Partage Win2K and more" -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 548 -m comment --comment "Apple file sharing" -j ACCEPT


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