Chinaunix首页 | 论坛 | 博客
  • 博客访问: 288259
  • 博文数量: 65
  • 博客积分: 1514
  • 博客等级: 中尉
  • 技术积分: 820
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-20 21:01
文章分类

全部博文(65)

文章存档

2012年(65)

分类: LINUX

2012-02-04 21:56:51

#!/bin/bash
#
# A script for Linux (kernel 2.4.x) firewall configure.
#
# Copyleft 2002 by netman ().
#
# Redistribution of this file is permitted under the terms of
# the GNU General Public License (GPL).

############################################################################
## WARNING: Please do NOT run this script unless you had studied your     ##
## network environment. Since this script is still under development, it  ##
## may be not suitable for your circumstance.                             ##
## It is running on your OWN risk if you decide to run this script anyway.##
############################################################################

DATE="2002/10/20"
SCRIPT_NAME="$(basename $0)"
VERSION="1.02"
MAINTAINER="netman<>"

PATH=/sbin:/usr/sbin:/bin:/usr/bin
USAGE="Usage: $SCRIPT_NAME {masq|server|nat|route|reset|status|save|restore|help}"
RC_LOCAL=/etc/rc.d/rc.local
RC_SQUID=/etc/rc.d/init.d/squid
BOOT_LOG=/var/log/boot.log
SERVICES_FILE=/etc/services
IPT_AP=$(which iptables 2>/dev/null)
IPT_SAVE_AP=$(which iptables-save 2>/dev/null)
IPT_RESTORE_AP=$(which iptables-restore 2>/dev/null)
IPT_SAVE_FILE=/etc/sysconfig/iptables
IPT_TMP_DIR=/var/tmp
IPT_TMP_FILE=$IPT_TMP_DIR/$SCRIPT_NAME.tmp
IPT_TMP_FILE1=$IPT_TMP_DIR/${SCRIPT_NAME}1.tmp
IPT_TMP_CONF=$IPT_TMP_DIR/$SCRIPT_NAME.conf
IPT_TMP_RUN=$IPT_TMP_DIR/$SCRIPT_NAME.run

ALLOWED_ICMP="0 3 3/4 4 11 12 14 16 18"
DENIED_ICMP="8"

# ------------- ensure iptables ----------
test -z "$IPT_AP" && {
 echo
 echo "$SCRIPT_NAME: ERROR: iptables program is not found."
 echo " Please install the program first."
 echo
 exit 2
}

# ------------- rmmod ipchains ----------
rm_ipchains () {
 lsmod | grep ipchains &>/dev/null && {
  echo "Disabling ipchains..."
  rmmod ipchains
 }
}

