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 <
External:
ip: $EXT_IP
interface: $EXT_IF
network: $EXT_NET
FW_END1
}
test "$set_INT" = "true" && {
cat <
Internal:
ip: $INT_IP
interface: $INT_IF
network: $INT_NET
FW_END2
}
test "$set_DMZ" = "true" && {
cat <
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) Script name: $SCRIPT_NAME Caveat: $USAGE [OPTIONS] help: masq: server: nat: All servers that running in the internal/dmz network are assigned with You could, however, keep some of services running on the NAT server route: Same as the 'nat' option, you can keep some of services running on the reset: status: save: You also have the option to launch the iptalbes and the related kernal restore: ======================================================================= END reset) server) save) restore) *) esac fi
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.##
############################################################################
Purpose: To configure iptables on Linux (kernel 2.4.x).
Version: $VERSION
Date: $DATE
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.
Displays this help manual.
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.
Same as the 'msaq' option, but also provide some pre-defined services
to outside world.
Pre-defined services will be NATed (Network Address Translation) to
other servers in an internal/dmz network, which is masqueraded behide
the NAT gateway.
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.
itself, based on your selection.
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.
gateway server itself, based on your selection.
Cleans up all current rules and policies, and restore the original
settings to the firewall, that is, it will be ACCEPTing everything.
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.
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.
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 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.
exit 0
;;
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
;;
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
;;
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 <
#!/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 <
## --- 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
;;
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
;;
exit 0