iptables 是 linux 比較常用的命令, 但是相對其它命令較為復雜且結合網絡應用, 所以單獨寫一篇文章存作筆記
目錄
1) iptables 介紹
2) 常用功能(防火牆、SNAT、DNAT)
一、iptables 介紹
早期的 linux 版防火牆叫 ipfirewall, 到了 7.0 開始正在向 firewall 過渡,目前大部分使用的版本叫 iptables,
(一) 表(table)
# iptables -t (表名)
iptables 有以下4張表, 我們在對表進行鏈的規則設置時需要帶上 -t 表名, 但對最常用的 filter 表不需要加 --t
filter: 防火牆過濾功能
nat: 用於NAT功能(端口映射和地址轉換等)
mangle: 用於對特定數據包進行修改
raw: 一般為了數據包不再讓 iptables 跟蹤處理
4個表的優先級為: raw>mangle>nat>filter
(二) 鏈(chain)
# iptables -t (表名) -操作類別 (鏈名)
操作類別:
-A: 添加(Append), 在指定鏈的最後添加一條規則
-I num: 插入(Insert), 在指定鏈第 num 前插入一條規則
-R num: 替換(Replace), 替換指定鏈第 num 條規則
-D num: 刪除(Delete), 刪除指定鏈的第 num 條規則,沒有帶 num 時表示刪除指定鏈與命令相匹配的規則
即: 使用 -A 命令添加規則, 將-A命令改為-D (其它不變) 可以刪除這一條規則
鏈分以下5種:
PREROUTING: 數據包進入路由表之前
INPUT: 通過路由表後, 目的地為本機
FORWARD: 通過路由表後, 目的地不為本機
OUTPUT: 由本機產生, 向外發送
POSTROUTING: 發送到網卡接口之前
如圖:
表鏈對應關系如下:
filter表: INPUT、FORWARD、OUTPUT
nat 表: PREROUTING、OUTPUT、POSTROUTING
mangle表: PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
raw表: PREROUTING、OUTPUT
(三) 規則
1)匹配
通用匹配:
-s: 源地址, ip/mask
-d: 目標地址
-p: 協議, tcp/udp/icmp
-i: 流入數據, -i eth0, 一般用在 INPUT和 PREROUTING
-o: 流出數據, -o eth0, 一般用在 OUTPUT和POSTROUTING
擴展匹配:
-p tcp: TCP協議擴展
--dport 22, 單個目標端口 或者 --dport 21-30, 多個目標端口
--sport 22, 單個源端口 或者 --sport 21-30, 多個源端口
--tcp-flags: TCP標志位(SYN,ACK,FIN,PSH,RST,URG)
-p udp: UDP協議擴展
---dport, 同上
---sport, 同上
-p icmp: icmp報文擴展
--icmp-type: icmp報文類型
echo-request: 請求回顯數據包
echo-reply: 響應數據包
-m multport: 多端口擴展
2) 處理方式
DROP: 丟棄
REJECT: 拒絕
關於DROP與REJECT的區別,參考文章: http://www.betasoft.com.cn/btzsk/2011-11-14/2056.html
ACCEPT: 接受
DNAT: 目標地址轉換, 比如 linux 主機映射 80 端口到內網web服務器, 需要修改數據包目標地址為內網web服務器地址
SNAT: 源地址轉換, 比如幾臺內網PC共享 linux 主機上網, 需要修改上網數據包的源地址為 linux 主機外網地址
MASQUERADE: 源地址偽裝, 比如自動將SNAT 的數據包源地址更改為本地網卡的當前IP
REDIRECT: 重定向, 主要用於端口重定向
MARK: 防火牆標記
參考文章: http://blog.csdn.net/maotianwang/article/details/8489908
RETURN: 返回, 用於連的跳轉, 鏈A 跳至鏈B, 鏈B執行 RETURN 會將數據包交給鏈A做規則判斷
參考文章: http://bbs.chinaunix.net/thread-2245599-1-1.html
二、常用功能
在學習查找資料的過程中, 發現iptables遠比想象中的更有深度.
本文使用linux 與 iptables版本如下
(一) 生效&保存
執行 iptables 命令進行修改防火牆設置會馬上生效, 但不會自動保存,需要執行保存命令,
保存命令會將當前設置保存到文件 /etc/sysconfig/iptables, 重啟iptables服務會加載 /etc/sysconfig/iptables文件的配置
保存配置
# /etc/rc.d/init.d/iptables save
重啟服務
# service iptables restart
注: 如果不保存直接重啟服務, 會丟失剛才的修改(二) 通用設置
查看 iptables 是否運行
# service iptables status
查看當前防火牆設置
# iptables -L (鏈名) //鏈名省略時表示全部
刪除指定鏈或所有鏈的規則
# iptables -F (鏈名)
刪除指定自定義鏈名或所有自定義鏈
# iptables -X (鏈名)
(三) 防火牆設置(Filter)
1) 設置默認規則
當前 iptables 規則是空的(默認狀態下3條鏈的規則都是 ACCEPT)
我的 Linux 主機不在本地,使用遠程連線, 所以在設置默認規則前先添加 tcp 22端口
# iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
注: --dport 表示目標(destination)端口22, -j ACCEPT 表示跳轉(jump)到 ACCEPT (接受)
設置 INPUT 默認為 DROP, OUTPUT 默認 ACCEPT, FORWARD 默認為 DROP (可根據實際情況進行調整)
# iptables -t filter -P INPUT DROP
# iptables -t filter -P OUTPUT ACCEPT
# iptables -t filter -P FORWARD DROP
注: 大寫-P 表示策略(Policy) , 小寫-p 表示協議(Protocol)
2) 設置放行規則
開啟訪問linux 主機的 tproxy tcp 3388 端口和 Xmanager udp 177 端口
# iptables -t filter -A INPUT -p tcp --dport 3388 -j ACCEPT
# iptables -t filter -A INPUT -p udp --dport 177 -j ACCEPT
執行完以上命令後 ssh 可以正常使用,但 tproxy 和 Xmanager 都不能正常使用,
使用 nmap 工具測試 tcp 3388 和 udp 177 端口狀態為 open (開啟)
添加以下規則後OK,
# iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-m : 多端口(multport), 對狀態(state)為 ESTABLISHED(已建立連接)、RELATED(回傳)的數據包放行
如果要拒絕訪問外網某個目標 ip 的 tcp 80, 如:
# iptables -t filter -A OUTPUT -d 112.80.248.74 -p tcp --dport 80 -j REJECT
3)測試規則的匹配原則:
# iptables -L
目前允許所有 ip INPUT TCP 22端口, 再添加一條拒絕某一個 IP INPUT TCP 22端口
# iptables -t filter -A INPUT -s 10.0.0.1 -p tcp --dport 22 -j REJECT
發現在 10.x.x.x 的主機上仍然可以訪問 tcp 22 端口, 說明iptables 匹配到第1條允許 tcp 22端口允許放行後,
就已經判定為放行, 不再逐條進行後面的檢查
所以拒絕某個 ip 的方法是使用 -I 選項插入到最前面去, 但會增加iptables的檢查步驟
# iptables -t filter -I INPUT 1 -s 10.0.0.1 -p tcp --dport 22 -j REJECT
(四) 地址轉換(Nat)
1) SNAT 源地址轉換
一個包如果目標不是自己, 在通過 Forward的時候, 把源地址改成自己的地址,
它只能發生在 Postrouting 上, 不能發生在 Prerouting上。
SNAT實例:
實現PC透過 linux 主機的雙網卡 + SNAT功能訪問 Internet
開啟 linux 主機轉發 10.0.0.1/24的數據包
# iptables -A FORWARD -s 10.0.0.1/24 -j ACCEPT
# iptables -A FORWARD -d 10.0.0.1/24 -j ACCEPT
手動修改 /proc/sys/net/ipv4/ip_forward 的值, 將默認的 0 改為1
# echo 1 > /proc/sys/net/ipv4/ip_forward
修改出口 POSTROUTING 鏈來源泉IP 10.0.0.1/24 為 linux 主機 ip: 192.168.1.105
# iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -j SNAT --to-source 192.168.1.105
將 PC 的網關設置為 10.0.0.105 或者設置 0.0.0.0 的路由轉發 10.0.0.105 後, PC即可訪問網絡 192.168.1.1/24與 Internet
也就是平常所說的NAT共享上網
當 linux 拔號上網(即外網IP地址不能固定)時, 可以使用以下命令
# iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -j MASQUERADE (偽裝)
2)DNAT目標地址轉換
當一個包到達 Prerouting 的時候, 如果目標地址是自己, 將端口匹配的數據包修改目標IP
DNAT實例:
PC 透過 linux主機的 DNAT 功能將 tcp 80 的數據包轉發到 WEB服務器
參考 SNAT實例, 開啟 linux 主機轉發 10.0.0.1/24的數據包,修改 /proc/sys/net/ipv4/ip_forward 為1
# iptables -t nat -A PREROUTING -d 10.0.0.105 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.101
當只有一個外網IP,但內網有多種服務需要供外網訪問時, 由 linux 主機根據端口做 DNAT 映射。
NAT參考文章:http://blog.163.com/leekwen@126/blog/static/33166229200981954962/
注意:
1)默認情況下, 執行 # service network restart 後, 文件 /proc/sys/net/ipv4/ip_forward 內容會變為 0, 會導致 nat 失效
解決辦法: 修改 etc/sysctl.conf 中的 net.ipv4.ip_forward 為 1
2)做SNAT設置訪問外網 0.0.0.0時, ,如果只做 1條 POSTROUTING 來源泉地址轉換會導致linux主機不能訪問內網,
原因: 所需要訪問 0.0.0.0 的數據包會部換成外網IP地址, 其中也包含 訪問內網的數據包
解決辦法: 增加1條:
# iptables -t nat -I POSTROUTING 1 -s 10.x.x.x/x -d 10.x.x.x/x -j SNAT --to-source 10.x.x.x (本機內網ip)
或者使用只這一條命令(中間有一個感嘆號), 表示除了訪問內網的數據外才做 SNAT
# iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -j SNAT --to-source 192.x.x.x(本機外網ip)