Difference between revisions of "Firewall principle"

Line 663: Line 663:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
 +
 +
==Allow all reserved ports==
 +
 +
All the ports between 0:1024 belongs to well-known network protocol and usage.
 +
So, instead of acting as paranoid, you can open the ports between O:1024.
 +
 +
 +
You can consult the full list over here: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
 +
 +
 +
<syntaxhighlight lang="bash">
 +
IPTABLES=`which iptables`
 +
 +
echo -e " ... Allow all standards ports between 0:1024"
 +
$IPTABLES -A OUTPUT -p tcp --dport 0:1024 -j ACCEPT
 +
$IPTABLES -A OUTPUT -p udp --dport 0:1024 -j ACCEPT
 +
 +
</syntaxhighlight>
 +
  
  

Revision as of 08:55, 8 August 2014

The firewall (FW) is a key component of your server's security.

You can search Internet to get all the related theory. My aim is not to explain that over here but just to give you HOW to setup a Firewall with IpTables.

The following codes and examples are based iptables and ip6tables.



Principle

This is how a firewall works:

FW principle


This is how you can use a firewall at home | work:

FW usage


The firewall performs:

  • Basic security check
  • Security policy's enforcement
  • IP, port filtering
  • Port forwarding and NAT



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!


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

$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

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
	

# Only localhost on Loopback interface + no forward
$IPTABLES -A INPUT ! -i lo -s 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 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)"
$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

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


Samba file-share

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


VPN

Adjust the following to your own port, network ID and protocol:

IPTABLES=`which iptables`

INT_ETH=eth0
IP_LAN_ETH=`/sbin/ifconfig $INT_ETH | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`

INT_VPN=tun0
VPN_PORT="8080"
VPN_PROTOCOL="udp"
LAN_ADDRESS_VPN="172.16.60.0/24"

echo -e " "		
echo -e "------------------------"
echo -e " VPN configuration"
echo -e "------------------------"

echo " " 
echo -e "# VPN interface  : $INT_VPN"
echo -e "# VPN IP @       : $LAN_ADDRESS_VPN"
echo -e "# VPN port       : $VPN_PORT"
echo -e "# VPN protocol   : $VPN_PROTOCOL"
echo -e "-------------------------------------- "

# Allow devices communication $ETH0 <--> tun0
$IPTABLES -t nat -A POSTROUTING -s $LAN_ADDRESS_VPN -o $INT_ETH -j MASQUERADE
$IPTABLES -A FORWARD -s $LAN_ADDRESS_VPN -j ACCEPT

echo -e " ... Allow VPN connections"
$IPTABLES -A INPUT -p $VPN_PROTOCOL --dport $VPN_PORT -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport $VPN_PORT -j ACCEPT

echo -e " ... Allow everything to go through VPN - all INPUT,OUTPUT,FORWARD"
$IPTABLES -A INPUT -i $INT_VPN -m state ! --state INVALID -j ACCEPT
$IPTABLES -A OUTPUT -o $INT_VPN -m state ! --state INVALID -j ACCEPT
$IPTABLES -A FORWARD -o $INT_VPN -m state ! --state INVALID -j ACCEPT

echo -e " ... Allow VPN network communication (required for client <> client comm.)"
$IPTABLES -A INPUT -s $LAN_ADDRESS_VPN -d $LAN_ADDRESS_VPN -j ACCEPT
$IPTABLES -A OUTPUT -s $LAN_ADDRESS_VPN -d $LAN_ADDRESS_VPN -j ACCEPT


OUTPUT filters

Mandatory output

This is the VERY MINIMUM you need to run a computer:


IPTABLES=`which iptables`

echo -e " "		
echo -e "------------------------"
echo -e " OUTGOING port filters"
echo -e "------------------------"
	
##############
# Main ports
##############
	
echo -e " ... Mandatory ports "
echo -e "       SSH, Telnet, HTTP(S), HTTP alt (8080), NTP, RPC"

