#!/bin/sh # # This will be universal firewalling script in near future # Can be started by init or by hand. # # Developed by Lubomir Host 'rajo' # Copyright (c) 2003 Platon SDG, http://platon.sk/ # Licensed under terms of GNU General Public License. # All rights reserved. # # $Platon: $ # # # Config: # DESC="firewall" PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DEFAULT_POLICY="DROP" # which modules to load MODULES="ipt_LOG ipt_REJECT ip_conntrack_ftp" LOG_LIMIT="-m limit --limit 12/h --limit-burst 10" # Paths: IPTABLES="/sbin/iptables" #IPTABLES=":" # for testing only - does nothing IFCONFIG="/sbin/ifconfig" DEPMOD="/sbin/depmod" MODPROBE="/sbin/modprobe" RMMOD="/sbin/rmmod" AWK="/usr/bin/awk" # interface connected to cruel world (internet jungle) INET_IFACE="eth0" INET_IP="IP_$INET_IFACE" # loopback interface LO_IFACE="lo" LO_IP="IP_$LO_IFACE" # Which ports will be allowed on INPUT (TCP connections) # 21 - ftp, 22 - ssh, 25 - smtp, 53 - DNS server TCP, 80 - www, 110 - POP3 # 143 - IMAP, 443 - HTTPS, 873 - rsync server # 123 137 138 139 631 - samba ACCEPT_INPUT_TCP="123 137 138 139 631 22 80" # Which ports will be allowed on INPUT (UDP connections) # 53 - DNS server, 517 - talk, 518 - ntalk ACCEPT_INPUT_UDP="123 137 138 139 631" # allow some ICMP packets - needed for ping etc. ACCEPT_ICMP_PACKETS="echo-reply destination-unreachable echo-request time-exceeded" # load necessary modules from $MODULES variable load_modules() { # {{{ echo "# Loading modules" for mod in $MODULES; do echo " $MODPROBE $mod" $MODPROBE $mod done } # }}} # unload necessary modules from $MODULES variable unload_modules() { # {{{ # reverse modules echo "# Removing modules" R_MODULES=`echo "$MODULES" | tr ' ' '\012' | tac | tr '\012' ' '` for mod in $R_MODULES; do echo " $RMMOD $mod" $RMMOD $mod done } # }}} # print status of found interfaces print_iface_status() { # {{{ # Print interfaces: echo "# iface | IP addr | broadcast | netmask | HW addr" for iface in $interfaces; do IP="IP_$iface"; Bcast="Bcast_$iface"; Mask="Mask_$iface"; HWaddr="HWaddr_$iface"; echo "$iface | ${!IP} | ${!Bcast} | ${!Mask} | ${!HWaddr}" done } # }}} # set default policy (variable $DEFAULT_POLICY) set_default_policy() { # {{{ # Set default policy for chain in INPUT OUTPUT FORWARD; do $IPTABLES -P $chain $DEFAULT_POLICY done } # }}} antispoof_on() { # {{{ for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "1" > ${interface} done } # }}} # clear status of iptable chains remove_chains() { # {{{ $IPTABLES -F # clear all chains $IPTABLES -X # remove all chains } # }}} # all packets on loopback are accted set_loopback() { # {{{ $IPTABLES -A INPUT -j ACCEPT -i $LO_IFACE $IPTABLES -A OUTPUT -j ACCEPT -o $LO_IFACE } # }}} # DROP packages from nmap(1) nmap_scan_filter() { # {{{ echo -en "Turning on nmap scan filter " for chain in INPUT FORWARD; do echo -en "." # Nie je nastaveny ziaden bit $IPTABLES -A $chain -p tcp --tcp-flags ALL NONE $LOG_LIMIT -j LOG --log-prefix "nmap scan $chain ALL NONE: " $IPTABLES -A $chain -p tcp --tcp-flags ALL NONE -j DROP # dva odporujuuce si flagy su nastavene: for flags in SYN,FIN SYN,RST FIN,RST ; do echo -en "." $IPTABLES -A $chain -p tcp --tcp-flags $flags $flags $LOG_LIMIT -j LOG --log-prefix "nmap scan $chain $flags: " $IPTABLES -A $chain -p tcp --tcp-flags $flags $flags -j DROP done # je nastavene len $flags bez predpokladaneho ACK for flags in FIN PSH URG ; do echo -en "." $IPTABLES -A $chain -p tcp --tcp-flags ACK,$flags $flags $LOG_LIMIT -j LOG --log-prefix "nmap scan $chain ACK,$flags: " $IPTABLES -A $chain -p tcp --tcp-flags ACK,$flags $flags -j DROP done done echo "done." } # }}} # drop packets in state INVALID invalid_packet_filter() { # {{{ echo -en "Turning on INVALID packet filter " for chain in INPUT OUTPUT FORWARD; do echo -en "." $IPTABLES -A $chain -m state --state INVALID $LOG_LIMIT -j LOG --log-prefix "INVALID $chain: " $IPTABLES -A $chain -m state --state INVALID -j DROP done echo "done." } # }}} syn_flood() { # {{{ $IPTABLES -N syn-flood $IPTABLES -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN $IPTABLES -A syn-flood -j DROP $IPTABLES -A INPUT -i $INET_IFACE -p tcp --syn -j syn-flood # Paket je označený jako NEW, ale nemá nastavený SYN flag - pryč s ním $IPTABLES -A INPUT -i $INET_IFACE -p tcp ! --syn -m state --state NEW -j DROP } # }}} anti_spoof_filter() { # {{{ # http://www.iana.com/assignments/ipv4-address-space $IPTABLES -N spoof echo "Turning on antispoof filter for interface $INET_IFACE " # Ochrana proti Spoogingu zo spetnej slucky $IPTABLES -A spoof -i $INET_IFACE -s 127.0.0.0/8 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:127.0.0.0/8 src" $IPTABLES -A spoof -i $INET_IFACE -s 127.0.0.0/8 -j DROP $IPTABLES -A spoof -i $INET_IFACE -d 127.0.0.0/8 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:127.0.0.0/8 dest" $IPTABLES -A spoof -i $INET_IFACE -d 127.0.0.0/8 -j DROP # Ochrana proti Spoofingu Internetu z adries urcenych pre lokalne siete $IPTABLES -A spoof -i $INET_IFACE -s 192.168.0.0/16 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:192.168.0.0/16 src" $IPTABLES -A spoof -i $INET_IFACE -s 192.168.0.0/16 -j DROP # RFC1918 $IPTABLES -A spoof -i $INET_IFACE -s 172.16.0.0/12 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:172.16.0.0/12 src" $IPTABLES -A spoof -i $INET_IFACE -s 172.16.0.0/12 -j DROP # RFC1918 $IPTABLES -A spoof -i $INET_IFACE -s 10.0.0.0/8 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:10.0.0.0/8 src" $IPTABLES -A spoof -i $INET_IFACE -s 10.0.0.0/8 -j DROP # RFC1918 len pre sietovy interface do Internetu, kedze 10.0.0.0 je adresa LAN $IPTABLES -A spoof -i $INET_IFACE -s 96.0.0.0/4 $LOG_LIMIT -j LOG --log-prefix "Reserved IP:96.0.0.0/4 src" $IPTABLES -A spoof -i $INET_IFACE -s 96.0.0.0/4 -j DROP # IANA echo "... done." } # }}} mangle_prerouting() { # {{{ echo "Optimizing PREROUTING TOS" # TOS flagy slouzi k optimalizaci datovych cest. Pro ssh, ftp a telnet # pozadujeme minimalni zpozdeni. Pro ftp-data zase maximalni propostnost $IPTABLES -t mangle -A PREROUTING -p tcp --sport ssh -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A PREROUTING -p tcp --dport ssh -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A PREROUTING -p tcp --sport ftp -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A PREROUTING -p tcp --dport ftp -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A PREROUTING -p tcp --dport telnet -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A PREROUTING -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput } # }}} mangle_output() { # {{{ echo "Optimizing OUTPUT TOS" # TOS flagy slouzi k optimalizaci datovych cest. Pro ssh, ftp a telnet # pozadujeme minimalni zpozdeni. Pro ftp-data zase maximalni propostnost $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ssh -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport ssh -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ftp -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport ftp -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport telnet -j TOS --set-tos Minimize-Delay $IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput } # }}} # accept TCP packets for ports in $ACCEPT_INPUT_TCP # accept UDP packets for ports in $ACCEPT_INPUT_UDP allow_input() { # {{{ if [ ! -z "$ACCEPT_INPUT_TCP" ]; then echo -en "Accepting INPUT TCP connections on ports: " for port in $ACCEPT_INPUT_TCP; do echo -en " $port" $IPTABLES -A INPUT -i $INET_IFACE -d ${!INET_IP} -p TCP --dport $port -j ACCEPT done echo "." fi if [ ! -z "$ACCEPT_INPUT_UDP" ]; then echo -en "Accepting INPUT UDP connections on ports: " for port in $ACCEPT_INPUT_UDP; do echo -en " $port" #$IPTABLES -A INPUT -i $INET_IFACE -d ${!INET_IP} -p UDP --dport $port -j ACCEPT $IPTABLES -A INPUT -i $INET_IFACE -p UDP --dport $port -j ACCEPT done echo "." fi } # }}} # ACCEPT all packets from our IP address allow_output() { # {{{ # Povolíme odchozí pakety, které mají naše IP adresy echo "Accepting OUTPUT packets from ${!LO_IP} ${!INET_IP}" $IPTABLES -A OUTPUT -s ${!LO_IP} -j ACCEPT $IPTABLES -A OUTPUT -s ${!INET_IP} -j ACCEPT } # }}} allow_icmp() { # {{{ echo -en "Accepting ICMP packets:" # Službu AUTH není dobré filtrovat pomocí DROP, protože to může # vést k prodlevám při navazování některých spojení. Proto jej # sice zamítneme, ale vygenerujeme korektní ICMP chybovou zprávu $IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 113 -j REJECT --reject-with tcp-reset #AUTH server # accept only allowed ICMP packets for type in $ACCEPT_ICMP_PACKETS; do echo -en " $type" $IPTABLES -A INPUT -i $INET_IFACE -p ICMP --icmp-type $type -j ACCEPT done echo " done." } # }}} log_input_drop() { # {{{ prefix="input drop: " echo "Input drop is logged with prefix '$prefix'" $IPTABLES -A INPUT $LOG_LIMIT -j LOG --log-prefix "$prefix" } # }}} log_output_drop() { # {{{ prefix="output drop: " echo "Output drop is logged with prefix '$prefix'" # Ostatní pakety logujeme (neměly by být žádné takové) $IPTABLES -A OUTPUT $LOG_LIMIT -j LOG --log-prefix "$prefix" } # }}} accept_related() { # {{{ echo "Accepting ESTABLISHED, RELATED packets for IP ${!INET_IP}" $IPTABLES -A INPUT -d ${!INET_IP} -m state --state ESTABLISHED,RELATED -j ACCEPT } # }}} accept_loopback() { # {{{ # Loopback není radno omezovat echo "Accepting loopback" $IPTABLES -A INPUT -i $LO_IFACE -j ACCEPT } # }}} # Parse output from ifconfig: - tested on Linux and FreeBSD # -- creates shell variables like IP_eth0="192.168.1.123" # http://platon.sk/cvs/cvs.php/scripts/shell/firewall/ifconfig-parse.sh parse_ifconfig() { # {{{ # Parse output from ifconfig: eval `$IFCONFIG | \ $AWK 'BEGIN { interfaces=""; } /^[a-zA-Z0-9]+[ \t]+/ { # Linux iface=$1; interfaces = sprintf("%s %s", interfaces, iface); printf "\nIFACE_%s=\"%s\"; export IFACE_%s;\n", iface, iface, iface; printf "HWaddr_%s=\"%s\"; export HWaddr_%s;\n", iface, $5, iface; } /^[ \t]+inet addr:/ { # Linux split($0, fields, "[ \t:]+"); printf "IP_%s=\"%s\"; export IP_%s;\n", iface, fields[4], iface; printf "Bcast_%s=\"%s\"; export Bcast_%s;\n", iface, fields[6], iface; printf "Mask_%s=\"%s\"; export Mask_%s;\n", iface, fields[8], iface; } /^[a-zA-Z0-9]+:/ { # FreeBSD iface = $1; sub(":", "", iface); interfaces = sprintf("%s %s", interfaces, iface); printf "\nIFACE_%s=\"%s\"; export IFACE_%s;\n", iface, iface, iface; } /^[ \t]+inet [0-9]+/ { # FreeBSD printf "IP_%s=\"%s\"; export IP_%s;\n", iface, $2, iface; printf "Bcast_%s=\"%s\"; export Bcast_%s;\n", iface, $6, iface; printf "Mask_%s=\"%s\"; export Mask_%s;\n", iface, $4, iface; } /^[ \t]+ether/ { # FreeBSD printf "HWaddr_%s=\"%s\"; export HWaddr_%s;\n", iface, $2, iface; } END { printf "\ninterfaces=\"%s\"; export interfaces;\n", interfaces; } '` # Now we have defined variables like this: # IFACE_eth0 HWaddr_eth0 IP_eth0 Bcast_eth0 Mask_eth0 # IFACE_lo HWaddr_lo IP_lo Bcast_lo Mask_lo # interfaces } # }}} parse_ifconfig case "$1" in start) echo -n "Starting $DESC: " # Inicialize modules $DEPMOD -a load_modules # # (un)commnet next lines as needed # set_default_policy set_loopback nmap_scan_filter invalid_packet_filter #anti_spoof_filter syn_flood mangle_prerouting mangle_output allow_input allow_output accept_related accept_loopback log_input_drop log_output_drop ;; stop) echo -n "Stopping $DESC: " unload_modules remove_chains set_default_policy ;; status) print_iface_status; echo $IPTABLES -L -nv ;; *) echo "Usage: $0 {start|stop|stop}" >&2 exit 1 ;; esac exit 0 # vim600: fdm=marker fdl=0 fdc=3