Linux上使用iptables設置防火牆

因爲老師留作業要對Netfilter內核模塊進行擴展編程,因此在此之前先學習了一下iptables的用法,筆記一下,忘了就來看看。

首先推薦一篇不錯的博客,作爲參考補充:
http://www.cnblogs.com/JemBai/archive/2009/03/19/1416364.html

iptables和netfilter

先說一下iptables和netfilter的關係:

netfilter在內核空間的代碼根據table中的rules,完成對packet的分析和處置。但是這些table中的具體的防火牆rules,還是必須由系統管理員親自編寫。內核中的netfilter只是提供了一個機制,它並不知道該怎樣利用這個機制,寫出合適的rules,來實現一個網絡防火牆。

那麼,系統管理員編寫的rules,怎樣進入位於內核空間中的netfilter維護的table中去呢?這個任務是由iptables這個工具來完成的。

說白了就是netfilter是位於內核裏的,iptables是位於用戶空間的管理工具。有了iptables,用戶空間就可以和內核中的netfilter進行交流,維護table中的防火牆rules了。

iptables的一丁點兒基本知識

表 (tables)

iptables 包含 5 張表(tables):
- raw 用於配置數據包,raw 中的數據包不會被系統跟蹤。
- filter 是用於存放所有與防火牆相關操作的默認表。
- nat 用於 網絡地址轉換(例如:端口轉發)。
- mangle 用於對特定數據包的修改(參考 損壞數據包)。
- security 用於 強制訪問控制 網絡規則(例如: SELinux – 詳細信息參考 該文章)。
大部分情況僅需要使用 filter 和 nat。其他表用於更復雜的情況——包括多路由和路由判定。

鏈 (chains)

我們暫時主要了解一下filter的過濾好了。

表由鏈組成,鏈是一些按順序排列的規則的列表。默認的 filter 表包含 INPUT, OUTPUT 和 FORWARD 3條內建的鏈,這3條鏈用於數據包過濾。

規則 (rules)

數據包的過濾基於規則。規則由一個目標(數據包包匹配所有條件後的動作)和很多匹配(導致該規則可以應用的數據包所滿足的條件)指定。一個規則的典型匹配事項是數據包進入的端口(例如:eth0 或者 eth1)、數據包的類型(ICMP, TCP, 或者 UDP)和數據包的目的端口。

配置filter表的具體操作

在我的Arch上,執行iptables的話需要root權限,畢竟是對內核功能的操作。

查看當前iptables的設置

pArch# iptables -nvL
Chain INPUT (policy ACCEPT 1 packets, 52 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1 packets, 52 bytes)
 pkts bytes target     prot opt in     out     source               destination 

以上參數的意義:

-L, --list [chain]
              List all rules in the selected chain.  If no chain is selected, all chains are listed. 

-n, --numeric
              Numeric output.  IP addresses and port numbers will be printed in numeric format.  By default, the program will  try to display them as host names, network names, or services (whenever applicable).

-v, --verbose
              Verbose output.  This option makes the list command show the interface name, the rule options (if any), and the  TOS masks.   The  packet  and  byte  counters  are  also listed, with the suffix 'K', 'M' or 'G' for 1000, 1,000,000 and 1,000,000,000 multipliers respectively.

上面的三條鏈INPUT/FORWARD/OUTPUT的policy都是ACCEPTED,表明還沒有配置規則。沒有數據包被阻止,均被接受。

清除原有規則

pArch# iptables -F  #清除預設表filter中的所有規則鏈的規則
pArch# iptables -X  #清除預設表filter中使用者自定鏈中的規則

如果已經有了過濾規則,可以通過以上命令清空,然後再一步步設置。

預設規則
比如將INPUT(所有接收的包)默認都丟掉:

pArch# iptables -P INPUT DROP
pArch# iptables -nvL         
Chain INPUT (policy DROP 26 packets, 3074 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 22 packets, 1626 bytes)
 pkts bytes target     prot opt in     out     source               destination      

其中參數:

