Iptables

From Frack - Hackerspace Friesland
Jump to navigationJump to search
Icoon waarschuwing geel.svg Het gebruik van iptables is veroudert waarmee ook onderstaand artikel niet meer relevant is. De standaard opvolger is nftables geworden.
Onderwerp: iptables
Firewall.png
Deskundigen
Afbeelding Anoniem.png Fludizz
Fludizz Rol: deelnemer Deskundig met: GL-Inet, Glasvezel lassen, Iptables, Linux, Netwerken, Nftables, OpenVPN, Python, RaspberryPi, Software Beginnend met: ENC28J60 Werkt aan: Geen projecten :(
Onderdeel van Netwerken, Linux, Beveiliging

De meeste linux distributies hebben standaard de netfilter modules in de kernel zitten. Middels iptables kan het netfilter geconfigureerd worden.

Een firewall is een mechanisme om toegang tot een computer of een heel netwerk te beperken op basis van regels. In een firewall kan je configureren wat wel doorgegeven mag worden en wat niet. Dit kan bijvoorbeeld het blokkeren van poorten zijn, het toestaan van bepaalde IP-adressen of bepaalde protocollen filteren. De meeste Linux-distributies hebben standaard al de netfilter-modules aan boord, dit is als firewall te gebruiken. Voor het configureren hiervan wordt iptables gebruikt.

Een (gekoppeld) netwerk kan niet zonder firewalls. Waar internet vroeger nog heel erg open en onbeveiligd was kan je tegenwoordig niet meer zonder firewalls, wegens kwaadwillende mensen en tegen malafide programma's die ongevraagd toegang willen tot de machines. Op deze pagina word een basic iptables firewall uitgelegd met NAT en IPv6 routing erin, deze configuratie gaat er vanuit dat alle machines op het interne netwerk "trusted" zijn en filtert alleen verkeer dat vanaf de WAN naar het LAN gerouteerd word.

Setup

De setup is relatief simpel, de server is voorzien van twee netwerkkaarten en een drietal virtuele interfaces:

  • eth1 (WAN, untrusted)
  • eth0 (LAN, trusted)
  • tun0 (VPN, virtuele adapter)
  • 6in4 (IPv6 in IPv4 tunnel, virtuele adapter, untrusted)
  • lo (Loopback adapter, virtuele adapter, altijd aanwezig)

Kernel modules

Er zijn veel kernel modules die onder netfilter vallen, voor een basis NAT firewall zijn de volgende nodig:

  • Voor IPv4:
    • ip_tables - Basis iptables/netfilter support.
    • ipt_MASQUERADE - NAT Masquerading support, dit is nodig voor NAT translations.
    • iptable_filter - Het packet filter
    • iptable_nat - NAT support.
    • nf_conntrack_ipv4 - IPv4 connection tracking, nodig voor NAT routing
    • nf_nat - De netfilter NAT module.
  • Voor IPv6:
    • ip6_tables - IPv6 iptables support
    • ip6table_filter - IPv6 packet filter
    • nf_conntrack_ipv6 - IPv6 connection tracking
  • Optionele modules:
    • nf_nat_ftp - Hiermee word de firewall FTP aware, helpt met FTP sessies achter NAT
    • nf_nat_sip - Deze zorgt voor SIP awareness, helpt met de RTP/SIP sessies achter NAT
    • Check /lib/modules/${Kernelversie}/kernel/net/ipv4/netfilter voor alle IPv4 modules.

iptables

iptables is een binary (executable) waarmee de netfilter modules geconfigureerd worden. Voor ipv6 heet de binary ip6tables maar deze heeft dezelfde syntax als de ipv4 versie, er zitten echter wel verschillen in bepaalde sub-opties, dit heeft te maken met de technische verschillen tussen IPv4 en IPv6 en worden hier niet verder behandeld.

Port en IP adres syntax

Voor het schrijven van iptables rules is het handig om te weten hoe poort(en) en ipadressen/subnets erin gezet moeten worden. Het is van belang om deze basis syntax te kennen omdat het script verderop in de configuratie deze syntax gebruikt.

Het invoeren van een poort die open moet, is relatief simpel. Je tikt gewoon het poortnummer in en je bent klaar. Echter, om performance redenen wil je niet voor elke poort een aparte iptables rule hebben. Dit kan simpel opgelost worden door de poorten in een komma-gescheiden lijst op te schrijven. Deze lijst heeft echter een limitatie van hoeveel poorten erin kunnen staan. Om toch genoeg poorten erin te kunnen zetten kan er een poortbereik in gezet worden. Dit word gedaan door startpoort en de eindpoort gescheiden met een dubbelepunt (:) te plaatsen. Bijvoorbeeld, je wilt poort 20, 21, 22, 80 en 8080 t/m 8090 open hebben. Dit schrijf je dan als volgt: 20:22,80,8080:8090

Voor filteren/routing kan het handig zijn om bepaalde IP-adressen wel of juist niet toe te staan. Dit kan gedaan worden door simpelweg een enkel IP-adres in te tikken voor een enkele host. Wil je echter een subnet toestaan of weigeren, dan moet er met netmasks gewerkt worden, dit kan op twee manieren ingevoerd worden: Met het subnet mask of met de subnet bits. Bijvoorbeeld, je wilt je eigen lokale subnet toevoegen en dat is 192.168.1.0. Dit kan dan op de volgende manieren: Subnet mask: 192.168.1.0/255.255.255.0; of Subnet bits: 192.168.1.0/24

Een voorbeeld regel met bovenstaande opties zou dan worden:

iptables -A INPUT -s 192.168.1.0/24 -p tcp -m multiport --dport 20:22,80,8080:8090 -j ACCEPT

-A INPUT staat voor "Append to the INPUT table". De INPUT table is alles wat naar de lokale machine toe gaat. -s 192.168.1.0/24 geeft aan dat deze regel toegepast moet worden op al het vekeer vanaf deze iprange. -p tcp -m multiport --dport 20:22,80,8080:8090 geeft aan dat het protocol TCP is, er meerdere poorten gaan volgen gevolgt door alle poorten die het betreft. -j ACCEPT geeft uiteindelijk aan wat er moet gebeuren als het inkomende verkeer aan bovengenoemde eisen voldoet. In dit geval dus accepteren en niet filteren.

Script

Onderstaande script kan gebruikt worden met de eerder genoemde #Setup. Zoals je ziet worden alleen de vertrouwde interfaces opgegeven en de interface waarop NAT routing toegepast moet worden. Alle interfaces die NIET in de lijst van vertrouwde interfaces staat moet door alle iptables rules heen. Vandaar dat de 6in4 interface niet zichtbaar terug komt in dit script.

Het script is op te delen in 2 stukken. Het eerste deel is de configuratie, met het invullen van een paar variabelen is aan te geven wat de firewall moet doen. Het twee deel van het script genereert de regels voor iptables (zoals het voorbeeld hier boven) op basis van de opgegeven configuratie.

iptables.sh

#!/bin/sh
#
# iptables & ip6tables script that applies all rules. This avoids using
# iptables-save and iptables-restore and enforces that a fixed set of rules is
# applied, discarding any (temporary) changes if it is executed.
#
# REQUIRED configuration needs valid interfaces, this needs to be filled in! If
# you do NOT specify this, you will most likely lock yourself out.
#
# Optional configuration options can be left blank if it is not used.
#
# For all configuration options, the standard iptables notation applies to ports
# and ip ranges. See iptables manual for details.
#
 
##
## Configuration
##
 
# Interfaces (REQUIRED)
# Add the list of trusted interfaces to TRUSTIF, seperated by a space.
# WARNING: Never remove lo from the trusted list!!!
# Add the single interface on which NAT routing should be applied to NATIF
TRUSTIF="lo eth0 tun0"
NATIF="eth1"
 
# Service ports (Optional)
# Add the ports that should be exposed to the internet here.
# Example: TCP port 20 through 25, port 80 and port 443 should be open:
#TCPPORTS="20:,80,443"
TCPPORTS="20:22,25,80,8080:8090"
UDPPORTS="53,1194"
 
# VoIP Security (Optional)
# If you have an ISP which provides VoIP, a certain set of ports is required to
# be open. You might want to use this to block unauthorized access from VoIP
# boxes which are NOT from your ISP.
# Note, the VoIP section is currently IPv4 only. Edit the script below if your
# VoIP provider uses IPv6.
VOIPRANGE="12.34.56.78/255.255.255.224"
VOIPPORTS="5060,10000:10100"
 
# IPv6 Forwarding (Optional)
# This section specifies which ports are allowed to be routed to which host. 
# This can be a single host, or a range of hosts. Connect the port to the 
# corresponding ip(range) with the '=' sign and seperate multiple entries with a
# space ("PORT1=HOST1 PORT2=HOSTS2").
# Example: Allow TCP port 100 to host 2001::1 and port range 110-120 to 2001::2
#TCPFORWARD="100=2001::1 110:120=2001::2"
TCPFORWARD=
UDPFORWARD=
 
# IPv4 NAT Port mapping (Optional)
# Here you can specify which ports should be mapped to which NAT-host. Connect
# the port(s) to the ip-address using the '=' sign and seperate multiple entries
# with a space ("PORT1=HOST1 PORT2=HOST2").
# Example: forward TCP port 900 to 192.168.1.100 and 10000-11000 to 192.168.1.2
#NATTCP="9000=192.168.1.100 10000:11000=192.168.1.2"
NATTCP=
NATUDP=
 
# IP blocklists (Optional)
# To avoid having to constantly edit this file, you can specify a two blocklists
# here, an IPv4 and an IPv6 blocklist. The blocklist should contain an IP range
# or a single ip per line.
# Use the full path to the file.
IP4BLOCK=
IP6BLOCK=
 
# Iptables binaries
IP4T=/sbin/iptables
IP6T=/sbin/ip6tables
 
##
## Generally no need to edit below this line. The script starts here and will
## generate the actual iptables commands.
##
echo -n "Loading iptables & ip6tables rules ... "
# Iptables cleanup and reset to it's default state
 
$IP4T -F
$IP4T -t nat -F
$IP4T -X
$IP4T -t nat -X
$IP4T -P INPUT ACCEPT
$IP4T -P OUTPUT ACCEPT
$IP4T -P FORWARD ACCEPT
$IP6T -F
$IP6T -X
$IP6T -P INPUT ACCEPT
$IP6T -P OUTPUT ACCEPT
$IP6T -P FORWARD ACCEPT
 
# Configure some basic settings you'd want to have.
$IP4T -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IP4T -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IP4T -P INPUT DROP
$IP6T -A INPUT -p ipv6-icmp -j ACCEPT
$IP6T -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IP6T -P INPUT DROP
 
# Now open up the firewall for your trusted interfaces.
for I in $TRUSTIF
do
  $IP4T -A INPUT -i $I -j ACCEPT
  $IP6T -A INPUT -i $I -j ACCEPT
  $IP6T -A FORWARD -i $I -j ACCEPT
  $IP4T -A FORWARD -i $I -j ACCEPT
done
 
# Open the TCP and UDP ports if they have been configured:
if [ $TCPPORTS ]
then 
  $IP4T -A INPUT -p tcp -m multiport --dport $TCPPORTS -j ACCEPT
  $IP6T -A INPUT -p tcp -m multiport --dport $TCPPORTS -j ACCEPT
fi
if [ $UDPPORTS ]
then
  $IP4T -A INPUT -p udp -m multiport --dport $UDPPORTS -j ACCEPT
  $IP6T -A INPUT -p udp -m multiport --dport $UDPPORTS -j ACCEPT
fi
 
# Test if we need to open VOIP stuff. If yes, apply rules.
if [ $VOIPRANGE ] && [ $VOIPPORTS ]
then
  $IP4T -A INPUT -s $VOIPRANGE -p udp -m multiport --dport $VOIPPORTS -j ACCEPT
  #$IP6T -A INPUT -s $VOIPRANGE -p udp -m multiport --dport $VOIPPORTS -j ACCEPT
fi
 
# If dhclient fails to get an IP from the WAN interface, uncomment below lines.
#$IP4T -A INPUT -p udp --sport 68 --dport 67 -j ACCEPT
#$IP4T -A INPUT -p tcp --sport 68 --dport 67 -j ACCEPT
 
# Configure routing options IPv6 (Enable routing in /etc/sysctl.conf first!)
$IP6T -A FORWARD -p ipv6-icmp -j ACCEPT
$IP6T -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
$IP6T -A FORWARD -p tcp ! --syn -j ACCEPT
$IP6T -P FORWARD DROP
 
# Now enable forwarding to the configured ports/hosts (if configured)
if [ $TCPFORWARD ]
then
  for I in $TCPFORWARD
  do
    DPORT=`echo $I | cut -d = -f 1`
    DADDR=`echo $I | cut -d = -f 2`
    $IP6T -A FORWARD -d $DADDR -p tcp -m multiport --dport $DPORT -j ACCEPT
  done
fi
if [ $UDPFORWARD ]
then
  for I in $UDPFORWARD
  do
    DPORT=`echo $I | cut -d = -f 1`
    DADDR=`echo $I | cut -d = -f 2`
    $IP6T -A FORWARD -d $DADDR -p udp -m multiport --dport $DPORT -j ACCEPT
  done
fi
 
# Configure IPv4 NAT routing
$IP4T -t nat -A POSTROUTING -o $NATIF -j MASQUERADE
 
# Now to open up the NAT Port mappings if configured
if [ $NATTCP ]
then
  for I in $NATTCP
  do
    DPORT=`echo $I | cut -d = -f 1`
    DADDR=`echo $I | cut -d = -f 2`
    $IP4T -A PREROUTING -t nat -p tcp -m multiport --dport $DPORT -j DNAT --to $DADDR
  done
fi
if [ $NATUDP ]
then
  for I in $NATUDP
  do
    DPORT=`echo $I | cut -d = -f 1`
    DADDR=`echo $I | cut -d = -f 2`
    $IP4T -A PREROUTING -t nat -p udp -m multiport --dport $DPORT -j DNAT --to $DADDR
  done
fi
 
# Load the IP blocklist if configured
if [ $IP4BLOCK ]
then 
  while read LINE
  do
    $IP4T -A INPUT -s $LINE -j REJECT --reject-with icmp-host-prohibited
  done < $IP4BLOCK
fi
if [ $IP6BLOCK ]
then
  while read LINE
  do
    $IP6T -A INPUT -s $LINE -j REJECT --reject-with icmp6-adm-prohibited
  done < $IP6BLOCK
fi
 
echo "Done"