天天看點

實用防火牆(Iptables)腳本分析

實用防火牆(iptables)腳本分析

——redhat,centos,ubuntu等常見linux發行版中都會預裝iptables防火牆,大多數初學者設定起來由于對這款軟體比較陌生,設定起來比較困難,下面這段腳本實作了修改變量的值就能輕松移植到自己的網絡,同時對各段内容做了介紹。首先在/usr/bin下建立一個腳本名為firewall,設定可執行權限

#chmod +x /usr/bin/firewall

下面我最這個腳本的關鍵部分做一些說明:

——首先設定假設你想限制某ip(例如10.10.10.20),你隻需将他們填入到badips變量中,可以設定多個ip或網端,每個用空格分開.

badips="10.10.10.20 10.1.14.0/24"

——接下來開始設定impossible_ips變量,例如設定三個私有ip的網段,前提是你的主機ip 不能在三個設定的網段範圍之内,如果在設定範圍内就要删除.

impossible_ips="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"

如果你的系統隻是家用,單獨上網,以下6行代碼就無需設定。

1).in_tcp_portallowed=""

2).in_icmp_allowed=""

3).egress="0"

4).out_tcp_portallowed=""

5).out_udp_portallowed=""

6).out_icmp_allowed=""

<a></a>

——如果你架設了伺服器就需要下面的設定,這裡強調一下in_tcp_porallowed,in_udp_portallowed是變量,他的值設定常見網絡服務的端口号;如果需要開放連續端口就需要使用“:”号,例如需要開放38000-38090之間的所有端口,隻要進行如下設定:

in_tcp_portallowed=”38000:38090”

下面看個複雜的例子,

例1:

——假定ssh服務隻允許200.100.10.10通路,而ftp服務之開放給192.168.20.0/24網段使用;smtp則是出了10.10.10.20以外其餘都可以通路:

in_tcp_portallowed=”ssh,200.100.10.10ftp,192.168.20.0/24smtp,!10.10.10.20”

例2:

——架設需要開放smtp,domain服務給所有ip使用,然後僅允許來自200.100.10.10和192.168.20.0/24的使用者使用ssh登陸伺服器:

in_tcp_portallowed=”ssh,200.100.10.10 ssh,192.168.20.0/24 smtp domain”

案3:一個錯誤的案例

——有人想允許192.168.150.30對内網ssh伺服器通路,但是除了192.168.20.10以外其他所有ip都可以通路22端口,其餘都阻斷。他是這樣寫的:

in_tcp_portallowed=”ssh,192.168.150.30ssh,!192.168.20.10”

——我們可以看到雖然規則1限制了隻有192.168.150.30可以通路 ssh伺服器,但是規則2卻反而将其開放給所有人,第一個規則等于擺設。

實用防火牆(Iptables)腳本分析

更多詳細的資訊您可以在/etc/service檔案中找到。

# 允許内網的tcp連結

in_tcp_portallowed="ssh,192.14.0.3 smtp domain http https"

# 允許内網的udp連結

in_udp_portallowed="domain"

如果你想讓ping包通過那麼需要如下設定

in_icmp_allowed=”8”

當然也可以設定隻有某個ip能ping,例如:

in_icmp_allowed=”8,61.63.33.172”

表示隻有61.63.33.172可以ping 主機。

# 允許内網ICMP的類型

in_icmp_allowed="0 3 8 11"

實用防火牆(Iptables)腳本分析

下面看個例子幫助我們了解這張表,在ping時,如果這個 echo-request 不能到達對方的機器﹐或是對方回應的 echo-reply 不能順利送回來﹐那 ping 就失敗。在許多有防火牆的環境中都會碰到﹐如果防火牆将 request 和 reply 攔下來就會導緻 ping 失敗。另外﹐就算不是防火牆設定的問題﹐對方也可以将機器設定為不回應任何 echo-request 封包﹐若在 linux 上,隻要用下面指令就可以了﹕

echo "1" &gt; /proc/sys/net/ipv4/icmp_echo_ignore_all

