#!/bin/sh

# Copyright 2003-2020 Kjell Enblom, Gnu General Public License version 2 (GPL) (http://www.gnu.org/)

# Firewall rules
# Brandväggsregler för en brandvägg med två nätverksinterface
# där maskering (NAT) görs av all trafik från det interna nätverket ut mot internet


############################# Gör dina inställningar här ########################################

# Sätt IPTABLES till sökvägen för kommandot iptables vilket kan vara
# t.ex. /sbin/iptables eller /usr/sbin/iptables
# Sätt IPTABLESSAVE till sökvägen för kommandot iptables-save
# t.ex. /sbin/iptables-save
IPTABLES='/sbin/iptables'
IPTABLESSAVE='/sbin/iptables-save'

# EXTERNAL ska sättas till namnet på det interface som sitter på utsidan
# INTERNAL ska sättas till namnet på det interface som sitter på insidan (mot det interna nätverket)
EXTERNAL='eth1'
INTERNAL='eth0'

# Sätt DYNAMICIP till ja om du för det externa interfacet får en
# adress dynamiskt via dhcp från din nätleverantör.
DYNAMICIP='nej'

# Tjänster som körs på brandväggen
# Ange protokoll,port
# För ICMP-trafik som ska släppas in till brandväggen skriv icmp,icmptyp
# Listan ska vara mellanslagseparerad. ICMP 3 Destination Unreachable och ICMP 11 Time Exceeded är bra att släppa in.
SERVICES='tcp,22 tcp,25 tcp,80 icmp,0 icmp,3 icmp,8 icmp,11'

# Om ssh (tcp port 22) är aktiverad ovan kan det vara bra att begränsa antalet uppkopplingar per tidsenhet för den
# för att minska risken att någon utifrån knäcker lösenord.
# Antal uppkopplingar per tidsenhet:
SSHHITCOUNT="10"
# Tidsenhet i sekunder t.ex. 10 minuter = 600 eller 1 timme = 3600.
SSHSECONDS="600"
# Ovan ger max ca 10 uppkopplingar under 10 minuter.


# Acess till tjänster på brandväggsdatorn som endast ska vara nåbar från det interna/lokala nätverket
# Ange protokoll,port
# För ICMP-trafik som ska släppas in till brandväggen skriv icmp,icmptyp
# Listan ska vara mellanslagseparerad
LOCALSERVICES='tcp,22 tcp,10000'

# NTP tidsserver/tidsservrar på Internet
# Skriv en mellanslagseparerad lista med IP-adresserna till de tidsservrar som ska användas
# Kommentera bort den om du ska synkronisera brandväggens klocka mot en tidsserver
# NTPSERVERS='1.2.3.4   1.2.3.5  4.3.2.1'

# DNS, nameservrar som ska vara tillgängliga för brandväggen och för de på det interna nätverket
# Skriv IP-adresserna som en mellanslagseparerad lista
DNSSERVERS='1.2.3.4 10.47.255.22'

# Webinloggningsserver
# Om webbinloggning krävs för att nå ut på nätet kan webbserverns adress skrivas in här
WEBLOGON='1.2.3.4'

# Port forward
# Trafik som kommer till en viss port på brandväggens utsida och som
# ska skickas vidare till en dator på det interna nätverket
# Listan ska vara mellanslagseparerad
#
# Ange på formen: protokoll,port-i-brandväggen,IP-på-lokala-nätverket,port-på-dator
# Exempel: all tcp-trafik som kommer till brandväggens utsida port 2022 ska till
# 192.168.22.17 port 22
# PORTFORWARD='tcp,2022,192.168.22.17,22'
PORTFORWARD='tcp,2022,192.168.22.17,22  tcp,21,192.168.22.17,21'

# Logga och kasta all övrig trafik?
# Om ja kommer all trafik som inte släpps fram att loggas och kastas
# Om nej kommer all övrig trafik att kastas utan att loggas.
LOGDROP='ja'

################################# Slut på inställningar ###########################################


# Sätt upp standardregler
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT ACCEPT


# Rensa bort gamla brandväggsregler
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F

# Rensa bort gamla kedjor
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X


# Om maskeringen är kompilerad som modul

modprobe iptable_nat
modprobe ip_conntrack

# För att ESTABLISHED, RELATED ska fungera bra för FTP-trafik ladda
# nedanstående moduler. Om de ligger fast i kärnan kommentera bort raderna.
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp 