# Remote Control
$IPTABLES -A OUTPUT -p tcp --dport 22 -j ACCEPT     # SSH (default port)
$IPTABLES -A OUTPUT -p tcp --dport 23 -j ACCEPT     # Telnet
# Web
$IPTABLES -A OUTPUT -p tcp --dport 80 -j ACCEPT     # HTTP
$IPTABLES -A OUTPUT -p tcp --dport 443 -j ACCEPT    # HTTPS
$IPTABLES -A OUTPUT -p tcp --dport 8080 -j ACCEPT   # TomCat (Java Web Server)
# Core Linux services
$IPTABLES -A OUTPUT -p udp --dport 123 -j ACCEPT    # Time NTP UDP
$IPTABLES -A OUTPUT -p tcp --dport 135 -j ACCEPT    # Remote Procedure Call

	
##############
# Remote control
##############
	
echo -e " ... Remote control"
$IPTABLES -A OUTPUT -p tcp --dport 3389 -j ACCEPT   # Windows Remote Desktop (terminal Server)
$IPTABLES -A OUTPUT -p tcp --dport 5900 -j ACCEPT   # VNC and Apple Remote Desktop


##############
# Communication
##############
	
echo -e " ... Communication"
	
# Email
$IPTABLES -A OUTPUT -p tcp --dport 25 -j ACCEPT     # SMTP
$IPTABLES -A OUTPUT -p tcp --dport 110 -j ACCEPT    # POP3
$IPTABLES -A OUTPUT -p tcp --dport 143 -j ACCEPT    # IMAP
$IPTABLES -A OUTPUT -p tcp --dport 993 -j ACCEPT    # IMAP over SSL
$IPTABLES -A OUTPUT -p tcp --dport 995 -j ACCEPT    # POP over SSL
$IPTABLES -A OUTPUT -p tcp --dport 587 -j ACCEPT    # SMTP SSL (gmail)
$IPTABLES -A OUTPUT -p tcp --dport 465 -j ACCEPT    # SMTP SSL (gmail)
	
##############
# I.T
##############
	
echo -e " ... I.T ports"
echo -e "        LDAP, Printing, WhoIs, UPnP, Webmin ..."	
# Domain
$IPTABLES -A OUTPUT -p tcp --dport 113 -j ACCEPT    # Kerberos
$IPTABLES -A OUTPUT -p tcp --dport 389 -j ACCEPT    # LDAP 
$IPTABLES -A OUTPUT -p tcp --dport 636 -j ACCEPT    # LDAP over SSL 

# Network Services
$IPTABLES -A OUTPUT -p tcp --dport 43 -j ACCEPT     # WhoIs
$IPTABLES -A OUTPUT -p tcp --dport 427 -j ACCEPT    # Service Location Protocol
$IPTABLES -A OUTPUT -p udp --dport 1900 -j ACCEPT   # UPnP - Peripheriques reseau

##############
# File share
##############

echo -e " ... File share"
$IPTABLES -A OUTPUT -p udp --dport 137 -j ACCEPT    # NetBios Name Service
$IPTABLES -A OUTPUT -p udp --dport 138 -j ACCEPT    # NetBios Data Exchange
$IPTABLES -A OUTPUT -p tcp --dport 139 -j ACCEPT    # NetBios Session + Samba
$IPTABLES -A OUTPUT -p tcp --dport 445 -j ACCEPT    # CIFS - Partage Win2K and more


Allow all reserved ports

All the ports between 0:1024 belongs to well-known network protocol and usage. So, instead of acting as paranoid, you can open the ports between O:1024.


You can consult the full list over here: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers


IPTABLES=`which iptables`

echo -e " ... Allow all standards ports between 0:1024"
$IPTABLES -A OUTPUT -p tcp --dport 0:1024 -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 0:1024 -j ACCEPT


Other output