再舉一個例子,在使用traceroute指令式,我們要知道當封包被一個路由節點處理之後﹐它原來的 ttl 值就會被扣掉 1 ﹐這樣﹐如果封包的 ttl 降到 0 的時候﹐路由器就會丢棄這個封包﹐并且同時向來源地送出一個 time_exceeded( type 11 ) 的 icmp 封包﹐以告知其封包的命運。

egress這個設定表示是否限制對外的連結,值為0代表不限制,1代表限制對外連結。

egress="0"

# 允許對外連結的通訊端口

out_tcp_portallowed="ssh smtp,root http https pop3"

# 允許對外連結的udp通訊端口

out_udp_portallowed=""

out_icmp_allowed="0 3 8 11"

#如果你希望記錄所有被放火牆阻止的資料包,就需要将droplog的值設定為1,不過這樣會使/var/log/messages日志容量上升

droplog="0"

#

dshield="0"

#裝載iptables核心子產品

modprobe ip_tables 2&gt;/dev/null

modprobe ip_conntrack 2&gt;/dev/null

modprobe ip_conntrack_ftp 2&gt;/dev/null

modprobe ip_conntrack_irc 2&gt;/dev/null

#清除目前iptables所有表的規則

echo -n "initiating iptables..."

iptables -p input accept

iptables -p output accept

iptables -p forward accept

iptables -t filter -f

iptables -t nat -f

iptables -t filter -x

iptables -t nat -x

echo "ok"

if [ "$dshield" = "1" ]; then

echo -n "getting the dshield block list..."

badips="$badips

`lynx --dump http://feeds.dshield.org/block.txt | \

awk '/^[1-9]/ {print $1 "/" $3}'`"

fi

block.txt的部分内容如下:

開始ip 結束ip 網絡号 攻擊數量 name country email

222.189.239.0222.189.239.255242054

195.178.109.0195.178.109.255241601providerru[no email]

216.145.110.0216.145.110.255241355

[email protected]

[email protected]

# 若你加上start參數,則将$skiptest變量置1,那麼就會跳過測試模式,設定所有規則後不再清除。

[ "$1" = "start" ] &amp;&amp; skiptest="1"

##設定iptables核心的安全相關參數

echo 1 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

echo 1 &gt; /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

echo 0 &gt; /proc/sys/net/ipv4/conf/all/accept_source_route

echo 0 &gt; /proc/sys/net/ipv4/conf/all/accept_redirects

echo 0 &gt; /proc/sys/net/ipv4/conf/all/send_redirects

echo 1 &gt; /proc/sys/net/ipv4/conf/all/rp_filter

echo 1 &gt; /proc/sys/net/ipv4/tcp_syncookies

echo 3 &gt; /proc/sys/net/ipv4/tcp_retries1

echo 30 &gt; /proc/sys/net/ipv4/tcp_fin_timeout

echo 1400 &gt; /proc/sys/net/ipv4/tcp_keepalive_time

echo 0 &gt; /proc/sys/net/ipv4/tcp_window_scaling

echo 0 &gt; /proc/sys/net/ipv4/tcp_sack

echo 0 &gt; /proc/sys/net/ipv4/tcp_timestamps

## 下面開始設定防火牆規則

echo -n "setting rules..." 

#設定input,output,forward的過濾規則,不符合規則的就會丢棄。

iptables -p input drop 

iptables -p output drop

iptables -p forward drop

# 允許流經環路位址(loopback)的包通過,lo代表環路接口。

iptables -a input -i lo -j accept

iptables -a output -o lo -j accept

iptables -a input -i ! lo -s 127.0.0.0/8 -j drop

iptables -a output -o ! lo -d 127.0.0.0/8 -j drop

# 增加新鍊badpkt

iptables -n badpkt

# 若droplog數值為1則記錄所有badpkt鍊的資料包

if [ "$droplog" = "1" ]; then

iptables -a badpkt -j log --log-prefix "** firewall badpkt **"

# 丢棄所有進入badpkt鍊的封包

iptables -a badpkt -j drop