# Raderna med modprobe ovan kan även stoppas in i någon annan lämplig fil
# som körs vid boot. Exempel /etc/rc.local eller /etc/rc.sysinit. 

# Slå på routing
echo "1" > /proc/sys/net/ipv4/ip_forward

# Firewall rules
# Min egna IP-adress på  (yttre interface)
MEexternal=`/sbin/ifconfig $EXTERNAL |sed -n '/inet/s/^[ ]*inet addr:\([0-9.]*\).*/\1/p'`

# Min egna IP-adress på $INTERNAL (inre interface)
MEinternal=`/sbin/ifconfig $INTERNAL |sed -n '/inet/s/^[ ]*inet addr:\([0-9.]*\).*/\1/p'`
MEinternalmask=`/sbin/ifconfig $INTERNAL |sed -n '/inet/s/^.*Mask:\([0-9.]*\).*/\1/p'`

# Räkna ut nätadress för det interna nätverket med hjälp av IP och mask
# Den här kräver programmet NetCalc.py som ska ligga i en katalog som din PATH pekar ut
INTERNALNETWORK="`NetCalc.py --network $MEinternal/$MEinternalmask`"

# Min broadcastadress på eth0
MYBROADCASTeth0=`/sbin/ifconfig eth0 |sed -n '/inet/s/^.*Bcast:\([0-9.]*\).*/\1/p'`
# Min broadcastadress på eth1
MYBROADCASTeth1=`/sbin/ifconfig eth1 |sed -n '/inet/s/^.*Bcast:\([0-9.]*\).*/\1/p'`

# Skapa kedjan logdrop som loggar och kastar trafiken
$IPTABLES -N logdrop
$IPTABLES -A logdrop -j LOG
$IPTABLES -A logdrop -j DROP

# Logga och kasta nya TCP-paket som inte är SYN-paket
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "NEW NOT SYN "
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

$IPTABLES -A FORWARD -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "NEW NOT SYN "
$IPTABLES -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP


# Spärra windows-share-trafik så att den inte slipper ut från det interna nätverket
$IPTABLES -A FORWARD --in-interface $INTERNAL -p tcp  --destination-port 137:139 -j DROP
$IPTABLES -A FORWARD --in-interface $INTERNAL -p udp  --destination-port 137:139 -j DROP

# Spärra inkommande windowsshare-trafik, NFS-trafik och X-window trafik
$IPTABLES -A FORWARD --in-interface $EXTERNAL -p tcp  --destination-port 137:139 -j DROP
$IPTABLES -A FORWARD --in-interface $EXTERNAL -p udp  --destination-port 137:139 -j DROP
$IPTABLES -A INPUT --in-interface $EXTERNAL -p tcp  --destination-port 137:139 -j DROP
$IPTABLES -A INPUT --in-interface $EXTERNAL -p udp  --destination-port 137:139 -j DROP

$IPTABLES -A FORWARD --in-interface $EXTERNAL -p tcp  --destination-port 2049 -j DROP
$IPTABLES -A FORWARD --in-interface $EXTERNAL -p udp  --destination-port 2049 -j DROP
$IPTABLES -A INPUT --in-interface $EXTERNAL -p tcp  --destination-port 2049 -j DROP
$IPTABLES -A INPUT --in-interface $EXTERNAL -p udp  --destination-port 2049 -j DROP

$IPTABLES -A FORWARD --in-interface $EXTERNAL -p tcp  --destination-port 6000:6010 -j DROP
$IPTABLES -A INPUT --in-interface $EXTERNAL -p tcp  --destination-port 6000:6010 -j DROP



# Se till att DNS-trafik kommer fram
if [ -n "$DNSSERVERS" ]
then
   for nameserver in $DNSSERVERS
   do
     $IPTABLES -A INPUT --in-interface $EXTERNAL -p tcp --source $nameserver --sport 53 --destination-port 1024:65535 -j ACCEPT
     $IPTABLES -A INPUT --in-interface $EXTERNAL -p udp --source $nameserver --sport 53 --destination-port 1024:65535 -j ACCEPT
     $IPTABLES -A FORWARD --in-interface $EXTERNAL -p tcp --source $nameserver --sport 53 --destination-port 1024:65535 -j ACCEPT
     $IPTABLES -A FORWARD --in-interface $EXTERNAL -p udp --source $nameserver --sport 53 --destination-port 1024:65535 -j ACCEPT
   done
fi


