netfilter概述
netfilter 組件位於內核空間(kernelspace),是內核的一部分,由一些信息包過濾表組成,這些表包含內核用來控制信息包過濾處理的規則集。
iptables 組件是一種用戶空間(userspace)的工具,用來插入、修改和除去信息包過濾表中的規則。
Netfilter 提供了整個防火牆的框架,各個協議基於 Netfilter 框架來實現自己的功能。每個協議都有獨立的表來存儲自己的配置信息,他們之間完全獨立的進行配置和運行。
下圖是netfilter的主要組成(來源wikipedia):
其中各模塊說明:
- 鏈路層的防火牆模塊,在鏈路層中對數據幀進行處理。對應用戶空間的配置工具是ebtables。
- 對ARP處理的防火牆模塊,有獨立的表來存放自己的配置,對應用戶空間的配置工具是arptables。
- 網絡層中ipv6的防火牆模塊,在Ipv6協議棧中對報文進行處理,對應用戶空間的配置工具是ip6tables
- 網絡層中ipv4的防火牆模塊,在Ipv4協議棧中對報文進行處理,對應用戶空間的配置工具是iptables/nftables。
nftables是iptables的后繼者,nftables在用戶態把網絡規則編譯成字節碼,然后由內核的虛擬機執行。
一個數據包在netfilter中的處理流程如下圖(來源wikipedia):

網絡層中的hook
Netfilter 提供了5個網絡層的hook,分別位於linux 網絡棧中的各個處理節點,如下圖:
--->[NF_IP_PRE_ROUTING]--->[ROUTE]--->[NF_IP_FORWARD]--->[NF_IP_POST_ROUTING]--->
| ^
| |
| [ROUTE]
v |
[NF_IP_LOCAL_IN] [NF_IP_LOCAL_OUT]
| ^
| |
v |
--------Local Process-------
Netfilter Hook的意義(參考:www.netfilter.org):
- NF_IP_PRE_ROUTING: 位於路由之前,報文一致性檢查之后(報文一致性檢查包括: 報文版本、報文長度和checksum)。
- NF_IP_LOCAL_IN: 位於報文經過路由之后,並且目的是本機的。
- NF_IP_FORWARD:位於在報文路由之后,目的地非本機的。
- NF_IP_LOCAL_OUT: 由本機發出去的報文,並且在路由之前。
- NF_IP_POST_ROUTING: 所有即將離開本機的報文。
Linux 內核模塊可以注冊到任何的hook,注冊的回調函數也必需指定優先級。當一個報文通過hook的時候,hook將會依據優先級調用回調函數。注冊的回調函數,可以有五種返回,每種返回代表對報文不同的操作:
- NF_ACCEPT: 繼續正常處理此報文,即允許報文通過。
- NF_DROP: 丟棄此報文,不再進行繼續處理,即拒絕此報文。
- NF_STOLEN: 取走這個報文,不再繼續處理。
- NF_QUEUE: 報文進行重新排隊,可以將報文發到用戶空間的程序,進行修改或者決定是拒絕或者允許。
- NF_REPEAT: 報文重新調用hook。
iptables的介紹
關於iptables的原理已經有很多博客都介紹過了,這里把我做的一個圖放上來供大家參考:
iptables常用的就是如上圖所示的四表五鏈(實際上還有個Security Table,應該是五個表,但這個表很少用):
- 四表:
- raw:可以對報文在鏈路跟蹤之前進行處理
- mangle:主要用於對報文的修改
- nat:主要用於NAT轉換
- filter:默認的規則表,用於報文的過濾
- 五鏈:PREROUTING, INPUT, OUTPUT, POSTROUTING, FORWARD,分別對應的是netfilter的五個hook。
iptables 工具使用
iptables命令基本格式:
iptables [-t table] [option] chain [rulenum] rule-specification
iptables 的操作是針對表中的鏈進行的,如果不指定,默認表為filter。
常用的Option如下
規則級別的修改:
| -A | 添加規則到指定鏈最后一行 |
| -D | 刪除指定鏈指定行 |
| -I | 插入規則到指定鏈的指定行,默認插入第一行 |
| -R | 替換規則到指定鏈指定行 |
針對規則查詢的:
| -L | 列出指定鏈中所有規則,若未指定鏈,則列出所有規則。-n 以數字方式顯示,-v 顯示具體信息 |
| -S | 類似於-L,按照iptables-save的格式打印規則 |
鏈級別的修改:
| -N | 新增自定義鏈 |
| -X | 刪除指定鏈,如未指定,則默認刪除所有鏈 |
| -P | 修改內置鏈的默認策略,值為ACCEPT或DROP |
| -F | 刪除指定鏈中的所有規則,默認刪除所有規則(所有鏈都還在,只不過規則被清空) |
規則語法(rule-specification)
規則由包匹配和目標動作組成。目標動作由-j選項指定。
常用的包匹配:
| -p | 指定協議。常見的有:tcp, udp, icmp |
| -s | 指定源地址,格式類似於192.168.1.0/24,多個地址使用逗號分隔,並且會自動形成多條規則 |
| -d | 指定目的地址,格式與-s一樣 |
| -i | 指定某網卡的流入規則 |
| -o | 指定某網卡的流出規則 |
| -m | 指定擴展匹配,可以匹配到特定性質的包。最常用的是tcp, udp, conntrack。當使用tcp和udp時,可以使用--dport指定目標地址端口,--sport指定源地址端口 |
大部分都支持使用!進行反向匹配。如:
iptables -A INPUT -s 192.168.2.0/24 -p tcp ! -i enth0 -j ACCEPT
# 接受所有非enth0的網卡流入的源地址為192.168.2.0/24網段的包。
-j中包含很多操作,比如對包的標記,ip地址的修改,ttl的修改等操作。某些操作只能在特定表和鏈中進行。
常用的動作:
-j user-chain |
跳轉到指定的自定義鏈。注意,自定義鏈匹配到最后一行以后會返回跳轉之前的地方繼續向后匹配 |
-j ACCEPT|DROP|REJECT |
設置策略 |
-j LOG [options] |
記錄日志 |
-j MASQUERADE |
僅在nat表的POSTROUTING鏈中使用。用於snat自動轉換IP功能 |
-j SNAT |
僅在nat表的POSTROUTING鏈中使用 |
-j DNAT |
僅在nat表的PRETROUTING和OUTPUT鏈中使用 |
最后補充一個剛剛犯的錯誤:
在配置FORWARD的時候,要保證正常通信,一定要配置雙向的規則。任何網卡流入的包首先經過的鏈都是PREROUTING。總結如下圖:

enth-a和enth-b都是主機的網卡。在FORWARD鏈上配置:
iptables -A FORWARD -i enth-a -j ACCEPT
iptables -A FORWARD -o enth-a -j ACCEPT
即可簡單實現雙網卡之間的互相轉發。
