Code: #!/bin/bash ### BEGIN INIT INFO # Provides: Firewall # Required-Start: $local_fs $network $syslog # Required-Stop: $local_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop Firewall ### END INIT INFO . /lib/lsb/init-functions #--------------------------------------------------------------------- # /etc/init.d/firewall # # IPTables (netfilter) firewall manager script # # Server: backup # # History of modifications # When Who What # ---- --- ---------- # 2011-06-01 Mark Original version # 2011-07-13 Mark Moved OUTPUT rules above INPUT rules # #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Global variables # IPT=`which iptables` MODPROBE=`which modprobe` DEPMOD=`which depmod` FLAGS='URG,ACK,PSH,RST,SYN,FIN' LOG_LEVEL="debug" CONFIG_FILE="/usr/local/etc/firewall.conf" #--------------------------------------------------------------------- # Config file # if [ ! -f $CONFIG_FILE ]; then echo "Error: $CONFIG_FILE not found!"; exit 1; else source $CONFIG_FILE fi #--------------------------------------------------------------------- # Function: Usage # Shows a reminder #--------------------------------------------------------------------- Usage() { echo "Usage: $0: start|stop|restart" exit 1 } #--------------------------------------------------------------------- # Function: StartFirewall # Loads the rules in memory #--------------------------------------------------------------------- StartFirewall() { #--------------------------------------------------------------------- # Load kernel modules # $DEPMOD -a $MODPROBE ip_tables $MODPROBE ip_conntrack $MODPROBE ip_conntrack_ftp $MODPROBE iptable_filter $MODPROBE ipt_LOG $MODPROBE ipt_limit $MODPROBE ipt_state #--------------------------------------------------------------------- # Empty the "filter" table # $IPT -t filter -F $IPT -t filter -X #--------------------------------------------------------------------- # Default policy for all tables: drop everything # $IPT -t filter -P INPUT DROP $IPT -t filter -P OUTPUT DROP $IPT -t filter -P FORWARD DROP #--------------------------------------------------------------------- # Log entries definitions # # Every log "line" will be prefixed with "[FW:" (for firewall), to # make log filtering easier down the road. # Log DROPs $IPT -N LOG_DROP if [ `echo "x$LOG_DROPPED_PACKETS" | tr [:upper:] [:lower:]` = "xyes" ]; then $IPT -A LOG_DROP -j LOG --log-prefix '[FW:DROP] ' --log-level $LOG_LEVEL fi $IPT -A LOG_DROP -j DROP # Log ACCEPTs $IPT -N LOG_ACCEPT if [ `echo "x$LOG_ACCEPTED_PACKETS" | tr [:upper:] [:lower:]` = "xyes" ]; then $IPT -A LOG_ACCEPT -j LOG --log-prefix '[FW:ACCEPT] ' --log-level $LOG_LEVEL fi $IPT -A LOG_ACCEPT -j ACCEPT # Log REJECTs $IPT -N LOG_REJECT if [ `echo "x$LOG_REJECTED_PACKETS" | tr [:upper:] [:lower:]` = "xyes" ]; then $IPT -A LOG_REJECT -j LOG --log-prefix '[FW: REJECT] ' --log-level $LOG_LEVEL fi $IPT -A LOG_REJECT -j REJECT #--------------------------------------------------------------------- # Drop weird packets # # A packet can't have SYN+ACK and also be new! (state NEW) $IPT -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j LOG_REJECT # No legal packet can have all flags on or off: doesn't make sense $IPT -A INPUT -p tcp --tcp-flags ALL NONE -j LOG_DROP $IPT -A INPUT -p tcp --tcp-flags ALL ALL -j LOG_DROP #--------------------------------------------------------------------- #Loopback interface (lo: 127.0.0.1) must be open to itself # $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT # Anti spoofing: traffic from 127.0.0.0/8 must originate from the loopback interface $IPT -A INPUT -s 127.0.0.0/8 ! -i lo -j LOG_DROP #--------------------------------------------------------------------- # Logging of start and end of connections (but not the "middle" packets) # $IPT -t filter -A OUTPUT -p tcp --tcp-flags $FLAGS SYN,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A OUTPUT -p tcp --tcp-flags $FLAGS FIN,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A OUTPUT -p tcp --tcp-flags $FLAGS RST,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A INPUT -p tcp --tcp-flags $FLAGS SYN,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A INPUT -p tcp --tcp-flags $FLAGS FIN,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A INPUT -p tcp --tcp-flags $FLAGS RST,ACK -m state --state ESTABLISHED,RELATED -j LOG_ACCEPT $IPT -t filter -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #--------------------------------------------------------------------- # OUTBOUND traffic (OUTPUT table) # Traffic that this server sends (not forwarded traffic) # Allow all outbound traffic $IPT -t filter -A OUTPUT -j ACCEPT #--------------------------------------------------------------------- # INBOUND traffic (INPUT table) # Traffic addressed explicitly for this server (ie: not forwarded traffic, # if the server is used as router/firewall). for SERVICE in $SERVICES_ALLOWED_TCP; do IPS_LIST=`echo IP_ALLOWED_$SERVICE | tr '[:lower:]' '[:upper:]'` if [ "x${!IPS_LIST}" = "x" ]; then # No IP limitations for this service $IPT -t filter -A INPUT -p tcp --dport $SERVICE --tcp-flags $FLAGS SYN -m state --state NEW -j LOG_ACCEPT else for IP in ${!IPS_LIST}; do $IPT -t filter -A INPUT -p tcp --dport $SERVICE -s "$IP" --tcp-flags $FLAGS SYN -m state --state NEW -j LOG_ACCEPT done fi done for SERVICE in $SERVICES_ALLOWED_UDP; do IPS_LIST=`echo IP_ALLOWED_$SERVICE | tr '[:lower:]' '[:upper:]'` if [ "x${!IPS_LIST}" = "x" ]; then # No IP limitations for this service $IPT -t filter -A INPUT -p udp --dport $SERVICE -j LOG_ACCEPT else for IP in ${!IPS_LIST}; do $IPT -t filter -A INPUT -p udp --dport $SERVICE -s "$IP" -j LOG_ACCEPT done fi done # PING $IPT -t filter -A INPUT -p icmp --icmp-type echo-request -j LOG_ACCEPT #--------------------------------------------------------------------- # Log all packets before they are dropped # (default policy) $IPT -t filter -A INPUT -j LOG_DROP $IPT -t filter -A OUTPUT -j LOG_DROP $IPT -t filter -A FORWARD -j LOG_DROP } #--------------------------------------------------------------------- # Function: StopFirewall # Stop the firewall and ACCEPT ALL TRAFFIC #--------------------------------------------------------------------- StopFirewall() { #--------------------------------------------------------------------- # Empty all filter tables # $IPT -t filter -F $IPT -t filter -X #--------------------------------------------------------------------- # Default policy: Accept everything # $IPT -P INPUT ACCEPT $IPT -P OUTPUT ACCEPT $IPT -P FORWARD ACCEPT } #--------------------------------------------------------------------- # Function: RestartFirewall # Empty and reload firewall rules #--------------------------------------------------------------------- RestartFirewall() { StartFirewall } #--------------------------------------------------------------------- # Main program [ main() ] # Check first argument and launch appropriate function #--------------------------------------------------------------------- case "$1" in start) echo -n "Starting firewall: " StartFirewall echo `basename $0`; ;; stop) echo -n "Stopping firewall: " StopFirewall echo `basename $0`; ;; restart) echo -n "Restarting firewall: " RestartFirewall echo `basename $0`; ;; *) Usage ;; esac exit 0 Code: # Configuration file for firewall # =============================== # SERVICES_ALLOWED: defines the services that are allowed to be accessed # IP_ALLOWED_<SERVICE>: Default all have access to the open services defined in SERVICES_ALLOWED # But if you define an "IP_ALLOWED_<SERVICE>" variable, # only those ip's are allowed to the service. # (this counts for internal AND external traffic!!) # Checkout /etc/services for service names, else use port number SERVICES_ALLOWED_TCP="ssh http https nrpe" SERVICES_ALLOWED_UDP="snmp" IP_ALLOWED_SSH="192.168.4.0/22 host1.domain.tld host2.domain.tld" IP_ALLOWED_NRPE="noc.domain.tld" IP_ALLOWED_SNMP="noc.domain.tld" LOG_DROPPED_PACKETS=no LOG_ACCEPTED_PACKETS=no LOG_REJECTED_PACKETS=yes basic example of the setup. I'm no bash guru, but I think it's a nice base to start working with.