歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

Linux內核轉發技術

前言

在linux內核中,通常集成了帶有封包過濾和防火牆功能的內核模塊, 不同內核版本的模塊名稱不同,
在2.4.x版本及其以後的內核中, 其名稱為iptables, 已取代了早期的ipchains和遠古時期的ipfwadm.
在命令行中可以通過lsmod | grep -i iptable來查看當前加載的相關模塊信息.

iptables作為內核模塊, 由一些信息包過濾表組成,這些表包含內核用來控制信息包過濾處理的規則集.
與此同時, iptables也作為用戶空間(userspace)的一個管理工具而存在,使得我們使插入,
修改和除去信息包過濾表中的規則變得非常容易,不需要每次修改規則後都重新編譯內核.
本文主要討論的也正是iptables在用戶空間的功能.

基本概念

linux內核的轉發機制主要通過查表(tables)來完成, 而iptables則用來設置,管理和檢查linux內核中ip包過濾規則表.
table後面加了s說明可以定義多張表, 而每張表中又包含了若干鏈路(chains), 鏈路表示一系列應用於匹配ip包的規則(rules).
下面就對這"三座大山"分別加以解釋. 為了使概念明了, 我們自底向上說明:

規則(rules)

規則又稱為rule-specification, 其主要作用是匹配特定的ip封包, 並作出相應的動作, 其格式為:

rule-specification = [matches...] [target]

其中,

match = -m matchname [per-match-options]
target = -j targetname [per-target-options]

matchname表示匹配的格式的名稱, targetname表示所執行的動作的名稱. iptables定義了一系列內置的格式和動作,
如target為accept表示接受, masquerade表示執行類似路由器的動作(用於nat)等, 具體可以通過man iptables-extensions查看.

鏈路(chains)

所謂鏈路, 顧名思義就是表示ip數據包傳輸的路徑, 一個封包的源和目的不同, 其走的路徑即有可能不同,
就像路途中的朋友們, 在任何一個節點都有可能分道揚镳.這些節點有:

  • pre_routing : 外部數據剛剛進入時.
  • post_routing : 外部數據准備離開時.
  • input : 數據包的目的地址為本地socket.
  • output : 數據包由本地生成.
  • forward : 數據包被本機轉發.

事實上, 鏈路在內核中以鉤子的形式存在, 在每個結點給用戶預留了回調函數來處理封包(即用前面提到的規則).
ip封包從外部進入後,所經過的鏈路如下圖所示:

網口接收到ip封包後, 首先經過mangle和nat表的pre_routing表的處理, 然後判斷是否目的地址為本機的應用程序,
若是則往左邊的路徑往下, 由接收程序處理完後再發出. 在未開啟內核轉發的情況下, 目的地址不為本機的ip包都會丟棄掉,
若開啟了轉發則往右邊路徑將其從網口轉發出去. 在圖中每個鏈路點都能對ip包做相應的修改和過濾.

注意: prerouting鏈只會匹配流的第一個包,也就是說,這個流的所有其他的包都不會被此鏈檢查.
因此prerouting鏈只能做網絡地址轉換,不能被用來做任何過濾.

表(tables)

當前最新版本的iptables中包含了五個獨立的表, 工作時使用哪張表取決於內核選項以及當前應用了哪個模塊. 各表說明如下:

  • filter: filter表為(iptables命令)默認使用的表, 包含input,forward和output鏈路.
  • nat: 當遇到一個創建了新鏈接的ip包時, 內核就會查找nat表, 其包含了prerouting和postrouting鏈路.
  • mangle: mangle表用於專門的封包修改,如改變tos,ttl,mark等. 在內核2.4.17之前只包含prerouting和output鏈路,
    在之後的版本中增加了input,forward和postrouting鏈路.
  • raw: raw主要用來在連接跟蹤中配置notrack行為, 其在netfilter的hook注冊了更高優先級的回調,因此可以在ip_conntrack表
    亦即其他ip表之前被調用. raw包含了prerouting和output鏈路.
  • security: security表用於命令訪問控制(mandatory access control, mac)網絡的規則. mac由linux安全模塊如selinux實現,
    security表在filter表之後調用, 提供了input,output和forward鏈路.

具體應用

工具的產生終究要服務於生產, 光解釋名詞也不能形象地展現linux強大的內核轉發機制,因此以幾個小例子來說明iptables的
具體使用, 並依據上述介紹來寫出有實際效用的腳本. iptables命令的一般格式如下:

iptables [-t table] {-a|-c|-d} chain rule-specification

其中命令分為三部分,亦即上面說到的指定表,鏈路和規則

-t table指定表的名字, 若不指定則默認為filter.
-a chain表示在鏈路中增加規則, -c和-d分別表示檢查和刪除.
剩余部分指定規則, 格式為`[matches...] [target]`

完整的命令可以通過iptables的manpages查看.

例1.作為防火牆

假設這麼一種場景, 我們連接上了一個煩人的局域網, 為什麼說它煩人呢? 因為局域網內有很多腳本小子,
來來回回掃描不說, 還在某些端口進行爆破. 因此我想簡單生成一個防火牆, 除了網關不允許子網內任何其他的
ip對我進行連接, 甚至連ping都ping不到我.