# --- Function: Get net info ---
get_net () {
 unset NET
 for i in $(echo $IP | sed -e 's/\./\ /g'); do
  let N="$i & $1"
  NET="$NET.$N"
  NET=${NET#.}
  shift
 done
}

# --- FUNCTION: gather nic info ---
nic_info () {
 unset IF
 unset IP
 unset NET
 unset MASK
 for IF in $1; do
  IP=$(ifconfig | grep "$IF " -A 1 \
   | awk '/inet/ {print $2}' | sed -e 's/.*://')
  if [ -z "$IP" ]; then
   echo
   echo "ERROR: there is no IP found on interface '$IF'."
   echo " Please make sure $IF is setup properly."
   echo
   return 1
  else
   chk_if="ok"
  fi
  MASK=$(ifconfig | grep "$IF " -A 1 \
   | awk '/inet/ {print $4}' | sed -e 's/.*://')
        get_net $(echo $MASK | sed -e 's/\./\ /g')
 done
}

# --- Function: set nic --
get_nic () {
 nic_err () {
  echo
  echo -n "ERROR: the interface($1) has been "
  echo "assigned to $2 network."
  echo "You can not use it as $3 interface."
 }
 get_ext_nic () {
  unset chk_if
  until [ "$chk_if" = "ok" ]; do
   PRE_IF=$dfgwdev
   test -z "$PRE_IF" && PRE_IF="ppp0"
   echo -n "What is your External Interface? (Default $PRE_IF): "
   read EXT_IF
   test -z "$EXT_IF" && EXT_IF="$PRE_IF"
   nic_info $EXT_IF
   EXT_IP=$IP
   EXT_NET=$NET/$MASK
   EXT_MASK=$MASK
   set_EXT="true"
  done
 }
 get_int_nic () {
  unset chk_if
  until [ "$chk_if" = "ok" ]; do
   if [ "$EXT_IF" != "eth0" ]; then
    PRE_IF="eth0"
   else
    PRE_IF="eth1"
   fi
   echo -n "What is your Internal Interface? (Default $PRE_IF): "
   read INT_IF
   test -z "$INT_IF" && INT_IF="$PRE_IF"
   test "$INT_IF" = "$EXT_IF" && {
    nic_err $INT_IF EXTERNAL INTERNAL
    get_int_nic
   }
   nic_info $INT_IF
   INT_IP=$IP
   INT_NET=$NET/$MASK
   INT_MASK=$MASK
   set_INT="true"
  done
 }
 get_dmz_nic () {
  unset chk_if
  until [ "$chk_if" = "ok" ]; do
   echo -n "What is your DMZ Interface? (press ENTER for none): "
   read DMZ_IF
   if [ -z "$DMZ_IF" ]; then
    set_DMZ="false"
    chk_if="ok"
   else
    set_DMZ="true"
    test "$DMZ_IF" = "$EXT_IF" && {
     nic_err $DMZ_IF EXTERNAL DMZ
     get_dmz_nic
    }
    test "$DMZ_IF" = "$INT_IF" && {
     nic_err $DMZ_IF INTERNAL DMZ
     get_dmz_nic
    }
    nic_info $DMZ_IF
    DMZ_IP=$IP
    DMZ_NET=$NET/$MASK
    DMZ_MASK=$MASK
   fi
  done
 }
 get_ext_nic
 get_int_nic
 get_dmz_nic
}

# --- Function: Check external service ip ---
chk_ser_ip () {
 unset test_ser_ip
 for ip in $@; do
  ifconfig | grep "$EXT_IF" -A 1 | grep $ip &>/dev/null || {
   echo
   echo "ERROR: Could not find ip '$ip' on $EXT_IF or it's aliases!"
   echo "Please make sure $@ is bound to the external interface."
   echo
   return 1
  }
 test_ser_ip="ok"
 done
}

# --- Function: Check IP ---
chk_ip () {
    ip_err () {
        echo
        echo "ERROR: the IP ($chkip) you just entered is invalid."
        echo "       A valid IP is four numbers, each is between 0 and 255, "
        echo "       and separated by three dots(.)."
        echo -n "NOTE: you'd better have the knowledge "
        echo "on IP subnetting as well."
    }
    for chkip in $@; do
        echo $chkip | grep '^\.' && {
            ip_err
            return 1
        }
        echo $chkip | grep '\.$' && {
            ip_err
            return 1
        }
        CHKIP1=$(echo $chkip |awk -F'.' '{print $1}')
        CHKIP2=$(echo $chkip |awk -F'.' '{print $2}')
        CHKIP3=$(echo $chkip |awk -F'.' '{print $3}')
        CHKIP4=$(echo $chkip |awk -F'.' '{print $4}')
        CHKIP5=$(echo $chkip |awk -F'.' '{print $5}')
        if [ -z "$CHKIP1" ] || [ -z "$CHKIP2" ] || [ -z "$CHKIP3" ] \
                || [ -z "$CHKIP4" ] || [ ! -z "$CHKIP5" ]; then
   ip_err
            return 1
        elif (($CHKIP1 < 1)) || (($CHKIP1 > 255))  \
            || (($CHKIP2 < 0)) || (($CHKIP2 > 255))  \
            || (($CHKIP3 < 0)) || (($CHKIP3 > 255))  \
            || (($CHKIP4 < 0)) || (($CHKIP4 > 255));
        then
            ip_err
            return 1
        else
            ip_check="ok"
        fi
        if [ "$CHKIP1" = 10 ]; then
            pri_ip="true"
        elif [ "$CHKIP1" = 172 ]; then
            if (($CHKIP2 > 15)) && (($CHKIP2 < 32)); then
                pri_ip="true"
   else
    pri_ip="false"
            fi
        elif [ "$CHKIP1" = 192 ]  && [ "$CHKIP2" = 168 ]; then
            pri_ip="true"
  else
   pri_ip="false"
        fi
    done
}

# --- Function: Check Services ---
chk_ser_name () {
    list=$(echo "$@ " | sed 's/dns/domain/g' \
        | sed 's/ftp\ /ftp\ ftp-data\ /g' \
        | sed 's/pop\ /pop-3\ /g')
    unset port_nu
    for i in $list; do
        unset test_ser
        port_name=$(cat $SERVICES_FILE | awk -F "#" '{print $1}' \
   | sed /^$/d | sed 's/\/...//' | grep "\<$i\>[\ \ \/]" \
   | awk '{print $2}' | uniq )
     test -z "$port_name" && {
            echo "ERROR: port definition for '$i' is not found in $SERVICES_FILE."
            return 1
        }
        test_ser="ok"
        port_nu="$port_nu $port_name"
    done
}

# --- Function: Routing Waring ---
route_warn () {
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
 echo
  echo "WARNING: The IP($1) seemed a $2 IP."
  echo "         It should be a $3 IP in this case."
  echo -n "Are you sure? (Y/n): "
  read YN
  test -z "$YN" && YN="y"
 done
}

# --- Function: Determine routing waring ---
route_warn_dtm () {
 if [ "$mode" = "route" ] && [ "$pri_ip" = "true" ]; then
  route_warn $@ Private Public
  if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then
   echo
   echo "Please re-type your IP."
   unset test_ser
   continue
  fi
 elif [ "$pri_ip" = "false" ] && [ "$mode" = "nat" ]; then
  route_warn $@ Public Private
  if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then
   echo
   echo "Please re-type your IP."
   unset test_ser
   continue
  fi
 fi
}

# --- Function: Get External Socket ---
get_ext_socket () {
 for PROTO in TCP UDP; do
  unset test_ser
  until [ "$test_ser" = "ok" ]; do
   unset ser_names
   echo -n "Services for $PROTO: "
   read  ser_names
   test -z "$ser_names" && continue 2
   test_name="$test_name ser_names"
   chk_ser_name $ser_names
  done
  for SER_PORT in $port_nu; do
   EXT_SOCKET="$EXT_SOCKET $PROTO $EXT_IP $SER_PORT"
  done
 done
}

# --- Function: External IP warning ---
ext_warn () {
 if [ -z "$(echo $ALL_EXT_IP | grep $SER_IP)" ]; then
  unset YN
  until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
   || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
   echo
   echo -n "WARNING: the IP($SER_IP) is not currently "
   echo "configured for external connection."
   echo "INFO: following external IP(s) are available on local machine: " 
   echo "      $ALL_EXT_IP"
   echo -n "Are you sure? (Y/n): "
   read YN
   test -z "$YN" && YN="y"
  done
  if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then 
   echo "Please re-type the socket."
   get_sock
  fi
 fi
 unset req_ext_warn
}

# --- Function: Get Socket Info ---
get_sock () {
 unset ip_check
 unset test_ser
 until [ "$ip_check" = "ok" ] && [ "$test_ser" = "ok" ]; do
  unset sock_name
  until [ "$sock_name" = "ok" ]; do
   echo -n "Service Socket: "
   read PROTO SER_IP SER_PORT EXTRA
   if [ "$PROTO" = "TCP" ] || [ "$PROTO" = "tcp" ] \
    || [ "$PROTO" = "UDP" ] || [ "$PROTO" = "udp" ]; then
    if [ -z "$PROTO" ] || [ -z "$SER_IP" ] || [ -z "$SER_PORT" ] \
     || [ -n "$EXTRA" ]; then
     echo
     echo -n "ERROR: invalid socket. "
     echo -n "it must be TCP or UDP, followed by one IP and "
     echo -n "one service name(or port number), "
     echo "and separated by white space."
    else
     sock_name="ok"
    fi
   else
    echo
    echo "ERROR: the first field must be either TCP or UDP."
   fi
  done
  chk_ip $SER_IP
  chk_ser_name $SER_PORT
  SER_PORT="$(echo $port_nu)"
 done
 test "$req_ext_warn" = "true" && ext_warn
 TEST_SOCKET="$PROTO $SER_IP $SER_PORT"
}

# --- Function: Service Sockets ---
get_ser_socket () {
  echo
  echo "Do you have more than one interface to provide services?"
  echo "It is most likely that you are running services on IP aliases, "
  echo -n "or you want to pass some(not all) of the services to a "
  echo "internal/dmz network."
  unset YN
  until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
 echo -n "Yes or No? (y/N): "
 read YN
 test -z "$YN" && YN="n"
  done
  if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then
 echo
 echo "What kind of services would you like to run on the interface?"
 echo -n "Note: the services you are giving must be defined in file "
 echo "$SERVICES_FILE."
 echo "Please specify the services for the TCP and UDP protocol separately."
 echo "NOTE: type in one line, eg: 'www ftp pop-3 smtp' and so on..."
 get_ext_socket
 test -z "$test_name" && {
  echo
  echo -n "ERROR: You must enter at least one service, "
  echo "otherwise press CTRL+C to abort."
  unset test_name
  get_ext_socket
 }
 if [ "$mode" = "route" ] || [ "$mode" = "nat" ]; then
  echo
  echo -n "You are selecting '$mode' option, which means "
  echo "that services are ran in the internal/dmz network."
  echo "Please give the IP of the internal/dmz server."
  until [ "$ip_check" = "ok" ]; do
   unset int_ser_ip
   until [ -n "$int_ser_ip" ]; do
    echo -n "Server IP: "
    read int_ser_ip
   done
   chk_ip $int_ser_ip
   route_warn_dtm $int_ser_ip
  done
  INT_SOCKET_TYPE="single" 
  get_single_ext () {
   while [ -n "$1" ]; do
    INT_SOCKET="$INT_SOCKET $1 $int_ser_ip $3"
    shift 3
   done
  }
  get_single_int () {
   while [ -n "$1" ]; do
    EXT_NAT_SOCKET="$EXT_NAT_SOCKET $1 $2 $3 $int_ser_ip"
    shift 3
   done
  }
  get_single_ext $EXT_SOCKET
  get_single_int $EXT_SOCKET
  unset EXT_SOCKET
 fi  
  else
 echo
 echo "You must specify every individual services socket and it's protocol."
 echo "Note: a socket is a routeable Public IP and the service name, "
 echo "Please enter in this format: "
 echo "  "
 echo "For example: TCP 1.2.3.4 www"
 get_all_ext_if () {
  ALL_EXT_IP=$(ifconfig | grep "$EXT_IF" -A 1 \
   | awk '/inet/ {print $2}' | sed -e 's/.*://')
  if [ "$mode" != "route" ]; then
   echo "INFO: following external IP(s) are available on local machine: " 
   echo "      $ALL_EXT_IP"
  fi
 } 
 get_fwd_mode () {
  DO_SOCKET="$PROTO $SER_IP $SER_PORT"
  echo
  echo "How would you like to do with this socket($DO_SOCKET)?"
  echo " * LOCAL: run it locally on nat server itself.  (press L)"
  echo " * REMOTE: run it remotely on a internal/dmz server. (press R)"
  unset fwd_mode
  until [ "$fwd_mode" = "l" ] || [ "$fwd_mode" = "L" ] \
   || [ "$fwd_mode" = "r" ] || [ "$fwd_mode" = "R" ]; do
   echo -n "Your choice? (default R): "
   read fwd_mode
   test -z "$fwd_mode" && fwd_mode="R"
  done
 }
 get_dmz_socket () {
  unset test_ser
  until [ "$test_ser" = "ok" ]; do
   echo
   echo "What is the Internal/DMZ socket(for $DO_SOCKET)?"
   req_ext_warn="false"
   get_sock
   route_warn_dtm
  done
 }
 unset MORE_SOCKET
 until [ "$MORE_SOCKET" = "n" ] || [ "$MORE_SOCKET" = "N" ]; do
  run_mode () {
   case $mode in
    server)
     get_all_ext_if
     req_ext_warn="true"
     get_sock
     chk_ser_ip $SER_IP
     test "$test_ser_ip" = "ok" || continue
     EXT_SOCKET="$EXT_SOCKET $TEST_SOCKET"
     ;;
    route)
     get_sock
     get_fwd_mode
     if [ "$fwd_mode" = "r" ] || [ "$fwd_mode" = "R" ]; then
      route_warn_dtm $SER_IP
      INT_SOCKET="$INT_SOCKET $TEST_SOCKET"
     else
      get_all_ext_if
      ext_warn
      EXT_SOCKET="$EXT_SOCKET $TEST_SOCKET"
     fi
     ;;
    nat)
     get_all_ext_if
     req_ext_warn="true"
     get_sock
     TEST_NAT_SOCKET=$TEST_SOCKET
     get_fwd_mode
     if [ "$fwd_mode" = "r" ] || [ "$fwd_mode" = "R" ]; then
      get_dmz_socket
      EXT_NAT_SOCKET="$EXT_NAT_SOCKET $TEST_NAT_SOCKET $SER_IP:$SER_PORT"
      INT_SOCKET="$INT_SOCKET $TEST_SOCKET"
     else
      EXT_SOCKET="$EXT_SOCKET $TEST_SOCKET"
     fi
     ;;
   esac
  }
  run_mode
  unset MORE_SOCKET
  until [ "$MORE_SOCKET" = "y" ] || [ "$MORE_SOCKET" = "Y" ] \
   || [ "$MORE_SOCKET" = "n" ] || [ "$MORE_SOCKET" = "N" ]; do
   echo
   echo -n 'Do you want to setup another socket? (y/N): '
   read MORE_SOCKET
   test -z "$MORE_SOCKET" && MORE_SOCKET="N"
  done
 done
  fi
}

