#!/bin/bash # pfilter -- allows for easy management of iptables rules # Packet filter for single host # Installation (need root privilege): # RedHat systems: # # /sbin/chkconfig --add pfilter # non-RedHat systems: # # cp pfilter /etc/init.d/pfilter # (then set up the necessary symlinks) # Be sure to check the variables in the CONFIGURATION section below # If you want to allow access to services on this host, # do the following: # - uncomment the allowed_services function call in start() # - write the necessary rules to allow that service # There are example rules below. # Also, you can comment out the extended_filters check. The function # call is in start() # chkconfig: 2345 02 90 # description: Pfilter is a script that manages iptable filtering # pidfile: /var/run/pfilter.pid # Copyright 2000 Stephen Fromm stephenf@ns.uoregon.edu # 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 MERCHANTIBILITY # 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. ############################################ # # # BEGIN CONFIGURATION # # # ############################################ IPT="/sbin/iptables" MP="/sbin/modprobe" # BE SURE TO DEFINE THE FOLLOWING AS IP ADDRESSES, NOT HOSTNAMES # interface connected to internet WAN_IF="eth0" # host's ip address WAN_IP="10.0.1.1" # host's subnet mask - to allow privilege for hosts on same subnet WAN_SUBNET="$WAN_IP/24" # similar to WAN_SUBNET - to allow privilege for hosts in a larger network WAN_NET="$WAN_IP/8" ############################################ # # # END CONFIGURATION # # # ############################################ ANY="any/0" # match any ip address LOOPBACK="127.0.0.1/8" # reserved loopback address CLASS_A="10.0.0.0/8" # Class A of private network ip addresses CLASS_B="172.16.0.0/12" # Class B CLASS_C="192.168.0.0/16" # Class C CLASS_D="224.0.0.0/4" # Class D Multicast reserved ip addresses CLASS_E="240.0.0.0/5" # Class E reserved BROADCAST_SRC="0.0.0.0" # broadcast source BROADCAST_DEST="255.255.255.255" # broadcast destination $MP ip_conntrack $MP ip_conntrack_ftp #----------------------------------------------------- # # define assorted linux kernel security mechanisms kernel_security () { echo -n "Defining linux security mechanisms..." # Enable TCP SYN cookie protection (must be compiled in kernel to work) echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Enable IP spoofing protection; turn on Source Address Verification for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f done # Disable ICMP Redirect Acceptance for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f done # Disable Source-Routed Packets for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f done # Enable broadcast echo protection; prevent smurfs echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Ignore icmp bogus error echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses # Log packets with impossible addresses to kernel log for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo 1 > $f done echo "Done." } #------------------------------------------------------- # # flush and zero the chains flush_and_zero () { echo -n "Flushing and zeroing chains..." $IPT -F $IPT -X $IPT -Z echo "Done." } #--------------------------------------------------------- # # stop filtering and allow everything stop () { flush_and_zero echo -n "Resetting chains to default ACCEPT..." $IPT -P INPUT ACCEPT $IPT -P OUTPUT ACCEPT $IPT -P FORWARD ACCEPT rm -f /var/lock/subsys/iptables echo "Done." } #--------------------------------------------------------- # # set it all up, baby! start() { kernel_security flush_and_zero echo -n "Setting default policy..." $IPT -P OUTPUT DROP $IPT -P INPUT DROP $IPT -P FORWARD DROP echo "Done." # allow all loopback stuff $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT $IPT -N SANITY $IPT -N LIMIT # if you don't want to use the extended filtering checks (to be # added to the above two chains), comment out this function call extended_filters $IPT -A INPUT -i $WAN_IF -j SANITY $IPT -A INPUT -i $WAN_IF -j LIMIT # Allow established/related stuff back in echo -n "Allowing stuff with state..." $IPT -A INPUT -m state --state ESTABLISHED,RELATED \ -i $WAN_IF -s ! $WAN_IP -d $WAN_IP -j ACCEPT $IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED \ -o $WAN_IF -s $WAN_IP -j ACCEPT echo "Done." $IPT -N ALLOWED # Services to allow # uncomment if you wish to allow these services # add additional req. services to allowed_services function # allowed_services $IPT -A INPUT -i $WAN_IF -j ALLOWED # Random logging stuff echo -n "Defining what to log..." $IPT -A INPUT -i $WAN_IF -s $ANY -p tcp --syn -m limit \ -j LOG --log-level warning \ --log-prefix "Connection attempt: " $IPT -A INPUT -i $WAN_IF -s $ANY -p tcp -m limit \ -j LOG --log-level warning \ --log-prefix "Unallowed traffic: " touch /var/lock/subsys/iptables echo "Done." } #--------------------------------------------------------- # # services to allow; only set if function call above is uncommented allowed_services() { echo -n "Stating services to allow..." echo -n "[ SSH" $IPT -A ALLOWED -s $ANY -p tcp --dport 22 \ -m state --state NEW,ESTABLISHED -j ACCEPT echo -n ", WWW" $IPT -A ALLOWED -s $ANY -p tcp --dport 80 \ -m state --state NEW,ESTABLISHED -j ACCEPT echo -n ", SMTP" $IPT -A ALLOWED -s $ANY -p tcp --dport 25 \ -m state --state NEW,ESTABLISHED -j ACCEPT echo " ] Done." $IPT -A ALLOWED -i $WAN_IF -s $WAN_NET -p tcp --dport 113 \ -j REJECT } #--------------------------------------------------------- # # extended filters # this encompasses bogus address detection, scan detection, # dtop fragments, and limit pings extended_filters() { # look for probes echo -n "Setting up scan detection..." $IPT -A SANITY -p tcp --tcp-flags ALL FIN,URG,PSH \ -j LOG --log-level warning --log-prefix "XMAS Scan: " $IPT -A SANITY -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A SANITY -p tcp --tcp-flags ALL NONE \ -j LOG --log-level warning --log-prefix "Null Scan: " $IPT -A SANITY -p tcp --tcp-flags ALL NONE -j DROP $IPT -A SANITY -p tcp --tcp-flags ALL FIN \ -j LOG --log-level warning --log-prefix "FIN Scan: " $IPT -A SANITY -p tcp --tcp-flags ALL FIN -j DROP echo "Done." # detect spoofed echo -n "Setting up spoof detection..." $IPT -A SANITY -s $WAN_IP -j LOG --log-level warning \ --log-prefix "$WAN_IP is source: " $IPT -A SANITY -s $LOOPBACK -j LOG --log-level warning \ --log-prefix "$LOOPBACK is source: " $IPT -A SANITY -s $CLASS_A -j LOG --log-level warning \ --log-prefix "Class A spoofed src packet: " $IPT -A SANITY -s $CLASS_B -j LOG --log-level warning \ --log-prefix "Class B spoofed src packet: " $IPT -A SANITY -s $CLASS_C -j LOG --log-level warning \ --log-prefix "Class C spoofed src packet: " $IPT -A SANITY -s $CLASS_D -j LOG --log-level warning \ --log-prefix "Class D spoofed src packet: " $IPT -A SANITY -s $CLASS_E -j LOG --log-level warning \ --log-prefix "Class E spoofed src packet: " $IPT -A SANITY -s $WAN_IP -j DROP $IPT -A SANITY -s $LOOPBACK -j DROP $IPT -A SANITY -s $CLASS_A -j DROP $IPT -A SANITY -s $CLASS_B -j DROP $IPT -A SANITY -s $CLASS_C -j DROP $IPT -A SANITY -s $CLASS_D -j DROP $IPT -A SANITY -s $CLASS_E -j DROP echo "Done." echo -n "Dropping fragments..." $IPT -A SANITY -f -j LOG --log-level warning \ --log-prefix "Rcvd fragment: " $IPT -A SANITY -f -j DROP echo "Done." # limit pings echo -n "Limiting pings and pongs..." $IPT -A LIMIT -p icmp --icmp-type echo-request \ -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A LIMIT -p icmp --icmp-type echo-reply \ -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A LIMIT -p icmp --icmp-type echo-request \ -s ! $WAN_NET -j DROP $IPT -A LIMIT -p icmp --icmp-type echo-reply \ -s ! $WAN_NET -j DROP $IPT -A LIMIT -p icmp --icmp-type echo-request \ -s $WAN_NET -m limit --limit 1/s -j ACCEPT $IPT -A LIMIT -p icmp --icmp-type echo-reply \ -s $WAN_NET -m limit --limit 1/s -j ACCEPT echo "Done." } #--------------------------------------------------------- # # usage statement USAGE () { cat < block traffic to/from host {log|unlog} log traffic to/from host EOF } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; panic) flush_and_zero echo -n "Dropping everything..." $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP echo "Done." ;; kill) echo -n "Blocking packets to/from $2..." $IPT -I INPUT -s $2 -j DROP $IPT -I OUTPUT -d $2 -j DROP $IPT -I FORWARD -s $2 -j DROP $IPT -I FORWARD -d $2 -j DROP echo "Done." ;; unkill) echo -n "Removing block on $2..." $IPT -D INPUT -s $2 -j DROP $IPT -D OUTPUT -d $2 -j DROP $IPT -D FORWARD -s $2 -j DROP $IPT -D FORWARD -d $2 -j DROP echo "Done." ;; log) echo -n "Logging traffic from/to $2..." $IPT -I INPUT -s $2 -j LOG --log-prefix "Logging $2: " $IPT -I OUTPUT -s $2 -j LOG --log-prefix "Logging $2: " $IPT -I FORWARD -s $2 -j LOG --log-prefix "Logging $2: " $IPT -I FORWARD -d $2 -j LOG --log-prefix "Logging $2: " echo "Done." ;; unlog) echo -n "Removing rules to log traffic from/to $2..." $IPT -D INPUT -s $2 -j LOG --log-prefix "Logging $2: " $IPT -D OUTPUT -s $2 -j LOG --log-prefix "Logging $2: " $IPT -D FORWARD -s $2 -j LOG --log-prefix "Logging $2: " $IPT -D FORWARD -d $2 -j LOG --log-prefix "Logging $2: " echo "Done." ;; status) echo "***Normal Chains: " $IPT --list -n ;; *) USAGE exit 1 ;; esac exit 0