一. netfilter
1. 什麼是entfilter 和 iptables
- netfilter指整個項目名
- 在這個項目裏面,netfilter特指內核中的netfilter框架,
- iptables指用戶空間的配置工具。
- netfilter在協議棧中添加了5個鉤子,允許內核模塊在這些鉤子的地方註冊回調函數,這樣經過鉤子的所有數據包都會被註冊在相應鉤子上的函數所處理,包括修改數據包內容、給數據包標記 或者丟掉數據包等。
- netfilter框架負責維護鉤子上註冊的處理函數或者模塊,以及它們的優先級。
- iptables是用戶空間的一個程序,通過netlink和內核的netfilter框架打交道,負責往鉤子上配置回調函數。
- netfilter框架負責在需要的時候動態加載其它的內核模塊, 有 ip_conntrack、nf_conntrack、NAT subsystem等。
通常使用中 可能會感覺iptables代表了整個項目, 代表了防火牆, 但是在開發者中, 可能netfilter 纔是整個項目.
2. netfilter 鉤子 (hooks)
- 內核協議棧中,有5個跟netfilter有關的鉤子,數據包經過每個鉤子時,都會檢查上面是否註冊有函數,如果有的話,就會調用相應的函數處理該數據包.
2.1 5個鉤子
- NF_IP_PRE_ROUTING:
- 接收的數據包剛進來,還沒有經過路由選擇,即還不知道數據包是要發給本機還是其它機器。
- NF_IP_LOCAL_IN:
- 已經經過路由選擇,並且該數據包的目的IP是本機,進入本地數據包處理流程。
- NF_IP_FORWARD:
- 已經經過路由選擇,但該數據包的目的IP不是本機,而是其它機器,進入forward流程。
- NF_IP_LOCAL_OUT:
- 本地程序要發出去的數據包剛到IP層,還沒進行路由選擇。
- NF_IP_POST_ROUTING:
- 本地程序發出去的數據包,或者轉發(forward)的數據包已經經過了路由選擇,即將交由下層發送出去。
2.2 位置圖
|
| In
↓
+-----------------+
| IP_PRE_ROUTING |
+-----------------+
|
↓
+_________________+ +---------------+
| Route table | ---------> | IP_LOCAL_IN |
+_________________+ +---------------+
| |
|
| +_______________+
| | local |
| +_______________+
| |
| |
↓ ↓
+---------------+ +---------------+
| IP_FORWARD | | IP_LOCAL_OUT |
+---------------+ +---------------+
| |
|-----------------------------+
|
↓
+-----------------+
| IP_POST_ROUTING |
+-----------------+
|
| Out
↓
- 上面顯示的可以看出, 一個數據包只會經過 下面三種路徑的一種.
- 本機收到的IP是本機的數據包: IP_PRE_ROUTING -> IP_LOCAL_IN
- 本機收到目的地IP 不是本地的: IP_PRE_ROUTING -> IP_FORWARD -> IP_POST_ROUTING
- 本機發出的數據包: IP_LOCAL_OUT -> IP_POST_ROUTING
2.3 iptables 中的表(tables)
- iptables 是使用表(tables) 來分配管它的規則的(rule) , 根據rule 的作用劃分了幾個表, 比如用啦過濾數據包 的rule 放在了 filter 表中, 用來處理 地址轉換的 rule 放在了 nat 表中, 其中rule 就是 應用在 netfilter 鉤子上的函數, 用來修改 數據包的內容或者過濾數據包, 目前 iptables 支持的表有:
-
filter
- filter 表內的 rule 用來過濾數據, 用來控制讓那些數據可以通過, 那些數據不可以通過.
-
nat
- nat 表內的 rule 用來控制網絡地址轉換, 控制要不要進行地址過濾, 以及如何修改源地址和目的地址, 從而影響數據包的路由, 達到連通的目的, 是路由器的必備功能.
-
Mangle
- 該表內的 rule 用於修改IP數據包頭, 如修改 TTL, 同時也可以爲數據包添加一些標記, 便於後續其他模塊 對數據包處理,( 添加標記是指 網內核skb 結構中添加, 而不是給IP數據包加東西)
-
raw 在 natfilter 裏面有個 connection tracking功能, 用來追蹤所有的連接, 而且可以看到 raw 表內的 rule 功能給數據包打的標記, 從而控制那些數據包不被 connection tracking 追蹤
-
security 在cnetos7 中新加的, 用於設置和 SElinux 相關, 主要設置 一些SELinux 標記, 便於和 SELinux 相關的模塊來處理數據包.
2.4 鏈
-
根據不同功能的 rule 在不同的表內, iptables 將表中的rule 在分類, 讓 rule 屬於 不同的鏈(chain), 有 chain來決定什麼時候觸發 chain 上的 那些rule.
-
iptables 的5個鏈分別對應5個鉤子:
- PREROUTING:
- 數據包經過NF_IP_PRE_ROUTING 會觸發 chain 上的rule
- INPUT
- 數據包經過 IP_LOCAL_IN 時會觸發 chain 上的 rule
- FORWARD
- 數據包經過 IP_FORWARD 時 會觸發 chain 的rule
- OUTPUT
- 數據包經過 IP_LOCAL_OUT時 會觸發chain 的rule
- POSTROUTING
- 數據包經過 IP_POST_ROUTING 時會觸發 chain 的rule
- PREROUTING:
-
每個表都可以有多個 chains , 但是並不表示每個表都包含了多個 chains, 應爲有些表上的 chains 上時沒有意義的, 如 raw 上只有 connection tracking 有意義.
2.5 每個表包含的 chain
|
| In
|
↓ ++---------------------++
+-----------------+ || raw ||
| IP_PRE_ROUTING | ------>|| (connection trak) ||
+-----------------+ || mangle ||
| || nat (DNAT) ||
| ++---------------------++
↓ ++-------------++
+_________________+ +---------------+ || mangle ||
| Route table | ---------> | IP_LOCAL_IN | --------> || filter ||
+_________________+ +---------------+ || security ||
| | || nat {SNAT} ||
| | ++-------------++
| |
| +_______________+
| | local |
| +_______________+
| | ++---------------------++
| | || raw ||
++----------++ ↓ ↓ || (connection track) ||
|| mangle || +---------------+ +---------------+ || mangle ||
|| filter || <--| IP_FORWARD | | IP_LOCAL_OUT | --------> || nat(DNAT) ||
|| security || +---------------+ +---------------+ || filter ||
++----------++ | | || security ||
|-----------------------------+ ++---------------------++
|
↓ ++----------++
+-----------------+ ||mangle ||
| IP_POST_ROUTING | -----> ||nat(SNAT) ||
+-----------------+ || ||
| ++----------++
| Out
↓
- 這裏以 NF_IP_PRE_ROUTING 爲例:
- 數據包到了這裏, 首先會執行raw 表中的 PREROUTING (chain) 裏面的 rule,
- 然後執行 connection tracking, 接着執行 managle 表中 PREROUTING 中的 rule,
- 最後執行 nat(DNAT) 表中的 PREROUTING 裏的rule
- 以 filter 爲例:
- 只能註冊在 IP_LOCAL_IN, IP_FORWARD, 和 IP_LOCAL_OUT中, 所以只支持 INPUT, FORWARD 和OUTPUT 三個 chain
3. iptables 中的規則(Rules)
- rule 存放在表的忒丁 chain 上, 每個 rule 都有兩部分信息.
- Matching
- matching 是如何匹配一個數據包, 匹配條件很多, 比如, 協議類型, 源/目的 地址, 源/目的 端口, in/out 接口, 保內的數據以及連接狀態.
- Targets
- target 是用於匹配到數據包後 如何做處理
- DROP: 丟棄數據包, 不做任何處理
- RETURN: 跳出當前chaing, 該 chain內的後續rule 不執行
- QUEUE: 將數據包放入用戶空間, 由用戶程序處理
- ACCEPT: 同意數據包通過, 執行後續 rule
- 跳轉到其他用戶自定義的 chain 執行
- target 是用於匹配到數據包後 如何做處理
- Matching
4. iptables 語法
4.1 語法和選項
- 語法:
iptables [-t table] OPTION [chain] rule-specification
- -t table 指定表名
- OPTION 指定選項操作
- chain 指定鏈chain
- rule-speci 規則說明
4.2 選項
- table
filter: 默認表( 不使用-t 指定表時的默認), 包含的鏈有 INPUT, FORWARD, OUTPUT
nat: 在創建新的連接時, 會查看此表. 包含的鏈有 PREROUTING, OUTPUT, POSTROUTING
mangle: 用於修改 數據包, 包含的鏈有: PREROUTING, OUTPUT, INPUT, FORWARD, POSTROUTING
raw: 該表用於和 NOTRACCK 配合設置耿總路由的豁免, 具有需要較高的優先級的鉤子上註冊, 因此 ip conntrack 或者其他表調用之前, 內置的鏈有 PREOUTING, OUTPUT
security: 用於設置強制訪問網絡規則, 配合 selinux 規則使用.
- OPTIONS:
# 規則相關
-A: --append 追加規則到所選擇的鏈的末端, 當 源/目的 地址爲多個時, 會爲每個可能的地址配備一個規則.
-I: --insert 再選中的鏈中插入規則, 可以選擇規則號, 如果沒有指定則默認插入到 第一條
-D --delete 刪除一條或多規則, 可以刪除規則號, 或者匹配規則
-C --check 檢查選中鏈 是否存在和規範的規則,
-R --replace 替換選中鏈中的 規則, 如果 源/目的 地址有多個, 會設置失敗, 規則號從 1開始
# 鏈相關
-N --new-chain chain 創建一個新的用戶定義鏈.
-L --list 列出選中鏈的所有規則, 如果沒有選擇鏈, 則列出所有, 常用於配合 -n (不使用 dns解析),
-F --flush 清空選中鏈的 所有規則
-X --delete-chain 刪除用戶自定義的空鏈.
-E --rename-chain 重命名鏈
-P --policy chain 指定鏈上到的 默認策略(ACCEPT, DROP, REJECT)
# 重要參數
-i: --in-interface 指定接受 數據包的接口, (僅用作INPUT, FORWARD, PREROUTING 鏈), 可以使用 ! 符號表示取反,
-o --out-interface 指定發出數據包的接口 (作用 OUTPUT, FORWARD, OUTROUTING 鏈), 可用 ! 取反
-p: --protocol 指定協議,
--sport: 源端口
--dport: 目的端口
--icmp-type: 指定協議爲 icmp 的類型,(Ping)
-s: --source address 指定該條規則的定的源, 可以是 主機名, 網絡名, ip網段(掩碼), 也可以是 ip地址
-d: --destination addr 指定該條規則的 目的地, 地址和 source 一樣
-m: --match match 指定要使用的匹配項, 測試特定的擴展模塊, 匹配的合集構成了條件
-j: --jump target 指定給你規則目標, 即, 如果匹配成功, 如何去做, 目標可以是用戶定義的鏈, 或者一個擴展.
-g: --goto chain 指定用戶的 鏈中繼續處理 和 jump 不同, 彙報不會繼續.
# 其他選項
-v: --verbose 更詳細的顯示
-w: --wait 設置抓用鎖, 等待時間
-n: --numeric 數字輸出, ip和 端口號 使用 數字顯示
-m
指定匹配模塊以及擴扎模塊
mulitiport: 指定多端口, 最大15個, 端口可以是 N-M,或範圍, 這些端口只能是同一個協議下的. 如 udp, tcp, dccp, sctp
--dport 目的端口
--sport 源端口
iprange: 指定ip範圍
--src-range 192.168.1.100-192.168.1.200 # 範圍內的源ip
--dest-range
time: 如果分組到達時間在給定範圍內, 則匹配, 所有選項都可以設置,
該項可以設置定時允許訪問網絡, 定時關閉訪問.
--datestart hh:mm[:ss] 開始時間
--datestop hh:mm[:ss] 結束時間
--monthdays: 指定每月的 day1,day2... 通過匹配
--weekdays: 指定每週的 day1, day2... 通過匹配
icmp: 如果協議是icmp , 則可以用這個選項
--icmp-type {type[/code] |typename}
允許指定ICMP烈性, 可以是數字類型, 名稱, 代碼, 或二者ICMP類型之一 iptables -p icmp -h
mac: 源端mac 匹配
limit: 限制, 該模塊用作有限速率匹配, 可以結合日誌做限速日誌,
--limit 速率[秒/分/時/天][second/minute/hour/day]
最大平均速率, 指定值, 默認是3小時
--limit-burst NUM
匹配最大的初始分組, 當達到上面設置的值, 將可以突破 NUM 次
hashlimit: hashlimit 是使用hash 算法來記錄匹配一組連接的速率.
分組可以由每個主機組(源/目的 地址) 和/或 端口來匹配.
可以使用N package.
length: 用與匹配長度.
string: 對報文中的應用層數據做字符串模式匹配檢測, (通過算法實現)
--algo(bm|kmp): 字符匹配查找時使用的算法
--string 'STRING' 查找的字符
--hex-string "HEX_STRING" : 使用16進制格式
connlimit: 每個IP併發連接數量限制
--connlimit-upto n 連接數小於 n 匹配
--connlimit-above n 連接數大於 n 匹配
state: 追蹤請求和相應之間報文狀態:
5種狀態:
INVALID: 無法識別的連接
ESTABLISHED 已建立的連接
NEW, 新連接請求
RELATED, 相關聯的連接 的一個新請求
UNTRACKED 未追蹤的連接
規則:
對進入的 ESTABLISHED 都應該放行
對出去的 ESTABLISHED 都應該放行
檢查管理 進入狀態的 NEW 連接
拒絕 進出 的 INVAIED
ipvs: 匹配ipvs 連接特性
--ipvs: 分組屬於ipvs 連接
--vproto proto : 匹配vip 協議, 按 編號或名稱, 如 TCP
--vaddr: vip 地址,
--vport: 匹配vip 端口號
--vdir: vip 報文流向
--vmethod: ipvs 轉發方式
- 處理動作
ACCEPT: 允許數據包通過
DROP: 丟棄數據包, 不迴應
REJECT: 拒絕數據包通過, 會返回響應信息
LOG: 在日誌中記錄信息, 並放給下一個規則
QUEUE: 防火牆將數據包交給用戶空間
RETURN: 防火牆執行當前鏈的 後續 Rule, 並返回到調用鏈
REDIRECT: 端口從定向
MARK: 做防火牆標記
DNAT: 目標地址轉化
SNAT: 源地址轉換
MASQUEREAD: 地址僞裝
5. iptables 實戰示例
- 查看當前防火牆狀態
- 首先爲ssh 端口開放
- 此時可以看到默認規則是accept, 將其改爲 DROP 然後測試
- 開放 TCP 的 80端口
- 此時會發現由於設置了
-P OUTPUT DROP
所以本機無法建立新的連接. - 所以需要設置
-P OUTPUT ACCEPT
, 不過此處我使用了-m state --state NEW,ESTABLISHED -j ACCEPT
對新建立的連接和 已建立的連接,放行
- 不讓其他主機ping 本機, 但是本機可以ping 其他地址
- 這裏需要準備規則有
-
- 禁止其他地址的 icmp 協議進入, 或者本機 INPUT表默認是 DROP.
-
- 本機 OUTPUT 需要允許 ICMP協議包, 或者允許新建的連接和已建立的連接 (state NEW,ESTABLISHED)
-A OUTPUT -p icmp -j ACCEPT
-
6. iptables nat 轉發實例
6.1 環境
-
網絡:
- 外網: 192.168.10.0/24
- 內網: 192.168.20.0/24
-
服務端:
- 外網IP: 192.168.10.11/24
- 內網IP: 192.168.20.11/24
-
客戶端:
- IP: 192.168.20.3/24
-
服務機
- 客戶機
6.2 配置操作
- 服務端開啓內核的 ip 轉發
- 需要將服務端的 內網接入數據包配置轉發,
- 將客戶端的 默認路由設置爲 服務端的內網IP
6.3 操作
- 服務端開啓內核的轉發
[root@node10011 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@node10011 ~]# grep forward /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@node10011 ~]# sysctl -p
-------------------
# 或臨時生效
[root@node10011 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
- 添加IP 轉發規則
iptables -t nat -I POSTROUTING -d 192.168.20.0/24 -j ACCEPT --to 192.168.10.11
- 客戶端添加默認路由信息
[fangfc@node10003 ~]$ ip route
169.254.0.0/16 dev eno33554960 scope link metric 1003
192.168.20.0/24 dev eno33554960 proto kernel scope link src 192.168.20.3
[fangfc@node10003 ~]$ sudo ip route add default via 192.168.20.11 dev eno33554960
[fangfc@node10003 ~]$
[fangfc@node10003 ~]$ ip route
default via 192.168.20.11 dev eno33554960
169.254.0.0/16 dev eno33554960 scope link metric 1003
192.168.20.0/24 dev eno33554960 proto kernel scope link src 192.168.20.3
- 添加DNS
- vi /etc/resolv.conf
- 測試
END