# --- Function: Show routing ---
get_route () {
 ln=$(/sbin/route -n | awk '{print $1}' | grep -n "\<0.0.0.0\>" \
  | head -n 1 | awk -F ":" '{print $1}')
 test -z "$ln" && {
  echo "There is no default gateway present for this moment."
  return 0
 }
 dfgw=$(/sbin/route -n | head -n $ln | tail -n 1 |awk -F ' ' '{print $2}')
 dfgwdev=$(/sbin/route -n | head -n "$ln" | tail -n 1 | awk -F ' ' '{print $8}')
}

# --- Function: Default route ---
d_route () {
  get_route
  test "$dfgwdev" = "$EXT_IF" || {
 echo
 if [ -z "$dfgw" ]; then
  echo "ATTENTION: Default gateway is not set."
 else
  echo -n "ATTENTION: Default gateway($dfgw) is not set on "
  echo "the External interface $EXT_IF."
 fi
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
  echo "Do you want to make default route to $EXT_IF?"
  echo "WARNING: This option may effect your current network environment."
  echo -n "Yes or No? (Y/n):"
  read YN
  test -z "$YN" && YN="y"
 done
 if [ $YN = "y" ] || [ $YN = "Y" ]; then
  D_GW=$(echo $EXT_IF | grep ppp)
  if [ -n "$D_GW" ]; then
   /sbin/route add default dev $EXT_IF
  else
     unset ip_check
   until [ "$ip_check" = "ok" ] && [ "$gwip" = "ok" ]; do
    echo
    echo -n "Please give the gateway IP (press C to cancel): "
    read GW_IP
    if [ "$GW_IP" = "c" ] || [ "$GW_IP" = "C" ]; then
     echo "Gateway is not changed!"
     return 1
    fi
    chk_ip $GW_IP
    test "$ip_check" = "ok" || continue
    IP=$GW_IP
    MASK=$EXT_MASK
          get_net $(echo $MASK | sed -e 's/\./\ /g')
    if [ "$NET/$EXT_MASK" = "$EXT_NET" ]; then
     /sbin/route add default gw $GW_IP dev $EXT_IF
     gwip="ok"
    else
     echo "ERROR: the gateway IP($GW_IP) you gave seemed bad."
     echo "Please make sure it is within the subnet of $EXT_NET."
    fi
   done
  fi
  get_route
 else
  echo "Default route is not changed."
 fi
  }
}