-P, --policy chain target
              Set  the  policy  for  the chain to the given target. Only built-in (non-user-defined) chains can have policies, and neither built-in nor user-defined chains can be policy targets.

可以看到,INPUT的policy已經變成DROP了,而立刻就有妄圖發到我的電腦的26 packets, 3074 bytes被丟棄了。

注:如果你是遠程SSH登陸的話,當你輸入第一個命令回車的時候就應該掉了,因爲設置完默認丟棄所有包之後,沒有設置任何可以接收的包。掉線了怎麼辦呢,只能去本機操作了=.=!

添加規則
由於剛剛我們默認INPUT爲DROP,則所有進入計算機的包都會被防火牆丟掉,本機收不到任何包。也就是說此時如果進行ping www.baidu.com的話是不會成功的,因爲icmp的echo request報文雖然發出去了,但是echo response報文被drop了。

爲了能ping通,我們需要設置icmp報文爲可接受狀態:

pArch# iptables -A INPUT -p icmp -j ACCEPT
pArch# iptables -nvL --line-numbers       
Chain INPUT (policy DROP 227 packets, 36248 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       18  1869 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0     

其中:

-A, --append chain rule-specification
              Append one or more rules to the end of the selected chain.  When the source and/or destination names resolve to more than one address, a rule will be added for each possible address combination.

[!] -p, --protocol protocol
              The  protocol  of the rule or of the packet to check.  The specified protocol can be one of tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh or the special keyword "all", or it can be a numeric value, representing one of these  pro‐tocols or a different one.  

-j, --jump target
              This specifies the target of the rule; i.e., what to do if the packet matches it.  

所以iptables -A INPUT -p icmp -j ACCEPT的意思就是給INPUT鏈添加一條規則,對於所有的icmp協議,都ACCEPT。

這樣的話ping就可以執行了。

小實例

我們都知道訪問服務器的80端口可以上網,所以我們使用iptables對自己的防火牆進行設置:除了上網的報文,其餘所有出去的報文均被攔截。

設置之後的效果:

pArch# iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
pArch# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 1 packets, 52 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     171K   11M ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

其中--dport代表destination port,目的端口號;--sport代表source port,源端口號。

上面的設置就是說我的電腦對訪問外服務器的80端口的tcp協議報文是放行的,即對請求網頁的報文是放行的,再說白點兒就是允許上網。

然後當我在瀏覽器中上百度的時候卻發現無論如何都上不去。這不科學!應該是可以上網的啊,我已經把通往外網80端口的數據包默認放行了啊!

後來找了半天原因,才發現百度的網址是https://www.baidu.com/,是https而不是http,而https所對應的端口是443(443/TCP HTTPS - HTTP over TLS/SSL(加密傳輸)),不是80(80/TCP HTTP(超文本傳輸協議)- 用於傳輸網頁)。

於是我果斷換了個網址,訪問新浪http://www.sina.com.cn/,果然就成功了。

然後把443端口也設爲ACCEPT,iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT,再上百度果然就行了。

配置並運行 iptables

最後說一下iptables的配置問題,參考https://wiki.archlinux.org/index.php/Iptables

iptables 是一個 Systemd 服務,因此可以這樣啓動:

systemctl start iptables

但是,除非有 /etc/iptables/iptables.rules 文件,否則服務不會啓動,Arch iptables 包不包含默認的 iptables.rules 文件。因此,第一次啓動服務時使用以下命令:

touch /etc/iptables/iptables.rules
systemctl start iptables

或者

cp /etc/iptables/empty.rules /etc/iptables/iptables.rules
systemctl start iptables

和其他服務一樣,如果希望啓動時自動加載 iptables,必須啓用該服務:

systemctl enable iptables

配置文件

通過命令行添加規則,配置文件不會自動改變,所以必須手動保存:

iptables-save > /etc/iptables/iptables.rules

修改配置文件後,需要重新加載服務:

systemctl reload iptables

或者通過 iptables 直接加載:

iptables-restore < /etc/iptables/iptables.rules
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章