# Se till att den eller de webinloggningsservar som eventuellt behövs för
# att komma ut på nätet är nåbara
if [ -n "$WEBLOGON" ]
then
   for WEBLOGONSERVER in $WEBLOGON
   do
       $IPTABLES -A INPUT --in-interface $EXTERNAL -p tcp --source $WEBLOGONSERVER  --source-port 80 --destination-port 1024:65535 -j ACCEPT
       $IPTABLES -A FORWARD --in-interface $EXTERNAL -p tcp --source $WEBLOGONSERVER --source-port 80 --destination-port 1024:65535 -j ACCEPT
   done
fi



# Spärra nät som är till för lokalt bruk 10.0.0.0/8,  172.16.0.0/12,  192.168.0.0/24
# Spärra trafik som kommer utifrån och som har en lokal adress som avsändar- eller mottagar-adress
if ! `echo $MEexternal | grep '^10\.' > /dev/null`
then
   $IPTABLES -A FORWARD --in-interface $EXTERNAL --source 10.0.0.0/8 -j DROP
   $IPTABLES -A INPUT --in-interface $EXTERNAL --source 10.0.0.0/8 -j DROP
fi

if ! `echo $MEexternal | grep '^172\.' > /dev/null`
then
   $IPTABLES -A FORWARD --in-interface $EXTERNAL --source 172.16.0.0/12 -j DROP
   $IPTABLES -A INPUT --in-interface $EXTERNAL --source 172.16.0.0/12 -j DROP
fi

if ! `echo $MEexternal | grep '^192\.' > /dev/null`
then
   $IPTABLES -A INPUT --in-interface $EXTERNAL --source 192.168.0.0/16 -j DROP
   $IPTABLES -A FORWARD --in-interface $EXTERNAL --source 192.168.0.0/16 -j DROP
fi

######################## Trafik till själva brandväggsdatorn ####################

# Logga och spärra ut netbus
$IPTABLES -A INPUT -p tcp --destination-port 12345 -j logdrop
$IPTABLES -A INPUT -p udp --destination-port 12345 -j logdrop

# Tillåt brandväggen att prata med sig själv
$IPTABLES -A INPUT --in-interface lo --source 127.0.0.0/8 -j ACCEPT
$IPTABLES -A INPUT --in-interface lo --source $MEexternal -d $MEexternal -j ACCEPT
$IPTABLES -A INPUT --in-interface lo --source $MEinternal -d $MEinternal -j ACCEPT

# Spärra ut avsändaradress 127.0.0.0/8 från omvärlden (som inte kommer
# från loopback)
$IPTABLES -A INPUT --in-interface ! lo --source 127.0.0.0/8 -j DROP

# Spärra trafik som kommer till broadcastadressen på yttre nätet
if [ $EXTERNAL = 'eth0' ]
then
   $IPTABLES -A INPUT -d $MYBROADCASTeth0/32 -j DROP
elif [ $EXTERNAL = 'eth1' ]
then
   $IPTABLES -A INPUT -d $MYBROADCASTeth1/32 -j DROP
fi


# Släpp in trafik till egna servertjänster
# Släpp in trafik till servertjänster på låga portar
# Tjänst protokoll klientportar serverport

for service in $SERVICES
do
   PROTOCOL=`echo $service | cut -d"," -f1`
   PORT=`echo $service | cut -d"," -f2`
   if [ $PROTOCOL = "icmp" ]
   then
       # Släpp in ICMP-trafik
       # För ICMP är PORT inte port utan ICMP-typ
       $IPTABLES -A INPUT -p icmp --icmp-type $PORT -j ACCEPT
   else
       $IPTABLES -A INPUT -m state --state NEW -p $PROTOCOL  --destination-port $PORT -j ACCEPT
       $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -p $PROTOCOL --destination-port $PORT -j ACCEPT
   fi
done


# Access till tjänster från det lokala nätverket
for service in $LOCALSERVICES
do
   PROTOCOL=`echo $service | cut -d"," -f1`
   PORT=`echo $service | cut -d"," -f2`
   if [ $PROTOCOL = "icmp" ]
   then
       # Släpp in ICMP-trafik
       # För ICMP är PORT inte port utan ICMP-typ
       $IPTABLES -A INPUT --in-interface $INTERNAL --source "$INTERNALNETWORK" -p icmp --icmp-type $PORT -j ACCEPT
   else
       # Tjänster som kör TCP, UDP
       $IPTABLES -A INPUT --in-interface $INTERNAL --source "$INTERNALNETWORK" -m state --state NEW -p $PROTOCOL   --destination-port $PORT -j ACCEPT
       $IPTABLES -A INPUT --in-interface $INTERNAL --source "$INTERNALNETWORK" -m state --state ESTABLISHED,RELATED -p $PROTOCOL --destination-port $PORT -j ACCEPT
   fi