# --- Function: Transparent Proxy ---
t_proxy () {
 $RC_SQUID status 2>/dev/null | grep pid &>/dev/null && {
     INT_IP=$(ifconfig | grep $INT_IF -A 1 \
         | awk '/inet/ {print $2}' | sed -e 's/.*://')
     test -n "$INT_IP" && {
      echo "Enabling transparent proxy...."
      $IPT_AP -t nat -A PREROUTING -d $INT_IP -i $INT_IF \
       -p tcp -m tcp --dport 80 -j ACCEPT
      $IPT_AP -t nat -A PREROUTING -i $INT_IF -p tcp -m tcp \
        --dport 80 -j REDIRECT --to-ports 3128
     }
 }
}


# --- Function: Firewall status ---
fw_stat () { 
 test -w $IPT_TMP_DIR && {
  echo ""  >| $IPT_TMP_FILE
  echo "Current Network Status:" >> $IPT_TMP_FILE
  echo "------------------------" >> $IPT_TMP_FILE
  test "$set_EXT" = "true" && {
   cat <> $IPT_TMP_FILE
External:
  ip: $EXT_IP
  interface: $EXT_IF
  network: $EXT_NET
FW_END1
  }
  test "$set_INT" = "true" && {
   cat <> $IPT_TMP_FILE
Internal:
  ip: $INT_IP
  interface: $INT_IF
  network: $INT_NET
FW_END2
  }
  test "$set_DMZ" = "true" && {
   cat <> $IPT_TMP_FILE
DMZ net:
  ip: $DMZ_IP
  interface: $DMZ_IF
  network: $DMZ_NET
FW_END3
  }
  test -z "$dfgw" || {
   echo -n "Default gateway is now set to '$dfgw' " >> $IPT_TMP_FILE
   echo "via '$dfgwdev'." >> $IPT_TMP_FILE
  }
  echo "" >> $IPT_TMP_FILE
  echo -n "The IP_FORWARD is " >> $IPT_TMP_FILE
  if [ "$(cat /proc/sys/net/ipv4/ip_forward)" = "0" ]; then
   echo -n "OFF" >> $IPT_TMP_FILE
   ipfd="false"
  else
   echo -n "ON" >> $IPT_TMP_FILE
   ipfd="true"
  fi
  echo "." >> $IPT_TMP_FILE
  cat $IPT_TMP_FILE
 }
}

# --- Function: load modules ---
ld_mod () {
 echo "Loading modules..."
 modprobe ip_tables &>/dev/null || {
  echo -n "$SCRIPT_NAME: loading ip_tables module failure."
  echo " Please Fix it!"
  exit 3
 }
 for file in /lib/modules/$(uname -r)/kernel/net/ipv4/netfilter/ip_conntrack_*.o
 do
  module=$(basename $file)
  modprobe ${module%.*} &>/dev/null
 done
 for file in /lib/modules/$(uname -r)/kernel/net/ipv4/netfilter/ip_nat_*.o
 do
  module=$(basename $file)
  modprobe ${module%.*} &>/dev/null
 done
}

