Difference between revisions of "Firewall principle"

(Next steps)
 
(28 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
[[Category:Linux]]
 
The firewall (FW) is a key component of your server's security.
 
The firewall (FW) is a key component of your server's security.
 
=Principle=
 
 
This is how a firewall works:
 
 
[[File:FW_principle.png|none|FW principle]]
 
 
  
 
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.
 
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'''.
 
The following codes and examples are based '''iptables''' and '''ip6tables'''.
Line 15: Line 8:
  
  
 +
=Principle=
  
 +
This is how a firewall works:
  
 
+
[[File:FW_principle.png|none|FW principle]]
=Set IP preference=
 
 
 
If you enable IPv6 then that will be the default.
 
 
 
 
 
 
 
You can override that and '''set IPv4 as the default protocol''':
 
 
 
<syntaxhighlight lang="bash">
 
vim /etc/gai.conf
 
</syntaxhighlight>
 
 
 
 
 
About line 54, un-comment the following line:
 
 
 
<syntaxhighlight lang="bash">
 
#
 
#    For sites which prefer IPv4 connections change the last line to
 
#
 
precedence ::ffff:0:0/96  100
 
</syntaxhighlight>
 
 
 
 
 
  
  
  
 +
This is how you can use a firewall at home | work:
  
=Enable modules=
+
[[File:FW_usage.png|none|FW usage]]
  
First things first! Before writing any rule you have to enable the required modules in your current O.S.
 
  
  
- Note -
+
The firewall performs:
 +
* Basic security check
 +
* Security policy's enforcement
 +
* IP, port filtering
 +
* Port forwarding and NAT
  
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.
 
 
 
 
<syntaxhighlight lang="bash">
 
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
 
 
</syntaxhighlight>
 
 
 
=Default policy=
 
 
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!
 
 
 
<syntaxhighlight lang="bash">
 
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 ACCEPT
 
 
$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!
 
$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
 
 
 
# 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
 
 
 
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
 
 
# Allow localhost communication
 
echo -e " ... Allow localhost"
 
$IPTABLES -A INPUT -i lo -s 127.0.0.0/24 -d 127.0.0.0/24 -j ACCEPT
 
$IPTABLES -A OUTPUT -o lo -s 127.0.0.0/24 -d 127.0.0.0/24 -j ACCEPT
 
 
$IP6TABLES -A INPUT -i lo -j ACCEPT
 
$IP6TABLES -A OUTPUT -o lo  -j ACCEPT
 
 
</syntaxhighlight>
 
 
 
 
 
 
=Protocol(s) enforcement=
 
 
 
<syntaxhighlight lang="bash">
 
IPTABLES=`which iptables`
 
IP6TABLES=`which ip6tables`
 
 
 
echo -e " "
 
echo -e "------------------------"
 
echo -e " Protocols enforcement"
 
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
 
 
 
 
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
 
 
</syntaxhighlight>
 
 
 
 
 
 
 
 
=Allow services and network protocols=
 
 
==DHCP==
 
 
DHCP client:
 
 
<syntaxhighlight lang="bash">
 
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
 
</syntaxhighlight>
 
 
 
==DNS==
 
 
This will allow your computer to perform DNS requests:
 
 
<syntaxhighlight lang="bash">
 
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
 
</syntaxhighlight>
 
 
 
==LAN communication==
 
 
To allow communication in the local network, without any restrictions:
 
 
<syntaxhighlight lang="bash">
 
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
 
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
 
fi
 
 
</syntaxhighlight>
 
 
Thanks to the '''! -z''' operator if the variable is not set or "" then the rule will be skipped.
 
 
 
 
 
==FTP client==
 
 
 
<syntaxhighlight lang="bash">
 
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
 
</syntaxhighlight>
 
 
 
==VPN==
 
 
Adjust the following to your own port, network ID and protocol:
 
 
<syntaxhighlight lang="bash">
 
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
 
</syntaxhighlight>
 
 
 
 
 
=Servers=
 
 
 
==SSH==
 
 
<syntaxhighlight lang="bash">
 
# SSH - max 3 connection request per minute
 
$IPTABLES -A INPUT -p tcp -m limit 3/min --limit-burst 3 --dport 22 -j ACCEPT
 
</syntaxhighlight>
 
 
 
==DHCP==
 
 
 
This is how you enable a DHCP server with TFTP (netBoot) :
 
 
<syntaxhighlight lang="bash">
 
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
 
</syntaxhighlight>
 
 
 
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 !!
 
 
 
 
 
 
=Advanced feature=
 
 
 
==Port forwarding==
 
 
 
===Principle===
 
 
The aim is to reach a server located behind the actual server we are working on.
 
 
 
[[File:FW_port_forwarding.png|none|FW port forwarding - without NAT]]
 
 
 
[[File:FW_port_forwarding_with_NAT.png|none|FW port forwarding - with NAT]]
 
 
 
To do a port forwarding you have to:
 
* Allow forwarding for the 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
 
 
 
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'''
 
 
<syntaxhighlight lang="bash">
 
#### Requirement: enable port forwarding in general
 
echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
 
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
 
</syntaxhighlight>
 
 
 
 
'''Allow forwarding for [all,some] requests'''
 
 
<syntaxhighlight lang="bash">
 
#### Requirement: allow forwarding
 
# Allow all forwarding
 
$IPTABLES -A FORWARD -J ACCEPT
 
# Allow forward for some particular network or IP @
 
$IPTABLES -A FORWARD -s 172.16.50.0/24 -J ACCEPT
 
$IPTABLES -A FORWARD -s 5.39.81.23 -J ACCEPT
 
</syntaxhighlight>
 
 
 
 
'''Perform port forwarding'''
 
 
 
You have to do the following for each computer / server you plan to serve:
 
 
<syntaxhighlight lang="bash">
 
####
 
# 1. Open target port
 
$IPTABLES -A INPUT -p tcp --dport 3389 -j ACCEPT
 
$IPTABLES -A OUTPUT -p tcp --dport 3389 -j ACCEPT
 
 
# 2. Enable Port forwarding to Windows server 192.168.100.10
 
$IPTABLES -A POSTROUTING -d 192.168.100.10 -t nat -j MASQUERADE
 
 
# 3. Redirect services to target server
 
$IPTABLES -A PREROUTING -t nat -p tcp --dport 3389 -j DNAT --to 192.168.100.10:3389
 
$IPTABLES -A PREROUTING -t nat -p tcp --dport 81 -j DNAT --to 192.168.100.10:80
 
</syntaxhighlight>
 
 
 
===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:
 
 
<syntaxhighlight lang="bash">
 
 
# 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 !
 
 
</syntaxhighlight>
 
 
 
Don't forget to drop all the rest at the end  !!
 
 
 
 
 
=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
 
 
 
==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
 
 
<syntaxhighlight lang="bash">
 
mkdir /etc/firewall
 
cp firewall* /etc/firewall/
 
chmod -R 755 /etc/firewall
 
</syntaxhighlight>
 
 
* Create some symlink for the firewall
 
 
<syntaxhighlight lang="bash">
 
ln -s /etc/firewall/firewall.sh /usr/bin/firewall
 
ln -s /etc/firewall/firewall.sh /etc/init.d/firewall
 
</syntaxhighlight>
 
 
* Register firewall script to boot sequence
 
 
<syntaxhighlight lang="bash">
 
cd /etc/init.d
 
update-rc.d firewall defaults
 
</syntaxhighlight>
 
 
 
Reboot and check that the firewall is up with:
 
 
<syntaxhighlight lang="bash">
 
firewall status
 
</syntaxhighlight>
 
  
  
 +
=Next steps=
  
 +
See [[Template:Menu_content_security#Firewall]]
  
 
=Note=
 
=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.
 
All this knowledge is the result of years of experiments and trials. Don't hesitate to search over Internet for more advanced || simpler rules.
 
  
  

Latest revision as of 09:34, 23 May 2015

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


Next steps

See Template:Menu_content_security#Firewall

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