# 将可疑封包交給badpkt鍊處理。

iptables -a input -m state --state invalid -j badpkt

iptables -a input -p tcp ! --syn -m state --state new -j badpkt

iptables -a input -p tcp --tcp-flags all none -j badpkt

iptables -a input -p tcp --tcp-flags syn,fin syn,fin -j badpkt

iptables -a input -p tcp --tcp-flags syn,rst syn,rst -j badpkt

iptables -a input -p tcp --tcp-flags fin,rst fin,rst -j badpkt

iptables -a input -p tcp --tcp-flags ack,fin fin -j badpkt

iptables -a input -p tcp --tcp-flags ack,urg urg -j badpkt

iptables -a input -p tcp --tcp-flags ack,psh psh -j badpkt

iptables -a input -p tcp --tcp-flags all fin,urg,psh -j badpkt

iptables -a input -p tcp --tcp-flags all syn,rst,ack,fin,urg -j badpkt

iptables -a input -p tcp --tcp-flags all all -j badpkt

iptables -a input -p tcp --tcp-flags all fin -j badpkt

# 允許目的端口為53的udp包通過,這樣才能使用dns查詢。

iptables -a output -p udp -m state --state new --dport 53 -j accept

# 允許已建立連線和回應的資料包通過

iptables -a input -m state --state established,related -j accept

iptables -a output -m state --state established,related -j accept

# 增加一個阻止ip的新鍊

iptables -n badip

# 若droplog變量為1,則記錄所有進入badip鍊的封包

iptables -a badip -j log --log-prefix "** firewall badip **"

# 丢棄所有進入badip鍊的封包

iptables -a badip -j drop

# 阻止特定ip

for ip in $badips $impossible_ips ; do

iptables -a input -s $ip -j badip

done

# 允許特定tcp号對内新連接配接

for i in $in_tcp_portallowed ; do

ifs=','

set $i

unset ifs ipt_option

port="$1"

[ -n "$2" ] &amp;&amp; ipt_option="-s `echo $2 | sed 's/^!/! /'`"

iptables -a input -p tcp $ipt_option --dport $port \

--syn -m state --state new -j accept

# 允許特定udp端口的對内新連結

for i in $in_udp_portallowed ; do

iptables -a input -p udp $ipt_option --dport $port \

-m state --state new -j accept

# 允許特定icmp類型資料包進入

for i in $in_icmp_allowed ; do

type="$1"

iptables -a input -p icmp $ipt_option --icmp-type $type \

# 前面講過egress數值為1标志管制對外連結

if [ $egress = "1" ]; then

# 允許特定tcp對外連結

for i in $out_tcp_portallowed ; do

[ -n "$2" ] &amp;&amp; ipt_option="-d `echo $2 | sed 's/^!/! /'`"

[ -n "$3" ] &amp;&amp; ipt_option="$ipt_option -m owner \

`echo $3 | sed 's/\([^!]\)/ --uid-owner \1/'`"

iptables -a output -p tcp $ipt_option --dport $port \

for i in $out_udp_portallowed ; do

iptables -a output -p udp $ipt_option --dport $port \

for i in $out_icmp_allowed ; do

iptables -a output -p icmp $ipt_option --icmp-type $type \

if [ ! "$egress" = "1" ]; then

iptables -a output -m state --state new -j accept

iptables -a input -j log --log-prefix "** firewall drop **"

iptables -a output -j log --log-prefix "** firewall drop **"

iptables -a forward -j log --log-prefix "** firewall drop **"

echo "done"

# 5秒後自動清除iptables規則,這樣可以避免鎖住自己。

if [ "$skiptest" = "1" ]; then exit ;fi

echo -e "\ntest mode"

echo -n "all chains will be cleaned after 5 sec."

i=1; while [ "$i" -le "5" ]; do

echo -n "."

i=`expr $i + 1`

sleep 1

echo -en "\nflushing ruleset..."

這樣一個200多行腳本就能實作基本功能的防火牆,大家可以去上機試試,附件中帶完整腳本。

繼續閱讀