done



if [ -n "$NTPSERVERS" ]
then
   for NTPSERVER in $NTPSERVERS
   do
      # Släpp in trafik från ntp-servern $NTPSERVER port 123 från utsidan
      $IPTABLES -A INPUT -p udp --source $NTPSERVER --sport 123 --destination-port 123 -j ACCEPT
   done
fi


# Släpp fram svarstrafik
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT


# Sätt begränsningar på antalet ssh-uppkopplingar
for service in $SERVICES
do
   PROTOCOL=`echo $service | cut -d"," -f1`
   PORT=`echo $service | cut -d"," -f2`
   if [ $PROTOCOL = "tcp" ] && [ $PORT == "22" ]
   then
       # Begränsa antalet ssh-uppkopplingar IN till t.ex. 10 st på 600 sekunder
       # Kommentera bort dessa två rader om du inte vill ha denna begränsning
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds $SSHSECONDS --hitcount $SSHHITCOUNT -j DROP
       break
   fi
done


###################### Trafik ut/in mellan Internet och interna nätet ###########################


# FORWARDREGLER
# Spärra trafik som kommer till broadcastadressen
$IPTABLES -A FORWARD --in-interface eth1 -d $MYBROADCASTeth0/32 -j logdrop
$IPTABLES -A FORWARD --in-interface eth0 -d $MYBROADCASTeth1/32 -j logdrop

# Om trafiken ut från det interna nätverket har en annan avsändaradress än vad som används
# på det interna nätverket ska den kastas.
if [ -n "$INTERNALNETWORK" ]
then
   $IPTABLES -A FORWARD --in-interface $INTERNAL ! --source "$INTERNALNETWORK" -j logdrop
fi

# Släpp ut trafik från interna nätet, och släpp in svarstrafik
$IPTABLES -A FORWARD --in-interface $INTERNAL -j ACCEPT
$IPTABLES -A FORWARD --in-interface $EXTERNAL -m state --state ESTABLISHED,RELATED -j ACCEPT

# Lägg på maskering på utgående trafik som ska ut till Internet så att
# det ser ut som att det är brandväggens utsida som surfar
if [ "$DYNAMICIP" != 'ja' ]
then
   $IPTABLES -t nat -A POSTROUTING -o $EXTERNAL -j SNAT --to $MEexternal
else
   # Släpp in dhcp-trafik
   $IPTABLES -A INPUT -i $EXTERNAL -p tcp --source-port 67 --destination-port 68 -j ACCEPT
   #
   # Om adressen på yttre interfacet fås dynamiskt t.ex. dhcp (DYNAMIC=ja)
   # använd MASQUERADE
      $IPTABLES -t nat -A POSTROUTING -o $EXTERNAL -j MASQUERADE
   # Notera att MASQUERADE gör av med lite mer CPU-kraft än SNAT men den behövs när dhcp används.
   #
   # Vid användning av dhcp aktivera ip_dynaddr
      echo "1" > /proc/sys/net/ipv4/ip_dynaddr
fi

# Port forwarding
# Skicka vidare trafik till vissa portar på brandväggens utsida till datorer
# på det inre nätet
if [ -n "$PORTFORWARD" ]
then
  for portfwd in $PORTFORWARD
  do
     PROTOCOL=`echo $portfwd | cut -d"," -f1`
     FWPORT=`echo $portfwd | cut -d"," -f2`
     IP=`echo $portfwd | cut -d"," -f3`
     PORT=`echo $portfwd | cut -d"," -f4`
     $IPTABLES -t nat -A PREROUTING --in-interface $EXTERNAL -p $PROTOCOL --dport $FWPORT -j DNAT --to $IP:$PORT
     $IPTABLES -A FORWARD -p $PROTOCOL --destination-port $PORT -j ACCEPT
  done
fi


if [ "$LOGDROP" = 'ja' ]
then
   # Logga och spärra resten
   $IPTABLES -A INPUT -j logdrop
   $IPTABLES -A FORWARD -j logdrop
fi


# Om det är en RedHat spara iptables-reglerna i filen /etc/sysconfig/iptables
if [ -f "/etc/redhat-release" ]
then
   iptables-save > /etc/sysconfig/iptables
fi
