#!/bin/sh ############################################################################### # # Original by Dinesh Kandiah # Major update by Daniel Carrera # # Copyright (C) 2000-2002 Point Clark Networks # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Inspired by... # - Trinity OS # - Linux Security # - linux-firewall-tools.com # - Usenet # ############################################################################### PATH=/sbin:/bin:/usr/bin UNIV="0.0.0.0/0" ######################################################################### # F U N C T I O N S ######################################################################### ######################################################################### # # K E R N E L S E T T I N G S # ######################################################################### setKernel() { # Enable IP Forwarding, not really required for standalone mode sysctl -w net.ipv4.ip_forward=1 >/dev/null # Enable TCP SYN Cookie protection: sysctl -w net.ipv4.tcp_syncookies=1 >/dev/null # Enabling dynamic TCP/IP address hacking. sysctl -w net.ipv4.ip_dynaddr=1 >/dev/null # Required for IPsec VPN sysctl -w net.ipv4.conf.all.rp_filter=0 >/dev/null sysctl -w net.ipv4.conf.eth0.rp_filter=0 >/dev/null 2>/dev/null sysctl -w net.ipv4.conf.ppp0.rp_filter=0 >/dev/null 2>/dev/null # Log spoofed, source-routed, and redirect packets sysctl -w net.ipv4.conf.all.log_martians=0 >/dev/null # Disable ICMP Re-directs sysctl -w net.ipv4.conf.all.accept_redirects=0 >/dev/null sysctl -w net.ipv4.conf.all.send_redirects=0 >/dev/null # Ensure that source-routed packets are dropped sysctl -w net.ipv4.conf.all.accept_source_route=0 >/dev/null # Disable ICMP broadcast echo protection sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 >/dev/null # Enable bad error message protection sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1 >/dev/null } ######################################################################### # # S E T P O L I C Y # ######################################################################### setPolicy() { for TABLE in filter nat mangle; do iptables -t $TABLE -F # Flush all previous rules. iptables -t $TABLE -X # Delete user-defined chains. done iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP } ######################################################################### # # D E F I N E C H A I N S # ######################################################################### defineChains() { # Create a chain for dropping trojans and flooders #------------------------------------------------- iptables -N drop-trojan iptables -t filter -A drop-trojan -j LOG --log-prefix "Drop - trojan-flooder: " iptables -t filter -A drop-trojan -j DROP # Create a chain for dropping reserved network IPs #------------------------------------------------- iptables -N drop-reserved iptables -t filter -A drop-reserved -j LOG --log-prefix "Drop - reserved network: " iptables -t filter -A drop-reserved -j DROP # Create a chain for dropping services that shouldn't leave the LAN #------------------------------------------------------------------ iptables -N drop-lan iptables -t filter -A drop-lan -j LOG --log-prefix "Drop - LAN only: " iptables -t filter -A drop-lan -j REJECT # Create a chain for flagging possible Trojans & services leaving the LAN #------------------------------------------------------------------------ iptables -N flag-lan iptables -t filter -A flag-lan -j LOG --log-prefix "Flag: " iptables -t filter -A flag-lan -j ACCEPT # Create a chain for testing #--------------------------- iptables -N testing iptables -t filter -A testing -j LOG --log-prefix "testing: " iptables -t filter -A testing -j ACCEPT } ######################################################################### # # L O A D K E R N E L M O D U L E S # ######################################################################### loadModules() { modprobe ipt_LOG # Add LOG target. modprobe ipt_REJECT # Add REJECT target. modprobe ipt_MASQUERADE # Add MASQUERADE target. modprobe ipt_owner # Allows you to match for the owner. modprobe ip_conntrack_ftp # Support connection tracking of FTP. modprobe ip_conntrack_irc # Support connection tracking of IRC. modprobe ip_nat_ftp # Active FTP modprobe ip_nat_irc # IRC stuff modprobe ip_conntrack_pptp > /dev/null 2>&1 # PPTP (Office only) # ip_nat_pptp module is handled in the default rules section. } ######################################################################### # # A D H O C R U L E S # ######################################################################### # # We sometimes want to drop in special rules into the firewall. # For instance, the cc-pptpd RPM will add /etc/rc.d/rc.firewal.pptp # to add the required ports and protocol to the firewall. runAdhocRules() { for EXTRAS in pptpd pptp squid ipsec; do FILENAME=/etc/rc.d/rc.firewall.$EXTRAS if [ -x $FILENAME ]; then logger -p local6.notice -t firewall "Running ad-hoc rules in $EXTRAS" . $FILENAME logger -p local6.notice -t firewall "Finished ad-hoc rules in $EXTRAS" fi done } ######################################################################### # # R U N D E F A U L T # ######################################################################### runDefaultRules() { # Allow everything on the loopback #--------------------------------- iptables -A INPUT -j ACCEPT -i lo iptables -A OUTPUT -j ACCEPT -o lo # Block IPs that should never show up on our external interface #-------------------------------------------------------------- iptables -A INPUT -j drop-reserved -i $EXTIF -s 127.0.0.0/8 iptables -A INPUT -j drop-reserved -i $EXTIF -s 1.0.0.0/8 iptables -A INPUT -j drop-reserved -i $EXTIF -s 23.0.0.0/8 iptables -A INPUT -j drop-reserved -i $EXTIF -s 31.0.0.0/8 iptables -A INPUT -j drop-reserved -i $EXTIF -s 96.0.0.0/3 iptables -A INPUT -j drop-reserved -i $EXTIF -s 128.0.0.0/16 iptables -A INPUT -j drop-reserved -i $EXTIF -s 128.9.64.26/32 iptables -A INPUT -j drop-reserved -i $EXTIF -s 128.66.0.0/16 iptables -A INPUT -j drop-reserved -i $EXTIF -s 191.255.0.0/16 iptables -A INPUT -j drop-reserved -i $EXTIF -s 197.0.0.0/16 iptables -A INPUT -j drop-reserved -i $EXTIF -s 201.0.0.0/8 iptables -A INPUT -j drop-reserved -i $EXTIF -s 223.255.255.0/24 iptables -A INPUT -j drop-reserved -i $EXTIF -s 240.0.0.0/5 iptables -A INPUT -j drop-reserved -i $EXTIF -s 248.0.0.0/5 CHKINT1=`echo $EXTIP | cut -d '.' -f1,2` CHKINT2=`echo $EXTIP | cut -d '.' -f1` # - If this box is sitting on an internal network, don't block these IPs # - Don't log these as drop-reserved... funny ISPs (@Home) to blame if [ "$CHKINT1" != "172.16" ]; then iptables -A INPUT -j DROP -i $EXTIF -s 172.16.0.0/12 fi if [ "$CHKINT1" != "192.168" ]; then iptables -A INPUT -j DROP -i $EXTIF -s 192.168.0.0/16 fi # Ugh... funny ISPs use 10.x.x.x for DNS servers and other such things #if [ "$CHKINT2" != "10" ]; then # iptables -A INPUT -j DROP -i $EXTIF -s 10.0.0.0/8 #fi # Allow some ICMP (ping) #----------------------- # ICMP can be used for attacks.. we allow as little as possible. # The following are necessary ports we *can't* do without: # 0 Needed to ping hosts outside the network. # 3 Needed by all networks. # 11 Needed by the traceroute program. iptables -A INPUT -i $EXTIF -d $EXTIP -j ACCEPT -p icmp --icmp-type 0 iptables -A INPUT -i $EXTIF -d $EXTIP -j ACCEPT -p icmp --icmp-type 3 iptables -A INPUT -i $EXTIF -d $EXTIP -j ACCEPT -p icmp --icmp-type 11 #This allows other hosts to ping you. You should keep this rule. iptables -A INPUT -i $EXTIF -d $EXTIP -j ACCEPT -p icmp --icmp-type 8 iptables -A OUTPUT -j ACCEPT -o $EXTIF -p icmp -s $EXTIP # Allow DHCP client to respond #----------------------------- iptables -A INPUT -j ACCEPT -i $EXTIF -p udp -d $EXTIP --dport bootpc --sport bootps iptables -A INPUT -j ACCEPT -i $EXTIF -p tcp -d $EXTIP --dport bootpc --sport bootps iptables -A OUTPUT -j ACCEPT -o $EXTIF -p tcp -s $EXTIP --sport bootpc --dport bootps iptables -A OUTPUT -j ACCEPT -o $EXTIF -p udp -s $EXTIP --sport bootpc --dport bootps # Allow PPTP protocol and port if server is set to run #----------------------------------------------------- # note: the ip_nat_pptp module should not be run on a PPTP server! PPTPCHK=`chkconfig --list pptpd 2>/dev/null | grep "3:on"` if [ -z "$PPTPCHK" ]; then modprobe ip_nat_pptp > /dev/null 2>&1 # PPTP (Office only) else logger -p local6.notice -t firewall "Unloading PPTP connection tracker for PPTP server" rmmod ip_nat_pptp > /dev/null 2>&1 logger -p local6.notice -t firewall "Allowing incoming GRE protocol 47 for PPTP server" iptables -A INPUT -j ACCEPT -i $EXTIF -p 47 iptables -A OUTPUT -j ACCEPT -o $EXTIF -p 47 logger -p local6.notice -t firewall "Allowing incoming TCP port 1723 for PPTP server" iptables -A INPUT -j ACCEPT -i $EXTIF -p tcp -d $EXTIP --dport 1723 iptables -A OUTPUT -j ACCEPT -o $EXTIF -p tcp -s $EXTIP --sport 1723 fi } ######################################################################### # # I N C O M I N G A L L O W E D # ######################################################################### runIncomingAllowed() { for PORT in $INCOMING_ALLOWED_TCP; do logger -p local6.notice -t firewall "Allowing incoming TCP port $PORT" iptables -A INPUT -j ACCEPT -i $EXTIF -p tcp -d $EXTIP --dport $PORT iptables -A OUTPUT -j ACCEPT -o $EXTIF -p tcp -s $EXTIP --sport $PORT done for PORT in $INCOMING_ALLOWED_UDP; do logger -p local6.notice -t firewall "Allowing incoming UDP port $PORT" iptables -A INPUT -j ACCEPT -i $EXTIF -p udp -d $EXTIP --dport $PORT iptables -A OUTPUT -j ACCEPT -o $EXTIF -p udp -s $EXTIP --sport $PORT done } ######################################################################### # # O U T G O I N G D E N I E D # ######################################################################### runOutgoingDenied() { for PORT in $OUTGOING_DENIED_TCP; do logger -p local6.notice -t firewall "Blocking outgoing TCP port $PORT" iptables -A PREROUTING -t nat -s $LANNETWORK/$LANNETMASK -d 0/0 -p tcp --dport $PORT -j DROP done for PORT in $OUTGOING_DENIED_UDP; do logger -p local6.notice -t firewall "Blocking outgoing UDP port $PORT" iptables -A PREROUTING -t nat -s $LANNETWORK/$LANNETMASK -d 0/0 -p udp --dport $PORT -j DROP done for HOST in $OUTGOING_DENIED_HOST; do logger -p local6.notice -t firewall "Blocking traffic to $HOST" iptables -A PREROUTING -t nat -s $LANNETWORK/$LANNETMASK -d $HOST -j DROP done for RULE in $OUTGOING_DENIED_HOST_PORT; do HOST=`echo $RULE | cut -d ':' -f1` PORT=`echo $RULE | cut -d ':' -f2` logger -p local6.notice -t firewall "Blocking traffic to $HOST on port $PORT" iptables -A PREROUTING -t nat -s $LANNETWORK/$LANNETMASK -d $HOST -p tcp --dport $PORT -j DROP done } ######################################################################### # # P O R T F O R W A R D I N G # ######################################################################### runPortForwardRules() { for RULE in $FORWARD_TCP_PORT; do SOURCE=`echo $RULE | cut -d '|' -f2` DEST=`echo $RULE | cut -d '|' -f3` NATTRICK=`echo $DEST | cut -d ':' -f1` logger -p local6.notice -t firewall "Port forwarding TCP $SOURCE to $DEST" iptables -A PREROUTING -t nat -p tcp -d $EXTIP --dport $SOURCE -j DNAT --to $DEST iptables -A POSTROUTING -t nat -p tcp -d $NATTRICK -s $LANNETWORK/$LANNETMASK --dport $SOURCE -j SNAT --to $LANIP done for RULE in $FORWARD_UDP_PORT; do SOURCE=`echo $RULE | cut -d '|' -f2` DEST=`echo $RULE | cut -d '|' -f3` NATTRICK=`echo $DEST | cut -d ':' -f1` logger -p local6.notice -t firewall "Port forwarding UDP $SOURCE to $DEST" iptables -A PREROUTING -t nat -p udp -d $EXTIP --dport $SOURCE -j DNAT --to $DEST iptables -A POSTROUTING -t nat -p udp -d $NATTRICK -s $LANNETWORK/$LANNETMASK --dport $SOURCE -j SNAT --to $LANIP done } ######################################################################### # # S T A N D A L O N E F I R E W A L L # ######################################################################### standalone() { setKernel setPolicy loadModules defineChains runDefaultRules runAdhocRules # User defined rules #------------------- runIncomingAllowed # INCOMING RULES #================================================================ # Allow high ports #----------------- iptables -A OUTPUT -o $EXTIF -p tcp -j ACCEPT -s $EXTIP --sport 1024:65535 iptables -A OUTPUT -o $EXTIF -p udp -j ACCEPT -s $EXTIP --sport 1024:65535 iptables -A INPUT -j ACCEPT -p udp --dport 1024:65535 -d $EXTIP iptables -A INPUT -j ACCEPT -p tcp --dport 1024:65535 -d $EXTIP \ -m state --state ESTABLISHED,RELATED # Block everything else #---------------------- iptables -A INPUT -j DROP -i $EXTIF -s $UNIV -d $UNIV iptables -A OUTPUT -j DROP -o $EXTIF -s $UNIV -d $UNIV } ######################################################################### # # G A T E W A Y F I R E W A L L # ######################################################################### gateway() { setKernel setPolicy loadModules defineChains runDefaultRules runAdhocRules # INCOMING RULES #================================================================ # User defined rules #------------------- runIncomingAllowed # Allow trusted networks (e.g. the LAN) #-------------------------------------- iptables -A INPUT -j ACCEPT -i $TRUSTEDIF iptables -A OUTPUT -j ACCEPT -o $TRUSTEDIF # Allow high ports #----------------- iptables -A OUTPUT -o $EXTIF -p tcp -j ACCEPT -s $EXTIP --sport 1024:65535 iptables -A OUTPUT -o $EXTIF -p udp -j ACCEPT -s $EXTIP --sport 1024:65535 iptables -A INPUT -j ACCEPT -p udp --dport 1024:65535 -d $EXTIP iptables -A INPUT -j ACCEPT -p tcp --dport 1024:65535 -d $EXTIP \ -m state --state ESTABLISHED,RELATED # Block everything else #---------------------- iptables -A INPUT -j DROP -i $EXTIF -s $UNIV -d $UNIV iptables -A OUTPUT -j DROP -o $EXTIF -s $UNIV -d $UNIV # FORWARD RULES #================================================================ # User defined rules #------------------- runPortForwardRules runOutgoingDenied # Block services from leaving the LAN (low port numbers) # Snort will log suspicious traffic in high port ranges #------------------------------------------------------- iptables -A FORWARD -j drop-lan -o $EXTIF -p tcp --dport 111 # RPC stuff iptables -A FORWARD -j drop-lan -o $EXTIF -p udp --dport 111 # RPC stuff iptables -A FORWARD -j drop-lan -o $EXTIF -p tcp --dport 137:139 # Samba iptables -A FORWARD -j drop-lan -o $EXTIF -p udp --dport 137:139 # Samba iptables -A FORWARD -j drop-lan -o $EXTIF -p tcp --dport 635 # Mountd iptables -A FORWARD -j drop-lan -o $EXTIF -p udp --dport 635 # Mountd # Enable masquerading #-------------------- iptables -A POSTROUTING -t nat -j MASQUERADE -o $EXTIF iptables -A FORWARD -i $TRUSTEDIF -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m limit --limit 3/minute --limit-burst 3 \ -j LOG --log-level DEBUG --log-prefix "IPT FORWARD packet died: " # Allow all other forwarding #--------------------------- # You need this rule if you port forward packets to machines behind the gateway. iptables -A FORWARD -j ACCEPT } ######################################################################### # # T R U S T E D G A T E W A Y # ######################################################################### trustedgateway() { setKernel loadModules # First clear everything #----------------------- for TABLE in filter nat mangle; do iptables -t $TABLE -F # Flush all previous rules. iptables -t $TABLE -X # Delete user-defined chains. done # Default policies #----------------- iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT # Enable masquerading #-------------------- iptables -A POSTROUTING -t nat -j MASQUERADE -o $EXTIF } ######################################################################### # M A I N # ######################################################################### ######################################################################### # # We can determine wheter we have a gateway or standalone machine. This # will work in the following situations: # # 1) Standalone server # 2) Gateway with two network cards (Internet + LAN) # 3) Gateway with three or more network cards (Internet + 2 or more LANs) # # DMZs, trusted gateways, and other network configuration will require # manual configuration in /etc/firewall. logger -p local6.notice -t firewall "Starting firewall..." # Configuration file #------------------- [ -f /etc/firewall ] && . /etc/firewall # Defaults #--------- if [ -z $EXTIF ]; then EXTIF=`cat /etc/sysconfig/network | grep GATEWAYDEV | cut -d '=' -f2` if [ -z $EXTIF ]; then echo "Gateway not defined in /etc/sysconfig/network... using eth0" logger -p local6.notice -t firewall "Gateway not set in /etc/sysconfig/network... using eth0" EXTIF="eth0" fi fi [ -z $LANIF ] && LANIF="eth1" [ -z $DMZIF ] && DMZIF="none" [ -z $TRUSTEDIF ] && TRUSTEDIF="! $EXTIF" # Sanity check #------------- EXTIP=`ifconfig | grep -A 4 $EXTIF | awk '/inet/{print $2}' | sed -e s/addr://` if [ -z $EXTIP ]; then echo "External IP not available... exiting" logger -p local6.notice -t firewall "External IP not available... exiting" exit 1 fi # LAN info #--------- if [ -f /etc/sysconfig/network-scripts/ifcfg-$LANIF ]; then LANIP=`grep IPADDR /etc/sysconfig/network-scripts/ifcfg-$LANIF | sed -e s/IPADDR=//i` if [ -z $LANIP ]; then logger -p local6.notice -t firewall "Could not determine LAN IP on $LANIF... exiting" echo "Could not determine LAN IP on $LANIF... exiting" exit 1 fi LANNETMASK=`grep NETMASK /etc/sysconfig/network-scripts/ifcfg-$LANIF | sed -e s/NETMASK=//i` if [ -z $LANNETMASK ]; then logger -p local6.notice -t firewall "Could not determine LAN netmask on $LANIF... exiting" echo "Could not determine LAN netmask on $LANIF... exiting" exit 1 fi LANNETWORK=`ipcalc --network $LANIP $LANNETMASK | sed s/NETWORK=//i` if [ -z $LANNETWORK ]; then logger -p local6.notice -t firewall "Could not determine LAN network on $LANIF... exiting" echo "Could not determine LAN network on $LANIF... exiting" exit 1 fi LANPREFIX=`ipcalc --prefix $LANIP $LANNETMASK | sed s/PREFIX=//i` if [ -z $LANPREFIX ]; then logger -p local6.notice -t firewall "Could not determine LAN prefix on $LANIF... exiting" echo "Could not determine LAN prefix on $LANIF... exiting" exit 1 fi logger -p local6.notice -t firewall "LAN info - $LANIP/$LANNETMASK on network $LANNETWORK/$LANPREFIX" TYPE="gateway" fi # DMZ info #--------- if [ -f /etc/sysconfig/network-scripts/ifcfg-$DMZIF ]; then GWIP=`grep GATEWAY /etc/sysconfig/network-scripts/ifcfg-$EXTIF | sed -e s/GATEWAY=//i` if [ -z $GWIP ]; then logger -p local6.notice -t firewall "Could not determine default route... exiting" echo "Could not determine default route... exiting" exit 1 fi DMZIP=`grep IPADDR /etc/sysconfig/network-scripts/ifcfg-$DMZIF | sed -e s/IPADDR=//i` if [ -z $DMZIP ]; then logger -p local6.notice -t firewall "Could not determine DMZ IP on $DMZIF... exiting" echo "Could not determine DMZ IP on $DMZIF... exiting" exit 1 fi DMZNETMASK=`grep NETMASK /etc/sysconfig/network-scripts/ifcfg-$DMZIF | sed -e s/NETMASK=//i` if [ -z $DMZNETMASK ]; then logger -p local6.notice -t firewall "Could not determine DMZ netmask on $DMZIF... exiting" echo "Could not determine DMZ netmask on $DMZIF... exiting" exit 1 fi DMZNETWORK=`ipcalc --network $DMZIP $DMZNETMASK | sed s/NETWORK=//i` if [ -z $DMZNETWORK ]; then logger -p local6.notice -t firewall "Could not determine DMZ network on $DMZIF... exiting" echo "Could not determine DMZ network on $DMZIF... exiting" exit 1 fi DMZPREFIX=`ipcalc --prefix $DMZIP $DMZNETMASK | sed s/PREFIX=//i` if [ -z $DMZPREFIX ]; then logger -p local6.notice -t firewall "Could not determine DMZ prefix on $DMZIF... exiting" echo "Could not determine DMZ prefix on $DMZIF... exiting" exit 1 fi logger -p local6.notice -t firewall "DMZ info - $DMZIP/$DMZNETMASK on network $DMZNETWORK/$DMZPREFIX" TYPE="dmz" fi if [ ! -z $TRUSTEDGATEWAY ]; then TYPE="trustedgateway" fi # Start the firewall #------------------- if [ "$TYPE" == "gateway" ]; then logger -p local6.notice -t firewall "Using gateway mode" gateway elif [ "$TYPE" == "dmz" ]; then logger -p local6.notice -t firewall "Using DMZ mode" gateway elif [ "$TYPE" == "trustedgateway" ]; then logger -p local6.notice -t firewall "Using trusted gateway mode" trustedgateway else logger -p local6.notice -t firewall "Using standalone mode" standalone fi