#!/bin/bash # # A simple script for Firewall, used in Linux iptables Modules(kernel 2.4.x .&. 2.6.X ). # Update Date: 2010/02/17 支援各種 Linux # # Copyright (C) 2003 by CHENG, Liang-Hsing (jls@mail.jls.idv.tw & jls@acfs.tw). # Website: http://www.jls.idv.tw/ # Website: http://www.acfs.tw/ # # 以下Script如有任何錯誤或您有更好的設定 # 敬請您 E-Mail 來指正 謝謝 ! # PATH=/sbin:/usr/sbin:/bin:/usr/bin ########################################################################### ################## 此段請依個人需要自行設定 ############################### ########################################################################### ########## 設定內外網卡,請自行設定,要是用撥接請在外部網卡設ppp0 ##### 外部網卡 EXT_IF="ppp0" ##### 要是只有一張網卡就設 INT_IF="eth0" 吧 ##### 內部網卡 INT_IF="eth1" ##### 想要對外開放的PORT (依個人需要,增加或減少) OPEN_PORT="20 21 22 25 53 80 110 113 123 143 443 3128 10000 12000 6667 7000" ##### NAT 內部IP (依個人需要,如無需要請設為 NAT_IP="" ) NAT_IP="" if [ "$NAT_IP" != "" ]; then ##### 想要對 NAT 開放的 PORT (依個人需要,增加或減少) NAT_PORT="20 21 22 25 53 80 110 113 143 443 3128 10000 12000 " fi if [ "$INT_IF" == "eth1" ]; then ##### 不想要對內部開放的 PORT (依個人需要,增加或減少,如無需要請設為 DROP_PORT="" ) DROP_PORT="" fi ##### 丟棄蠕蟲對80埠的請求(依個人需要,增加) #CHK_STRING="cmd.exe default.ida robots.txt scripts msadc MSADC _vti_bin _mem_bin root.exe" ##### 對於攻擊您Server的IP給予拒絕,不可設為 INPUT_IP="" ,也就是字串("")不能為空白 INPUT_IP="/etc/firewall/input_ip" ####### 只允許開放IP和MAC二個需相同才開放對外連線,不可設為 OUT_IP_MAC="" ,也就是字串("")不能為空白 ####### 當設為此種模式時以下二種方式均無效.格式為 192.168.2.170=XX:XX:XX:XX:XX:XX OUT_IP_MAC="/etc/firewall/clientout.ip.mac" ####### 只允許開放IP對外連線,不可設為 OUT_IP="" ,也就是字串("")不能為空白 OUT_IP="/etc/firewall/clientout.ip" ####### 只允許開放網卡號碼對外連線,不可設為 OUT_MAC="" ,也就是字串("")不能為空白 OUT_MAC="/etc/firewall/clientout.mac" ################################################################################# ###################### 以下如無特別需要,不需做任何修改 ########################## ################################################################################# netinfo () { IP="" MASK="" NET="" for NIC in "$@" ; do { IP=$(ifconfig $NIC |grep 'inet addr' |awk '{print $2}'|sed -e "s/addr\://") MASK=$(ifconfig $NIC |grep 'inet addr' |awk '{print $4}'|sed -e "s/Mask\://") IP1=$(echo $IP |awk -F'.' '{print $1}') if [ "$IP1" = "" ]; then echo "" echo "Warning: there is no IP found on $NIC." echo "Action is aborted." echo "Please make sure the interface is setup properly, then try again." echo "" exit 1 else IP2=$(echo $IP |awk -F'.' '{print $2}') IP3=$(echo $IP |awk -F'.' '{print $3}') IP4=$(echo $IP |awk -F'.' '{print $4}') MASK1=$(echo $MASK |awk -F'.' '{print $1}') MASK2=$(echo $MASK |awk -F'.' '{print $2}') MASK3=$(echo $MASK |awk -F'.' '{print $3}') MASK4=$(echo $MASK |awk -F'.' '{print $4}') let NET1="$IP1 & $MASK1" let NET2="$IP2 & $MASK2" let NET3="$IP3 & $MASK3" let NET4="$IP4 & $MASK4" NET="$NET1.$NET2.$NET3.$NET4" fi } done } ##### 變數設定 KVERSION="/lib/modules/$(uname -r)/kernel/net/ipv4/netfilter" HI="1024:65535" HD_DEV="hda hdb hdc hdd" ###### 外部網段 netinfo "$EXT_IF" EXT_IP="$IP" EXT_NET="$NET"/"$MASK" ####### 內部網段 netinfo "$INT_IF" INT_IP="$IP" INT_NET="$NET"/"$MASK" ####### HD Ata 66 #if [ -f "/proc/scsi/scsi" ] && [ "`cat /proc/scsi/scsi`" != "Attached devices: none" ]; then # echo "為 SCSI 介面" #else # CHK_HDPARM=$(which hdparm 2>/dev/null) # if [ -n "$CHK_HDPARM" ]; then # ######起動 HD ATA 66 # echo "啟動 HD ATA 66" # #################### # for HD in $HD_DEV; do # hdparm -d1 -c3 -k1 /dev/$HD 2>/dev/null # done # fi #fi ###### 載入相關模阻 for file in $KVERSION/ip_*.* do module=$(basename $file) modprobe ${module%%.*} &>/dev/null done for file in $KVERSION/nf_*.* do module=$(basename $file) modprobe ${module%%.*} &>/dev/null done for file in $KVERSION/ipt*.* do module=$(basename $file) modprobe ${module%%.*} &>/dev/null done ###### 關閉 ipchains CHK_IPCHAINS=$(which ipchains 2>/dev/null) CHK_IPCHAINS_M=$(lsmod | grep ipchains) if [ -n "$CHK_IPCHAINS" ] && [ -n "$CHK_IPCHAINS_M" ]; then echo "Disabling ipchains..." /etc/rc.d/init.d/ipchains stop &>/dev/null || ipchains -F &>/dev/null rmmod ipchains fi ####### 檢查 iptables 是否啟動 CHK_IPTABLES=$(which iptables 2>/dev/null) if [ -z "$CHK_IPTABLES" ]; then echo echo "$(basename $0): iptables program is not found." echo " Please install the program first." echo exit 1 fi ###### 重新設定 iptables -F iptables -X iptables -F -t filter iptables -X -t filter iptables -Z -t filter iptables -F -t nat iptables -X -t nat iptables -Z -t nat iptables -F -t mangle iptables -X -t mangle ###### 預設全部關閉 iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP ###### 將lo 的部份打開 iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT ###### 將內部的通訊打開 if [ "$INT_IF" != "$EXT_IF" ] ; then iptables -A INPUT -i $INT_IF -j ACCEPT iptables -A OUTPUT -o $INT_IF -j ACCEPT iptables -A FORWARD -i $INT_IF -j ACCEPT iptables -A FORWARD -o $INT_IF -j ACCEPT else iptables -A INPUT -s $INT_NET -j ACCEPT iptables -A OUTPUT -s $INT_NET -j ACCEPT iptables -A FORWARD -s $INT_NET -j ACCEPT fi ####### 啟動所有介面的來源 IP 查核 if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ] then for f in /proc/sys/net/ipv4/conf/*/rp_filter do echo "1" > $f done fi #### 啟動 IP 轉送 echo 1 > /proc/sys/net/ipv4/ip_forward ########## 設定核心的安全相關參數 #### 忽略發送至廣播位址的 PING 封包,以防內部電腦被當成 DDoS 攻擊的工具。 echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts #### 忽略無效或錯誤的 ICMP 封包。 echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses #### 關閉 PING 的回應 echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all #### 阻擋來源路由封包,以防止入侵者藉由偽裝的方式入侵。 echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route #### 阻擋 ICMP Redirect 封包 (路由器通知主機更改路由表的封包),以防靜態路由表被竄改。 echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects #### 禁止送出 ICMP Redirect 封包,避免內部電腦被當成入侵的工具。 echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects #### 開啟核心逆向過濾功能 (Reverse Path Filtering),以過濾不可能出現在某個網路介面的封包。 echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter #### 使用 SYN cookes 功能,防止超量攻擊。 echo 1 > /proc/sys/net/ipv4/tcp_syncookies ########## 縮短 TCP 連線的重試次數與逾時時間,以減少 DoS 攻擊的危害 echo 3 > /proc/sys/net/ipv4/tcp_retries1 echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout echo 1400 > /proc/sys/net/ipv4/tcp_keepalive_time echo 0 > /proc/sys/net/ipv4/tcp_window_scaling echo 0 > /proc/sys/net/ipv4/tcp_sack echo 0 > /proc/sys/net/ipv4/tcp_timestamps ####### 記錄所有PING的LOG iptables -A INPUT -p icmp -j LOG ####### 記錄所有Firewall的LOG # iptables -A INPUT -j LOG --log-prefix "Firewall Log " ######## 防止 Ping of Death iptables -N icmpfilter iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type echo-request -j DROP iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type echo-reply -j ACCEPT iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type destination-unreachable -j ACCEPT iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type parameter-problem -j ACCEPT iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type source-quench -j ACCEPT iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type time-exceeded -j ACCEPT iptables -A icmpfilter -i $EXT_IF -p icmp --icmp-type fragmentation-needed -j ACCEPT iptables -A INPUT -i $EXT_IF -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT iptables -A OUTPUT -m state -p icmp --state INVALID -j DROP iptables -A OUTPUT -p icmp -s $EXT_IP --icmp-type 8 -d any/0 -j ACCEPT iptables -A INPUT -p icmp -s any/0 --icmp-type 0 -d $EXT_IP -j ACCEPT ######## 過瀘 iptables -N block iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A block -m state --state NEW ! -i $EXT_IF -j ACCEPT iptables -A INPUT -j icmpfilter iptables -A INPUT -j block iptables -A FORWARD -j icmpfilter iptables -A FORWARD -j block ######## 防止 sync flood 攻擊的設定 iptables -N synfoold iptables -A synfoold -p tcp --syn -m limit --limit 10/s -j RETURN iptables -A synfoold -p tcp -j REJECT --reject-with tcp-reset iptables -A INPUT -p tcp -m state --state NEW -j synfoold iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP ######## 防止 SSL 攻擊 iptables -t nat -A OUTPUT -p tcp --sport 1000:3000 --dport 443 -j REDIRECT --to-port 10000 ######## 防止惡意掃描 iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags ALL NONE -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP iptables -A INPUT -i $EXT_IF -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 6/m -j ACCEPT ######## disable been scaned iptables -N tcp_packets iptables -A tcp_packets -p TCP --tcp-flags ALL FIN,URG,PSH -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags ALL ALL -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags ALL NONE -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "been scanned:" iptables -A tcp_packets -p TCP --tcp-flags ALL FIN,URG,PSH -j DROP iptables -A tcp_packets -p TCP --tcp-flags ALL ALL -j DROP iptables -A tcp_packets -p TCP --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP iptables -A tcp_packets -p TCP --tcp-flags ALL NONE -j DROP iptables -A tcp_packets -p TCP --tcp-flags SYN,RST SYN,RST -j DROP iptables -A tcp_packets -p TCP --tcp-flags SYN,FIN SYN,FIN -j DROP iptables -A FORWARD -p tcp -j tcp_packets ######## 丟棄蠕蟲對 80 PORT 請求 #if [ -f "/lib/iptables/libipt_string.so" ]; then # for STRING in $CHK_STRING; do # iptables -I INPUT -j DROP -p tcp -s 0.0.0.0/0 -m string --string $STRING ######每小時只記錄一條這樣的資訊: # iptables -I INPUT -j LOG -p tcp -s 0.0.0.0/0 -m string --string $STRING -m limit --limit 1/hour # done #fi ##### 對於攻擊您Server的IP給予拒絕 if [ -f $INPUT_IP ] ; then DROP_IP=$(cat $INPUT_IP) for DROPIP in $DROP_IP; do iptables -I INPUT -s $DROPIP -j DROP done fi ###### 自訂 allowed 這個 chain 來處理 允許進入的 tcp 連線 ###### 凡 tcp_packets 中的 chain rule 目的是某些欲開放的 port 者, ###### 則跳至此一 allowed chain 來處理. iptables -N allowed iptables -A allowed -p TCP --syn -j ACCEPT iptables -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A allowed -p TCP -j DROP iptables -A tcp_packets -p TCP -s 0/0 --dport 1024:65535 -j allowed for PORT in $OPEN_PORT; do iptables -A tcp_packets -p TCP -s 0/0 --dport $PORT -j allowed done ###### 對於主動連線或者是不合法連線,一律通通拒絕掉 iptables -A INPUT -i $EXT_IF -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i $EXT_IF -m state --state NEW,INVALID -j DROP ###### 重導 www 請求至 Squid (透過代理伺服器) ###### 這樣可以強迫使用者使用 Proxy 而不必修改 Client 端設定 if [ "$INT_IF" != "$EXT_IF" ] ; then CHK_SQUID=$(/etc/rc.d/init.d/squid status 2>/dev/null | grep pid) if [ -n "$CHK_SQUID" ]; then echo "開啟 proxy 對外連線" INT_IP=$(ifconfig | grep $INT_IF -A 1 | awk '/inet/ {print $2}' | sed -e s/addr\://) if [ -z "$INT_IP" ]; then echo echo "$(basename $0): there is no IP found on $INT_IF." echo " Please make sure $INT_IF is setup properly." echo exit 3 fi iptables -t nat -A PREROUTING -i $INT_IF -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 3128 fi fi ####### 啟動內部對外轉址 if [ "$INT_IF" != "$EXT_IF" ] ; then iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -A POSTROUTING -o $INT_IF -j SNAT --to-source $INT_IP # iptables -t nat -A POSTROUTING -s $INT_NET -j SNAT --to-source $EXT_IP iptables -t nat -A POSTROUTING -o $EXT_IF -s $INT_NET -j MASQUERADE fi ####### 語音 (依個人需要) #iptables -A PREROUTING -t nat -p tcp -i $EXT_IF --dport 389 -j DNAT --to 192.168.1.100 #iptables -A PREROUTING -t nat -p tcp -i $EXT_IF --dport 522 -j DNAT --to 192.168.1.100 #iptables -A PREROUTING -t nat -p tcp -i $EXT_IF --dport 1503 -j DNAT --to 192.168.1.100 #iptables -A PREROUTING -t nat -p tcp -i $EXT_IF --dport 1720 -j DNAT --to 192.168.1.100 #iptables -A PREROUTING -t nat -p tcp -i $EXT_IF --dport 1731 -j DNAT --to 192.168.1.100 ####### 將封包偽裝出去 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT ######################################################### ################### 各種允許的範例 ###################### ######################################################### if [ -f $OUT_IP_MAC ] ; then CLIENTOUT_IP_MAC=$(cat $OUT_IP_MAC) iptables -I FORWARD -p all -s $INT_NET -j DROP for OUT_IP_MAC1 in $CLIENTOUT_IP_MAC; do IP_OUT=$(echo $OUT_IP_MAC1 |awk -F'=' '{print $1}') MAC_OUT=$(echo $OUT_IP_MAC1 |awk -F'=' '{print $2}') iptables -I FORWARD -s $IP_OUT -m mac --mac-source $MAC_OUT -j ACCEPT done else if [ -f $OUT_IP ] ; then CLIENTOUT_IP=$(cat $OUT_IP) iptables -I FORWARD -p all -s $INT_NET -j DROP for OUT_IP in $CLIENTOUT_IP; do iptables -I FORWARD -p all -s $OUT_IP -j ACCEPT done fi if [ -f $OUT_MAC ] ; then CLIENTOUT_MAC=$(cat $OUT_MAC) iptables -I FORWARD -p all -s $INT_NET -j DROP for OUT_MAC in $CLIENTOUT_MAC; do iptables -I FORWARD -m mac --mac-source $OUT_MAC -p all -j ACCEPT done fi fi ######################################################### ################### 各種限制的範例 ###################### ######################################################### ###下面的規則是直接把所有的 p2p 封包擋下 #iptables -A FORWARD -m ipp2p --ipp2p -j DROP ######停止 USER 使用 MSN 聊天 #iptables -I FORWARD -p tcp -o $EXT_IF -d 207.46.104.20 -j DROP ####### 單一USER的限制,只可連web 以IP為主(依個人需要) #iptables -I FORWARD -p all -s 他的IP -j DROP #iptables -I FORWARD -p tcp -s 他的IP --dport 80 -j ACCEPT ####### 單一USER的限制,只可連web 以網卡號碼為主(依個人需要) #iptables -I FORWARD -m mac --mac-source XX:XX:XX:XX:XX:XX -p all -j DROP #iptables -I FORWARD -m mac --mac-source XX:XX:XX:XX:XX:XX -p tcp --dport 80 -j ACCEPT ####### 限制對某IP之連線 #iptables -I FORWARD -d 202.1.237.21 -i $INT_IF -j DROP ####### 限制對內 224-254 範圍內 IP 對外連線 #iptables -I FORWARD -p all -s 192.168.2.192/26 -j DROP #iptables -I FORWARD -p all -s 192.168.2.224/27 -j DROP #iptables -I FORWARD -p all -s 192.168.2.240/28 -j DROP ####### 限制對內 IP 對外連線 #iptables -I FORWARD -p all -s 192.168.2.192 -j DROP ####### 限制對內 IP 對外連線(依照您所設時間為準,例:早上8點至下午5點都不能對外連線) #iptables -I FORWARD -p all -s 192.168.2.100 -d 0/0 -m time --timestart 08:00 --timestop 17:00 -j DROP ####### 阻擋指定的網卡號碼 (依個人需要) ####### 這是 Kernel 2.4 系列新功能,主要防止 Client 非法搶 IP #iptables -A INPUT -m mac --mac-source XX:XX:XX:XX:XX:XX -j DROP ####### 阻擋內部網卡號碼出去 (依個人需要) #iptables -I FORWARD -m mac --mac-source XX:XX:XX:XX:XX:XX -j DROP ####### 不允許非root帳號的封包連線到外部網路 #iptables -A OUTPUT -m owner ! --uid-owner 0 -j DROP ####### 允許相關連結服務 for PORT in $OPEN_PORT; do iptables -A INPUT -i $EXT_IF -p tcp --dport $PORT -j ACCEPT iptables -A INPUT -i $EXT_IF -p udp --dport $PORT -j ACCEPT iptables -A INPUT -p tcp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT iptables -A INPUT -p udp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT iptables -A OUTPUT -o $EXT_IF -p tcp --dport $PORT -j ACCEPT iptables -A OUTPUT -o $EXT_IF -p udp --dport $PORT -j ACCEPT iptables -A OUTPUT -p tcp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT iptables -A OUTPUT -p udp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT iptables -A FORWARD -i $EXT_IF -p tcp --dport $PORT -j ACCEPT iptables -A FORWARD -i $EXT_IF -p udp --dport $PORT -j ACCEPT iptables -A FORWARD -p tcp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT iptables -A FORWARD -p udp --sport $HI -d $EXT_IP --dport $PORT -j ACCEPT done ##### 不想要對內部開放 if [ "$INT_IF" == "eth1" ]; then if [ "$DROP_PORT" != "" ]; then for DROPPORT in $DROP_PORT; do iptables -I FORWARD -p tcp -i $INT_IF -m multiport --dport $DROPPORT -j DROP done fi fi iptables -A PREROUTING -t mangle -p tcp --dport 20 -j TOS --set-tos 8 iptables -A PREROUTING -t mangle -p tcp --dport 21 -j TOS --set-tos 16 iptables -A PREROUTING -t mangle -p tcp --dport 23 -j TOS --set-tos 16 iptables -A PREROUTING -t mangle -p tcp --dport 25 -j TOS --set-tos 8 iptables -A PREROUTING -t mangle -p tcp --dport 80 -j TOS --set-tos 16 iptables -A PREROUTING -t mangle -p tcp --dport 53 -j TOS --set-tos 8 iptables -A PREROUTING -t mangle -p udp --dport 53 -j TOS --set-tos 16 iptables -A PREROUTING -t mangle -p tcp --dport 110 -j TOS --set-tos 2 ###### NAT部份對外網路轉址:eth0 IP位址:x.x.x.x if [ "$NAT_IP" != "" ]; then clear echo "您已開啟對內轉址,IP:$NAT_IP" for NAT in $NAT_PORT; do iptables -t nat -A PREROUTING -p tcp -d $EXT_IP --dport $NAT -j DNAT --to-destination $NAT_IP:$NAT echo "外部IP=$EXT_IP PORT:$NAT ---------------> 轉內部IP=$NAT_IP PORT:$NAT" done fi #iptables -t nat -A PREROUTING -p tcp -d $EXT_IP -j DNAT --to-destination $NAT_IP exit 0