You can increase the previous list, at least for:

  • Communications tools: Skype, Google hangout, ...
  • Videos and streaming: YouTube, NetFlix, ...
  • Development tools: SVN, JMX, JMS, AMQP, ...
  • Custom services


IPTABLES=`which iptables`


!! TO BE COMPLETED !!!


INPUT filters: servers

SSH

# SSH - max 3 connection request per minute
$IPTABLES -A INPUT -p tcp -m limit 3/min --limit-burst 3 --dport 22 -j ACCEPT


DHCP

This is how you enable a DHCP server with TFTP (netBoot) :

IPTABLES=`which iptables`

# Allow LAN communication
# ... Required for NFS and the NetBoot ...
$IPTABLES -A INPUT -s $LAN_ADDRESS -d $LAN_ADDRESS -m state ! --state INVALID -j ACCEPT
$IPTABLES -A OUTPUT -s $LAN_ADDRESS -d $LAN_ADDRESS -m state ! --state INVALID -j ACCEPT
 
########################
# INPUT filters
########################
 
##### DHCP client ######
# Broadcast IP request 
$IPTABLES -A OUTPUT -p udp -d 255.255.255.255 --sport 68 --dport 67 -j ACCEPT
# Send / reply to IPs requests
$IPTABLES -A INPUT -p udp -s 255.255.255.255 --sport 67 --dport 68 -j ACCEPT
 
###### DHCP server ######
# Received client's requests [udp + tcp]
$IPTABLES -A INPUT -p udp --sport 68 --dport 67 -j ACCEPT
$IPTABLES -A INPUT -p tcp --sport 68 --dport 67 -j ACCEPT

# NetBoot - TFTP server
$IPTABLES -A INPUT -p udp -s $LAN_ADDRESS --dport 69 -j ACCEPT
 
 
########################
# OUTPUT filters
########################
# DHCP [udp + tcp]
$IPTABLES -A OUTPUT -p udp --dport 67 -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 67 -j ACCEPT
$IPTABLES -A OUTPUT -p udp --dport 68 -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 68 -j ACCEPT
 
# TFTP NetBoot 
$IPTABLES -A OUTPUT -p udp --dport 69 -j ACCEPT


Note the difference between the broadcast request that every computer should allow and the plain OUTPUT allow on ports 67,68 for the DHCP server !!


LDAP

$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 389 -j ACCEPT # LDAP
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 636 -j ACCEPT # LDAPS


NFS

It's really tricky to adjust the firewall for NFS as the port is dynamic. But option is to allow LAN traffic and use NFS over LAN only.




Advanced feature

Port forwarding

Principle

The aim is to reach a server located behind the actual server we are working on.


Basic proxy

FW port forwarding - without NAT

In this case the target port number is the same as the source port.

This is a RISK because we exposed to Internet the schema of our Network.


Advanced proxy

FW port forwarding - with NAT


Here, the source and target port numbers are different. That's better but you need to maintain a 'IN / OUT ports matching table' as IT admin.



How to

To do a port forwarding you have to:

  • Allow some source IP / hosts to use forwarding
  • Create some forward target
  • Open the incoming port [input + output]
  • Register the target server and allow POST-ROUTING operations on it
  • Route the incoming port to the target server + port number


Proxy how-to


Requirements:

  • Enable port forwading
  • The current server must be able to reach the target {server,port}


IpTables script

You have to declare the following only ONCE in all your FW script:


Enable module

#### Requirement: enable port forwarding in general
echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding


### Allow forward from IP@... 
$IPTABLES -A FORWARD -s 91.121.17.114 -j ACCEPT		# work
$IPTABLES -A FORWARD -s 5.39.81.23 -j ACCEPT	        # family VPN
$IPTABLES -A FORWARD -s 192.168.18.0 -j ACCEPT	        # home


### Open incoming ports [=from ports]...
$IPTABLES -A INPUT -p tcp --dport 25 -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 80 -j ACCEPT
 