需求明確, 那麼如何實現呢? 其實很簡單, 只需要以下命令(假設子網為192.168.1.0/24):

#1. 清空現有規則
iptables -t filter -f
#2. 打開網關訪問權限
iptables -t filter -a input -s 192.168.1.1 -j accept
#3. 指定不過濾ping的返回
iptables -t filter -a input -p icmp --icmp-type 0 -s 192.168.1.0/24 -j accept
#4. 關閉其他所有內網訪問權限
iptables -t filter -a input -p all -s 192.168.1.0/24 -j drop

一般來說防火牆策略一般是從非信任->信任,先用策略(-p policy)關閉所有訪問權限,再添加規則按需要逐條打開.
這裡為了簡單就在默認策略(accept)的基礎上添加規則. 各個表的當前策略可以通過iptables -t table -s查看.
要注意的是所有規則是按順序檢查的, 一旦檢查到符合的條件就會執行,而不往下繼續檢查,如果所有規則都不匹配,
則會執行默認的操作(默認策略).因此在逐條添加規則的時候最好是從小到大添加.
在#3命令中,我們打開了icmp type為0的輸入,即ping echo reply封包, 這樣別人ping不到我的同時,我卻能ping到別人,是不是很方便?

例2.作為路由器

在管制的網絡中經常有這麼一種情況, 即內網是綁定mac地址的, 客戶端要接入路由器必須要網絡管理員添加,
因為即使有wifi密碼,連接上之後也無法獲取ip,因而不能上網. 我的pc已經被添加到網絡中,但是手機,平板之類
的設備不想一一要網管去添加, 那該怎麼連上wifi呢? 解決辦法有很多, 在windows下有各種xxx-wifi軟件, linux的
networkmanager也有類似添加熱點的解決方案. 這裡講的是iptables的解決辦法.

現假定筆記本啟動了熱點at0,並已配置好dhcp服務. 我們的子網還是192.168.1.0/24, 熱點的子網為10.0.0.0/24,
共用同一塊無線網卡wlan0. 此時子網的請求會到wlan0上, 但是目的地址不是我, 根據上圖可以知道, 這時
ip封包應該往右邊的路徑轉發出去, 不過需要出去前改變一下網絡地址(即nat, 詳見p2p通信原理與實現).
設置nat轉發的規則也很簡單:

iptables -t nat -a postrouting -o wlan0 -j masquerade

這是在當我們既用wlan0上網,也用wlan0做路由器的時候配置的nat規則,但是這樣性能會不太理想,
更普遍的情況是我們用一個網卡連接網絡(假設為wlan0), 另一個網卡作為路由器(設為wlan1),
這種情況下只需要將wlan1的流量轉發到wlan0上:

iptables -t filter -a forward -i wlan1 -o wlan0 -j accept
iptables -t filter -a forward -i wlan0 -o wlan1 -m state --state established,related -j accept
iptables -t nat -a postrouting -o wlan0 -j masquerade

其中masquerade表示提供一種類似路由器的轉發行為,即為出去的tcp/udp包改變源地址,為進來的包改變目的地址,
用-j snat可以實現同樣功能, 只不過ip地址需要自己指定(這裡為wlan0在內網中的地址). masquerade被專門設計
用於那些動態獲取ip地址的連接,比如撥號上網,dhcp連接等.如果你有靜態ip,使用snat target可以減少開銷.

iptables -t nat -a postrouting -o wlan0 -p tcp -j snat --to-source [wlan0-ip]
# 這裡不需要設置dnat, 因為snat會記住連接,把響應轉發給對應的請求.不過為了例示還是寫出來:
iptables -t nat -a prerouting -i wlan0 -d [wlan0-ip] -p tcp -j dnat --to [client-ip]

這裡值得一提的是, iptables本質上只是過濾和處理數據, 所以准確說是允許將wlan1的流量轉發到wlan0上,
事實上如果用默認策略, forward都是允許的, 不用額外設置.

例3.作為透明代理

不同的人對代理有不同的需求, 最常見的就是http代理, 一般提供了地址和端口號. 我們在浏覽器中配置使用
代理並指定地址和端口後, 上網沖浪的請求會經過代理服務器接收,然後根據需要會從為我們去向目的網站請求內容,
或者從緩存中直接給我們返回內容. 假設我們現在已經配置好並運行了squid代理服務器, 工作在3128端口.
和作為路由器類似, 不過除了改變ip還需要改變目的端口號:

iptables -t nat -a prerouting -i wlan1 -p tcp --dport 80 -j dnat --to [wlan0-ip]:3128
iptables -t nat -a prerouting -i wlan0 -p tcp --dport 80 -j redirect --to-port 3128

透明代理完整的iptables配置可以參考set up squid in linux.

後記

對於linux內核轉發的技術介紹感覺差不多了, 雖然沒有完全表現出其強大的功能,
但相信有需要的人可以根據基本規則來舉一反三; 通過google查看別人的iptables"腳本",
也能獲得很多靈感. 另外關於iptables的更多具體命令,要記得多使用簡單的辦法查閱(man iptables).

參考資料

  • iptables指南
  • iptables/netfilter原理

博客地址:

  • pannzh.github.io

歡迎交流,文章轉載請注明出處.

Copyright © Linux教程網 All Rights Reserved