# --- Function: Flush Iptables ---
flush_IPT () {
 echo "Flushing old rules..."
 $IPT_AP -F -t filter
 $IPT_AP -X -t filter
 $IPT_AP -Z -t filter
 $IPT_AP -F -t nat
 $IPT_AP -X -t nat
 $IPT_AP -Z -t nat
}

# --- Function: Reset Iptables ---
reset_IPT () {
 echo "Reseting iptables..."
 echo "Setting policies to ACCEPT..."
 $IPT_AP -P INPUT ACCEPT
 $IPT_AP -P OUTPUT ACCEPT
 $IPT_AP -P FORWARD ACCEPT
 $IPT_AP -t nat -P PREROUTING ACCEPT
 $IPT_AP -t nat -P POSTROUTING ACCEPT
 $IPT_AP -t nat -P OUTPUT ACCEPT
 flush_IPT
 echo "Done: iptables is set to ACCEPT to all."
}

# --- Function: Create ICMP filter ---
run_icmp () {
 echo "Creating icmpfilter chain..."
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
  echo -n "Do you allow PING & TRACEROUTE from outside? (y/N): "
  read YN
  test -z "$YN" && YN="n"
 done
 if [ "$YN" = "y" ] || [ "$YN" = "Y" ]; then
  DENIED_ICMP=$(echo $DENIED_ICMP | sed s/8//)
  ALLOWED_ICMP="$ALLOWED_ICMP 8"
 fi
 $IPT_AP -N icmpfilter
 test -n "$DENIED_ICMP" && {
  for TYPE in $DENIED_ICMP; do
   $IPT_AP -A icmpfilter -i $EXT_IF -p icmp \
    --icmp-type $TYPE -j DROP
  done
 }
 for TYPE in $ALLOWED_ICMP; do
  $IPT_AP -A icmpfilter -p icmp \
   --icmp-type $TYPE -j ACCEPT
 done
}

# --- Function: Create BLOCK chain ---
run_block () {
 echo "Creating block chain..."
 $IPT_AP -N block
 $IPT_AP -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
}

# --- Function: Run filter ---
run_filter () {
 $IPT_AP -A INPUT -j block
 $IPT_AP -A INPUT -j icmpfilter
 $IPT_AP -A FORWARD -j block
 $IPT_AP -A FORWARD -j icmpfilter
}
run_filter_end () {
 $IPT_AP -A INPUT -m state --state NEW,INVALID -i $EXT_IF -j DROP
 $IPT_AP -A FORWARD -m state --state NEW,INVALID -i $EXT_IF -j DROP
 echo "Resetting INPUT and FORWARD policies to DROP..."
 $IPT_AP -P INPUT DROP
 $IPT_AP -P FORWARD DROP
}

# --- Function: Run auth setup ---
run_auth () {
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
  test "$auth_warn" = "no" || {
   echo
   echo -n "NOTE: more and more services are now requiring "
   echo "authentication(ident)."
   echo -n "It may delay such connection if you don't provice "
   echo "auth services."
   echo -n "Do you want to allow auth request from outside? (Y/n): "
   read YN
  }
  test -z "$YN" && YN="y"
 done
 if [ "$YN" = "y" ] || [ "$YN" = "Y" ]; then
  $IPT_AP -I block -p tcp --dport 113 -j ACCEPT
 fi
}

# --- Function: set environment ---
set_evn () {
 echo
 echo "NOTE: you can stop the script by press 'CTRL' + 'C' at any time."
 echo
 get_nic
 test "$ser_req" = "true" && get_ser_socket
 rm_ipchains
 ld_mod
 reset_IPT
 run_block
 run_icmp
 echo
 echo "Turning on IP_FORWARD..."
 echo 1 > /proc/sys/net/ipv4/ip_forward
 echo "Turning on anti-spoofing..."
 for file in /proc/sys/net/ipv4/conf/*/rp_filter; do
  echo "1" > $file
 done
 echo "Allow local network..."
 $IPT_AP -A INPUT -i lo -j ACCEPT
 $IPT_AP -A OUTPUT -o lo -j ACCEPT
 $IPT_AP -A INPUT -i $INT_IF -j ACCEPT
 $IPT_AP -A OUTPUT -o $INT_IF -j ACCEPT
 $IPT_AP -A FORWARD -i $INT_IF -j ACCEPT
 echo "Masquerading internal traffic..."
 $IPT_AP -t nat -A POSTROUTING -s $INT_NET -o $EXT_IF -j MASQUERADE
 test "$mode" = "nat" && {
  echo "Fix the icmp host redirect problem..."
  $IPT_AP -t nat -A POSTROUTING -s $INT_NET -d $INT_NET \
   -p tcp -j SNAT --to $INT_IP
  test "$set_DMZ" = "true" && {
   $IPT_AP -t nat -A POSTROUTING -s $DMZ_NET -d $DMZ_NET \
    -p tcp -j SNAT --to $DMZ_IP
  }
 }
}

# --- Function: Allow DMZ ---
allow_dmz () {
 if [ -n "$DMZ_IF" ] && [ -n "$DMZ_NET" ]; then
  echo "Allow DMZ network..."
  DENIED_ICMP=$(echo $DENIED_ICMP | sed s/8//)
  ALLOWED_ICMP="$ALLOWED_ICMP 8"
  unset YN
  until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
   || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
   echo "Do you allow DMZ to connect back to Firewall? (y/N)"
   read YN
   test -z "$YN" && YN="n"
  done
  if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then
   $IPT_AP -A INPUT -i $DMZ_IF -m state --state ! NEW -j ACCEPT
  else
   $IPT_AP -A INPUT -i $DMZ_IF -j ACCEPT
   
  fi
  $IPT_AP -A OUTPUT -o $DMZ_IF -j ACCEPT
  $IPT_AP -A FORWARD -i $DMZ_IF -d ! $INT_NET -j ACCEPT
  echo "Masquerading DMZ traffic..."
  $IPT_AP -t nat -A POSTROUTING -s $DMZ_NET -o $EXT_IF -j MASQUERADE
 fi
}

# --- Function: Fix ICMP for Internal/DMZ servers ---
i_ser_icmp () {
 for NAT_SER in $@; do
  $IPT_AP -A INPUT -p icmp -s $NAT_SER -j ACCEPT
  $IPT_AP -A FORWARD -p icmp -s $NAT_SER -j ACCEPT
  $IPT_AP -A FORWARD -p icmp -d $NAT_SER -j ACCEPT
  $IPT_AP -t nat -A POSTROUTING -p icmp -s $NAT_SER -j MASQUERADE
 done
}

# --- Function: Service chain ---
service_chain () {
 while [ -n "$1" ]; do
  $IPT_AP -A INPUT -i $EXT_IF -p $1 -d $2 --dport $3 -j ACCEPT
  shift 3
 done
}

# --- Function: NAT chain ---
nat_chain () {
 while [ -n "$1" ]; do
 $IPT_AP -t nat -A PREROUTING -p $1 -d $2 --dport $3 -j DNAT --to $4
 echo "$int_nat_proto " | grep "$1 " &>/dev/null \
  || int_nat_proto="$int_nat_proto $1"
 echo "$int_nat_ser " | grep "${4%:*} " &>/dev/null \
  || int_nat_ser="$int_nat_ser ${4%:*}"
 shift 4
 done
 for NAT_PROTO in $int_nat_proto; do
  for NAT_SER in $int_nat_ser; do
   $IPT_AP -t nat -A POSTROUTING -p $NAT_PROTO -s $NAT_SER -j MASQUERADE
  done
 done
}

# --- Function:  Forward chain ---
int_fwd_chain () {
 while [ -n "$1" ]; do
  $IPT_AP -A FORWARD -p $1 -d $2 --dport $3 -j ACCEPT
  $IPT_AP -A FORWARD -p $1 -s $2 --sport $3 -j ACCEPT
  echo "$int_ser " | grep "$2 " &>/dev/null \
   || int_ser="$int_ser $2"
  shift 3
 done
 i_ser_icmp $int_ser
}

# --- Fuction: Run Server
run_server () {
 echo "Entering Server mode..."
 run_filter
 allow_dmz
 echo "$EXT_SOCKET " | grep "[^\.]113 " &>/dev/null || run_auth
 test -n "$EXT_SOCKET" && {
  service_chain $EXT_SOCKET
 }
 t_proxy
 run_filter_end
}

# --- Function: Run NAT ---
run_nat () {
 echo "Entering nat mode..."
 run_filter
 chk_auth1=$(echo "$EXT_SOCKET " | grep "[^\.]113 ")
 chk_auth2=$(echo "$EXT_NAT_SOCKET " | grep "[^\.]113 ")
 if [ -n "$chk_auth1" ] || [ -n "$chk_auth2" ]; then
  auth_warn="no"
 fi
 if [ -z "$chk_auth1" ]; then
  run_auth
 elif [ -z "$chk_auth1" ]; then
  run_auth
 fi
 test -n "$INT_SOCKET" && {
  int_fwd_chain $INT_SOCKET
 }
 test -n "$EXT_SOCKET" && {
  service_chain $EXT_SOCKET
 }
 test -n "$EXT_NAT_SOCKET" && {
  nat_chain $EXT_NAT_SOCKET
 }
 t_proxy
 run_filter_end
}


# --- Function: Run routing ---
run_route () {
 echo "Entering route mode..."
 run_filter
 if [ "$INT_SOCKET_TYPE" = "single" ]; then
  chk_auth1=$(echo "$port_nu " | grep "113 ")
 else
  chk_auth1=$(echo "$EXT_SOCKET " | grep "[^\.]113 ")
  chk_auth2=$(echo "$INT_SOCKET " | grep "[^\.]113 ")
 fi
 if [ -z "$chk_auth1" ] || [ -z "$chk_auth2" ]; then
  if [ -n "$chk_auth1" ] || [ -n "$chk_auth2" ]; then
   auth_warn="no"
  fi
  run_auth
 fi
 test -n "$INT_SOCKET" && {
  int_fwd_chain $INT_SOCKET
 }
 test -n "$EXT_SOCKET" && {
  service_chain $EXT_SOCKET
 }
 t_proxy
 run_filter_end
}

# --- Starting script ---

# --- Determine fw option ---
if [ -z "$1" ]; then
  echo "$USAGE"
  exit 4

else

  case "$1" in

  help)
 cat <


 ############################################################################
 ## WARNING: Please do NOT run this script unless you had studied your     ##
 ## network environment. Since this script is still under development, it  ##
 ## may be not suitable for your circumstance.                             ##
 ## It is running on your OWN risk if you decide to run this script anyway.##
 ############################################################################

Script name: $SCRIPT_NAME
Purpose: To configure iptables on Linux (kernel 2.4.x).
Version: $VERSION
Date:  $DATE

Caveat: 
 1, The script supports Ehternet and/or PPP only.
 2, You have to configure the subnetting/routing on your own.
 3, It allows maximun 3 network interfaces(including ppp).
 4, It allows only 1 external interface, no multi-path supported.
  (You can however use IP aliases to provide mutlti-services.)
 5, Do NOT run this script if you are doing one of the following:
  * Advanced Routing
  * Traffic Shaping
  * IP Virtual Server
  * Masqueraded VPN
  * Other advanced packet management
 6, The script may creates/modifies following files on your system:
  * /etc/sysconfig/iptables
  * /etc/sysconfig/iptables.*
  * /etc/rc.d/rc.local
  * /etc/rc.d/rc*.d/*ipchains
  * /etc/rc.d/rc*.d/*iptables
  * /var/tmp/ipt-save.*
  * /var/tmp/ipt_config.tmp
  * /var/tmp/ipt_config1.tmp
  * /var/tmp/ipt_config.conf
  You must have write permission to above files, and please make
  your own backup as needed.
 7, The script needs $BOOT_LOG for some determination. You
  must fix the \$BOOT_LOG variable if the file is unreachable.
 8, The iptables must be configured as modules. The script doesn't
  support iptables that is built-in within the kernel.
 9, This script has been tested on RedHat 7.1(kernel 2.4.x) only.
  There is no guarantee to work on any other systems.

$USAGE

[OPTIONS]

help:
 Displays this help manual.

masq:
 Forms as a gateway for your LAN. It simply masquerades your internal
 network behide ONE single IP to the outside world. Note: no service
 requests will be accepted from outside with this option.

server:
 Same as the 'msaq' option, but also provide some pre-defined services
 to outside world.

nat:
 Pre-defined services will be NATed (Network Address Translation) to
 other servers in an internal/dmz network, which is masqueraded behide
 the NAT gateway.

 All servers that running in the internal/dmz network are assigned with
 PRIVATE IPs. When a service-request hits the NAT server, it is passed
 to the real corresponding internal/dmz server. Packets are modified
 before the forwarding.

 You could, however, keep some of services running on the NAT server
 itself, based on your selection.

route:
 Most services are running on the internal/dmz servers with PUBLIC IPs,
 which means it's routeable between the servers and the outside networks.
 Packages are simply passed to the real servers directly without any
 modification.

 Same as the 'nat' option, you can keep some of services running on the
 gateway server itself, based on your selection.

reset:
 Cleans up all current rules and policies, and restore the original
 settings to the firewall, that is, it will be ACCEPTing everything.

status:
 Lists the current active firewall rules and the network status.
 NOTE: this option will consult the time stamp of $BOOT_LOG to
  determine whether the information is obsolete.

save:
 Saves the rules to a file(usually will be $IPT_SAVE_FILE), so
 that you can get back the settings by running the 'restore' option.

 You also have the option to launch the iptalbes and the related kernal
 modules at boot time.
 NOTE: it will change your run-level scripts(/etc/rc.d/rc*.d &
  /etc/rc.d/rc.local) and the default iptalbes configuration.
  Be sure you have enough permissions to do so.

restore:
 Restore the previous saved rules and make them activated.
 WARNING: all current rules will be lost unless you have another saving
  copy for them.

=======================================================================
Please email to $MAINTAINER for bugs and comments.

END
 exit 0
 ;;

  reset) 
 rm_ipchains
 ld_mod
 echo
 reset_IPT
 get_route
 fw_stat
   test "$ipfd" = "true" && {
  unset DO_IPFW
  until [ "$DO_IPFW" = "y" ] || [ "$DO_IPFW" = "Y" ] \
   || [ "$DO_IPFW" = "n" ] || [ "$DO_IPFW" = "N" ]; do {
     echo -n "Do you want to turn it OFF? (y/N): "
   read DO_IPFW
   test -z "$DO_IPFW" && DO_IPFW="n"
  }
  done
  if [ "$DO_IPFW" = "y" ] || [ "$DO_IPFW" = "Y" ]; then
   echo "0" > /proc/sys/net/ipv4/ip_forward
   echo "Done: IP-Foreard is truned off."
  fi
 }
   test -z "$dfgw" || {
  unset YN
  until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
   || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do {
   echo
     echo "Default gateway is now set to '$dfgw' via '$dfgwdev'."
   echo -n "Do you want ro remove this setting? (y/N): "
   read YN
   test -z "$YN" && YN="n"
  }
  done
  if [ "$YN" = "y" ] || [ "$YN" = "Y" ]; then
   /sbin/route del default dev $dfgwdev
   echo "Please run 'route -n' to confirm your routing."
  fi
 }
 echo
 exit 0
 ;;
 
  masq) 
 mode="masq"
 get_route
 set_evn
 d_route
 ld_mod
 run_auth
 echo "Entering MASQ mode..."
 run_filter
 allow_dmz
 t_proxy
 run_filter_end
 fw_stat
 echo
 exit 0
 ;;

  server)
 mode="server"
 ser_req="true"
 get_route
 set_evn
 d_route
 run_server
 allow_dmz
 fw_stat
 echo
 exit 0
 ;;
 
  nat)
 mode="nat"
 ser_req="true"
 get_route
 set_evn
 d_route
 run_nat
 allow_dmz
 fw_stat
 echo
 exit 0
 ;;
 
  route)
 mode="route"
 ser_req="true"
 get_route
 set_evn
 d_route
 run_route
 allow_dmz
 fw_stat
 echo
 exit 0
 ;;
 
  status)
 rm_ipchains
 ld_mod
 clear
 if [ -w $IPT_TMP_DIR ]; then
  echo "" > $IPT_TMP_FILE1
  test -e $BOOT_LOG || {
   echo
   echo "ERROR: file $BOOT_LOG is not existing."
   echo " It is needed for ensuring the newest information."
   echo
  }
  test $IPT_TMP_FILE -nt $BOOT_LOG && cat $IPT_TMP_FILE >> $IPT_TMP_FILE1
  echo "" >> $IPT_TMP_FILE1
  echo "Current Iptables Status:" >> $IPT_TMP_FILE1
  echo "------------------------" >> $IPT_TMP_FILE1
  $IPT_AP -L -n >> $IPT_TMP_FILE1
  $IPT_AP -t nat -L -n >> $IPT_TMP_FILE1
  test -z $IPT_SAVE_AP || {
   echo "" >> $IPT_TMP_FILE1
   echo "Current Iptables Rules:" >> $IPT_TMP_FILE1
   echo "------------------------" >> $IPT_TMP_FILE1
   $IPT_SAVE_AP >> $IPT_TMP_FILE1
  }
  cat $IPT_TMP_FILE1 |more
  echo 
 else
  echo
  echo "ERROR: you don't have write permission to $IPT_TMP_DIR."
  echo "Plese fix it."
  exit 5
 fi
 exit 0
 ;;

  save)
 echo
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
  echo -n "Would you like to get the settings back automatically "
  echo -n "while boot up? (Y/n): "
  read YN
  test -z "$YN" && YN="y"
 done
 if [ "$YN" = "y" ] || [ "$YN" = "Y" ]; then
  if [ -w ${IPT_SAVE_FILE%/*} ] ; then
   if [ -f $IPT_SAVE_FILE ]; then
    if [ -w $IPT_SAVE_FILE ]; then
     OLD_FILE=$IPT_SAVE_FILE.$(date +%y%m%d%M%S)
     mv $IPT_SAVE_FILE $OLD_FILE
     echo "The old file was saved as $OLD_FILE."
    else
     echo
     echo  -n "ERROR: you do NOT have write permission to "
     echo "$IPT_SAVE_FILE. Please fix it."
     echo "Exiting, nothing was changed."
     exit 6
    fi
   fi
   rm_ipchains
   ld_mod
   $IPT_SAVE_AP > $IPT_SAVE_FILE || {
    echo
    echo "ERROR: can NOT save settings. Please fix it."
    mv $OLD_FILE $IPT_SAVE_FILE
    echo "Exiting..."
    exit 6
   }
   /sbin/chkconfig --add iptables
   /sbin/chkconfig iptables on
   /sbin/chkconfig --del ipchains
cat < $IPT_TMP_RUN
#!/bin/bash
depmod -a &>/dev/null
modprobe ip_conntrack_ftp &>/dev/null
for file in /lib/modules/\$(uname -r)/kernel/net/ipv4/netfilter/ip_nat_*.o
do
 module=\$(basename \$file)
 modprobe \${module%.*} &>/dev/null
done
echo "1" > /proc/sys/net/ipv4/ip_forward
RUN_END
   grep "added by $SCRIPT_NAME" $RC_LOCAL &>/dev/null || {
cat <> $RC_LOCAL
## --- lines added by $SCRIPT_NAME for iptables ----
[ -f $IPT_TMP_RUN ] && sh $IPT_TMP_RUN
## --- ##
RC_END
   }
  else
   echo
   echo "ERROR: you do NOT have write permission to ${IPT_SAVE_FILE%/*}."
   echo "Please fix it."
   echo "Exiting, nothing was changed."
   exit 6
  fi
 else
  if [ -w $IPT_TMP_DIR ]; then
   [ -f $IPT_TMP_RUN ] && rm -f $IPT_TMP_RUN
   IPT_SAVE_FILE=$IPT_TMP_DIR/ipt-save.$(date +%y%m%d%M%S)
   rm_ipchains
   ld_mod
   $IPT_SAVE_AP > $IPT_SAVE_FILE || {
    echo
    echo "ERROR: can NOT save settings. Please fix it."
    echo "Exiting..."
    exit 6
   }
  else
   echo
   echo -n "ERROR: you do NOT have write permission to $IPT_TMP_DIR, "
   echo "or it is not existing. Please fix it."
   echo "Exiting, nothing was changed."
   exit 6
  fi
 fi
 echo "IPT_SAVE_FILE=$IPT_SAVE_FILE" >> $IPT_TMP_FILE1
 echo "The current iptables rules are saved at '$IPT_SAVE_FILE'."
 echo "IPT_SAVE_FILE=$IPT_SAVE_FILE" > $IPT_TMP_CONF
 echo
 ;;

  restore)
 rm_ipchains
 ld_mod
 echo
 echo "Please give the path to the saved iptables rules file."
 test $IPT_TMP_CONF -nt $BOOT_LOG && . $IPT_TMP_CONF
 if [ -f $IPT_SAVE_FILE ]; then
  echo "INFO: the default path is '$IPT_SAVE_FILE', press ENTER to accept."
 fi
 until [ "$test_path" = "ok" ]; do
  echo -n "Path: "
  read ipt_save_file
  test -z "$ipt_save_file" && {
   test -f $IPT_SAVE_FILE && ipt_save_file=$IPT_SAVE_FILE
  }
  if [ -f $ipt_save_file ]; then
   test_path="ok"
  else
   echo
   echo "ERROR: the file($ipt_save_file) is not existing."
   echo "Please re-type the path, or press CTRL+C to abort."
  fi
 done
 unset YN
 until [ "$YN" = "y" ] || [ "$YN" = "Y" ] \
  || [ "$YN" = "n" ] || [ "$YN" = "N" ]; do
  echo
  echo -n "WARNING: All current iptalbes rules will be lost "
  echo "unless you've saved them somewhere else."
  echo -n "Are you sure? (y/N): "
  read YN
  test -z "$YN" && YN="n"
 done
 if [ "$YN" = "n" ] || [ "$YN" = "N" ]; then
  echo "Nothing changed. Exiting..."
 else
  flush_IPT
  echo -n "Restoring previously saved iptable rules... "
  $IPT_RESTORE_AP < $IPT_SAVE_FILE
  echo "Done!"
 fi
 echo
 ;;

  *)
 echo
 echo -n "$SCRIPT_NAME: invalid option: '$1'. "
 echo "Please run '$SCRIPT_NAME help' for more information."
 echo $USAGE
 echo
 exit 1
 ;;

  esac

fi
exit 0

 

阅读(1663) | 评论(0) | 转发(0) |
0

上一篇:iptables例子1

下一篇:sshd 中文手册

给主人留下些什么吧!~~