### Declare forward targets [=to]...
$IPTABLES -A POSTROUTING -d 192.168.18.2 -t nat -j MASQUERADE            # Email server
$IPTABLES -A POSTROUTING -d 192.168.18.5 -t nat -j MASQUERADE            # JEE server



### Redirect FROM (IP:port) TO (server:port)
$IPTABLES -A PREROUTING -t nat -p tcp --dport 25 -j DNAT --to 192.168.18.2:25
$IPTABLES -A PREROUTING -t nat -p tcp --dport 80 -j DNAT --to 192.168.18.5:8080



Port forwarding VS proxy

Usually it's better to proxy than forward.

So if you can use the Apache2 proxy to redirect "http://mysite/myApp" to your sub-server Apache2 "/myApp" - DO IT !


My advice:

Only use port forwarding when there are no other choice.



Source address filtering

You can restricted the access of a particular service to a limited set of source networks, IP @.


Example:

# Only allow company's offices to access our Tomcat
$IPTABLES -A INPUT -p tcp --dport 8088 -s 192.168.1.0/24 -j ACCEPT           # Sweden LAN
$IPTABLES -A INPUT -p tcp --dport 8088 -s 90.83.80.64/27 -j ACCEPT           # FR remote
$IPTABLES -A INPUT -p tcp --dport 8088 -s 90.83.80.123/27 -j ACCEPT          # FR remote
$IPTABLES -A INPUT -p tcp --dport 8088 -s 77.68.140.115/24 -j ACCEPT         # DK remote
$IPTABLES -A INPUT -p tcp --dport 8088 -s 0.0.0.0/0 -j DROP             # DROP all the rest !


Don't forget to drop all the rest at the end  !!


Advanced version: for loop

ALLOWED_REMOTE_IPS=(
195.101.122.64/27            # French office
193.12.118.194               # Sweden codriver.vehco.com
193.12.118.196               # Sweden code.vehco.com
91.121.17.114                # French RTD preprod [VPN]
)

# enable access to services (HTTP)
for ipList in ${ALLOWED_REMOTE_IPS[@]}
do
$IPTABLES -A INPUT -p tcp --dport 80 -s $ipList -j ACCEPT
done
# disable for everyone else
$IPTABLES -A INPUT -p tcp -m tcp -s 0.0.0.0/0 --dport 80 -j DROP


Scripts

To use the firewall you need to:

  • Have a firewall start script
  • Have a firewall stop script
  • Have a firewall launcher script
  • Register the firewall to the boot sequence


Firewall start script

My firewall start script: http://www.daxiongmao.eu/wiki_upload_files/firewall/firewall-start.sh


NetBoot client Firewall start script

My NetBoot firewall start script (LAN only): http://www.daxiongmao.eu/wiki_upload_files/firewall/firewall-nfs-client.sh


Firewall stop script

My firewall stop script: http://www.daxiongmao.eu/wiki_upload_files/firewall/firewall-stop.sh


Firewall launcher script

My firewall stop script: http://www.daxiongmao.eu/wiki_upload_files/firewall/firewall.sh


Installation

  • Download and adjust all the previous scripts.
  • Put all the scripts in /etc/firewall/ and set the execution rights
mkdir /etc/firewall
cp firewall* /etc/firewall/
chmod -R 755 /etc/firewall
  • Create some symlink for the firewall
ln -s /etc/firewall/firewall.sh /usr/bin/firewall
ln -s /etc/firewall/firewall.sh /etc/init.d/firewall
  • Register firewall script to boot sequence
cd /etc/init.d
update-rc.d firewall defaults


Reboot and check that the firewall is up with:

firewall status



Note

All this knowledge is the result of years of experiments and trials. Don't hesitate to search over Internet for more advanced || simpler rules.



References

  • My education at Telecom Bretagne [1] && Chalmers [2]
  • Working years and some co-workers help:
    • Julien Rialland