iptables簡要介紹及使用iptables實踐NAT技術

簡介

iptables的文章多如牛毛,但是,我讀了一些,發現雖然成體系,但是不便理解,今天就結合自己的理解,好好講解下,另外,我們也會使用iptables來實驗一個nat地址轉換的demo,nat轉換,通俗地講,一般是爲了解決ipv4公網地址不夠用的問題,因此在學校、公司等機構的有公網ip的服務器上,部署nat軟件進行地址轉換,如內網機器訪問互聯網時,將源地址轉換爲服務器的公網ip;在收到響應時,此時目的地址是公網ip,此時需要修改爲內網機器的地址。

這個東西,教科書裏學了很多年了,沒想到還能走進現實,也是有點意思。

iptables和netfilter的關係

iptables運行在用戶態,netfilter運行在linux內核中。iptables相當於一套界面,可以將防火牆規則寫入內核中的一片內存區域,而netfilter會去讀取這片內存區域中的規則,根據規則進行對應的網絡包處理,如丟棄、放行等。

正因爲如此,我們需要手動安裝iptables,如yum install -y iptables-services,但是,netfilter是linux內核本身自帶的,無需安裝。

簡單來說,netfilter纔是核心,你要覺得iptables不好用,可以換其他的命令行、圖形界面工具,甚至自己寫也可以。當然,netfilter和iptables都是同一個團隊弄的,因爲它不可能讓大家直接寫代碼去操作netfilter,肯定還是得搞個好用的命令行工具給大家用吧,所以有了iptables。

而且,現在團隊覺得iptables還是不夠好,目前新搞了個nftables來取代iptables。

項目官網:https://www.netfilter.org/index.html

網絡包的流向

大概有這麼幾種網絡包:

  • 從網卡進來,但是目的地址不是當前機器(如當前機器僅負責路由轉發、防火牆等),此時,不需要交給本機進程處理,直接按照路由錶轉發出去
  • 從網卡進來,目的地址是當前機器,此時,會交給本機的進程處理(如tcp的話,會根據端口號找到對應進程)
  • 本機要向外發送的數據庫包,不管是請求其他遠程服務(此時作爲客戶端,會主動向外發包),或者是本機作爲服務器,對外部進來的請求包做出迴應。這兩種,都算是要出去的包

如果讓你來設計,你應該也會引入幾個時間點,在這個時間點,主動去查詢用戶定義的規則,看看規則中是要丟棄還是放行數據包。

時間點的考慮,也很重要。

比如,針對網卡收到的數據包的處理,第一個時間點,應該是在檢查路由表之前(即檢查目的地址是否是本機之前),此時,給用戶提供一個介入的時機,用戶甚至可以修改這個數據包,比如,本來是發給當前機器的,我可以將目的地址改爲其他機器,這就是DNAT(nat分爲修改源地址和目的地址,這裏說的這種,就是修改目的地址)適用的場景;

第二個時間點,應該是在路由決定做出之後,在交給進程處理之前;

第三個時間點,應該是進程處理完成後,假如需要回應,即進程將數據包交給我們後,此時也可以進行處理

另外,針對那種路由轉發的數據,在轉發出去之前,應該也可以進行一些處理。

這些時間點呢,一般就是擴展點,就像spring裏面一樣,bean的創建過程中有很多時間點會回調用戶的函數,用戶就可以註冊自己的回調函數,進行一些特殊的邏輯處理。

netfilter中的擴展點

Netfifilter一共在內核的網絡協議棧中,插入了5個擴展點(官網叫hook)。我參考瞭如下文章:

https://www.usenix.org/system/files/login/articles/892-neira.pdf

  • PREROUTING:

    All the packets, with no exceptions, hit this hook, which is reached before the routing decision。

    Port Address Translation (NAPT) and Redirections, that is, Destination Network Translation (DNAT), are implemented in this hook.

​ 這個時間點,就是所有的網絡包在做出路由決定前,就會調用本hook。一般來說,端口轉換和重定向、DNAT(目標地址轉換)就是在這裏實現

  • LOCAL INPUT:

    All the packets going to the local machine reach this hook. This is the last hook in the incoming path for the local machine traffific.

​ 在檢查目的地址後,發現包是發給本機的,那麼這些包在交給進程之前,就會調用本hook。

  • FORWARD:

    Packets not going to the local machine (e.g., packets going through the fifirewall) reach this hook.

​ 所有不是發往本機的包,即本機充當路由轉發功能時(linux主機實現爲路由器或防火牆等),會調用本hook

  • LOCAL OUTPUT

    This is the fifirst hook in the outgoing packet path. Packets leaving the local machine always hit this hook.

    本機對外部請求的回覆包或者對外發起的請求包,就會觸發這個hook

  • POSTROUTING

    This hook is implemented after the routing decision. Source Network Address Translation (SNAT) is registered to this hook. All the packets that leave the local machine reach this hook.

​ 在做出路由決定後,調用本hook。源地址轉換,基本就在這個hook階段完成。所有要離開本機的數據包,就會觸發本hook。

具體可以看下圖:

image-20230723203225034

​ 按照這篇文章的提法,主要有下面幾種網絡包流向:

Therefore we can model three kind of traffific flflows, depending on the

destination:

■ Traffific going through the fifirewall, in other words, traffific not going to

the local machine. Such traffific follows the path: PREROUTING 、

FORWARD、 POSTROUTING.

僅僅穿越本機的流量包,即,目的地址不是本機,這樣的網絡包,會依次經歷:

PREROUTING 、FORWARD、POSTROUTING

■ Incoming traffific to the fifirewall, for example, traffific for the local

machine. Such traffific follows the path: PREROUTING INPUT.

發給本機的流量包,路徑爲:

PREROUTING 、LOCAL INPUT

■ Outgoing traffific from the fifirewall: OUTPUT POSTROUTING.

本機生成的,要出去的流量包(別管是回覆別人的那種還是自己發起的,對機器來說都一樣,都是要出去的),經歷:

OUTPUT 、POSTROUTING

幾個時間點說清楚了,那麼,這些時間點,回調我們的時候,是查詢我們設置的防火牆規則對吧,那麼,規則大概長啥樣呢?

iptables -I INPUT  -p tcp --dport 8080 -j ACCEPT

比如,上面這就是一個規則,其中,-p tcp --dport 8080就是指定要篩選出哪些數據包來處理,如目標端口8080的,那麼,怎麼處理呢,這個-j ACCEPT就表示放行。

另外,我們也不可能就一個規則吧,這個規則處理8080的,那我還有其他處理8081端口的規則,所以,最終是一堆規則,一個規則列表。

此時,我們就可以往每個hook點,註冊上一個規則集合,即一個規則鏈,按鏈中順序,依次處理。

那麼,iptables是這樣搞的嗎,我們來看看。

iptables中的規則組織形式

此時,可以看下圖:

image-20230723204335084

在每個hook點,如左下角的PREROUTING,按理說只需要有一個規則集合就夠了,爲啥有三個黃色方塊(它們唯一指向了一堆PREROUTING階段的規則集合),也就是說,怎麼有三個規則集合呢?

其實,就是因爲不同規則大相徑庭:

  • 有的規則最終是進行NAT轉換,只改改ip、端口這些;
  • 有的規則是進行大改,甚至修改報文,如ip報文中的Type of Service字段
  • 有的規則呢,根本不去動報文,完全不改,比如我們可能就是想打個日誌記錄下報文
  • 還有的規則,是檢查報文,檢查完成後,比如防火牆,發現指定端口是不開放的,那麼可以直接丟棄報文或者拒絕報文(分別造成客戶端讀超時、連接reset等異常)
  • 其實還有很多種目標動作

然後,官方就大體根據這些規則,進行了分類,把一個大集合,分成了好幾個集合,比如nat集合負責nat相關規則、mangle集合負責改報文字段的規則,如Type of Service、raw集合呢,目前我接觸到的有trace、log等規則、像filter呢,就負責對報文檢查後進行篩選過濾。

另外呢,像一個報文的生命週期,可能會依次經過:

PREROUTING 、LOCAL  INPUT

那麼,在這兩個階段,我們都可以執行規則,比如,filter集合裏的規則,在這兩個hook點都可以執行,所以,filter表中,包含了多個hook點的規則集合;像nat集合裏的規則呢,一般就在PREROUTING 、POSTROUTING這兩個階段發揮作用,所以呢,nat表,包含了PREROUTING 、POSTROUTING兩個hook點的規則集合,兩者互不影響,井水不犯河水。

我個人喜歡上面那張圖,下面這張也可以參考:

image-20230723210256615

網上還有一張圖,我覺得也很棒(https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg):

image-20230723210446254

下圖是隻針對轉發這種場景,也不錯,圖都是來源網絡,侵刪:

image-20230723214351472

如何使用iptables對規則集合進行增刪改查

比如,上圖中,我想操作左下角的prerouting階段的raw表:

// -t 指定表名,如raw,-I 表示插入,chain表示在哪個鏈插入,如PREROUTING,rulenum呢,是在PREROUTING鏈中插入到第幾個,後面的rule-spe就是規則定義:篩選包+對包的操作
iptables [-t table] -I chain [rulenum] rule-specification

比如,我想trace一下發往8080端口的包:

iptables -t raw -I PREROUTING -p tcp -m tcp --dport 8080 -j TRACE

其他操作:

// -R,替換,即修改
iptables [-t table] -R chain rulenum rule-specification
// -D 刪除
iptables [-t table] -D chain rulenum
// -L 查詢,一般組合使用iptables -nvL,默認查看filter表
iptables [-t table] -L, --list [chain]

其他命令參考man iptablesman iptables-extensions(包含了各種目標操作的講解)

nat實驗

簡介

image-20230723212111654

看我上面的圖,server1沒有實際監聽8080端口,server2有監聽,假設我客戶端只能直接訪問server1,那麼,我想做的是,在server1上靠iptables的dnat,修改目的ip爲server2,達成我訪問server2的8080服務的目的。

server1開啓轉發能力

// 沒有持久化,臨時修改
echo 1 >/proc/sys/net/ipv4/ip_forward
// 查看
[root@hx168-access ~]# sysctl -p
net.ipv4.ip_forward = 1

因爲server1沒有監聽8080端口,那肯定不能自己處理,所以必須轉發給server2,所以需要開啓這個功能

增加trace規則,方便調試

iptables -t raw -I PREROUTING -p tcp -m tcp --dport 8080 -j TRACE
iptables -t raw -I PREROUTING -p tcp -m tcp --sport 8080 -j TRACE

目標端口爲8080的,表示客戶端發出來的;源端口爲8080的,表示server2回覆的。都加上trace

有問題就去看/var/log/messages日誌

在PREROUTING增加DNAT規則

iptables -t nat -I PREROUTING 1 -p tcp -m tcp   --dport 8080 -j DNAT --to-destination  10.80.121.115

即,在網絡包剛進來時,因爲目標ip是server1,此時如果不進行目標ip修改,就會交給本機處理,所以,我們不能讓這事發生,得改成server2.

在filter表的forward鏈,增加放行規則

iptables -t filter -I FORWARD 1 -p tcp -m tcp --dport 8080 -j ACCEPT
iptables -t filter -I FORWARD 1 -p tcp -m tcp --sport 8080 -j ACCEPT
正向的和反向的,各加一個,免得一會還要再加

在nat表的POSTROUTING鏈,增加SNAT規則

iptables -t nat -I PREROUTING 1 -p tcp -m tcp --dport 8080 -j SNAT --to-source  10.80.121.114

因爲此時發往server2的報文裏,源ip還是客戶端的ip,如果就這麼發過去,server2就會返回報文給客戶端,而不是server1,所以得改源ip爲server1.

測試

image-20230723213446750

可以看到,完全沒問題。

網絡報文

在執行上述命令測試時,我在server1上抓包了:

tcpdump -i any tcp port 8080 -w 114.pcap

然後分析114.pcap時,發現就是如下這樣,一個簡單的三次握手也不簡單:

image-20230723213700210

疑問

我一開始有疑問,當server2給server1返回時,目標ip爲server1,我們也沒有配置什麼NAT規則,把目標ip改成客戶端的ip,那麼,服務器爲啥不是把報文交給server1的進程處理,而是原路forward轉發呢

這個其實還是因爲NAT依賴了netfilter的會話跟蹤功能,簡單來說,netfilter是有狀態的,以tcp舉例,tcp連接的建立是因爲客戶端ip:客戶端端口和服務端ip:服務端端口,這個四元組是有來有回的,就是我給你發了消息,你也回我了,此時,netfilter就認爲這是一個會話。

所以,在server2給server1返回時,server1拿着server2和server1之間的四元組去查,查到有會話,因此,就按照之前的路徑,原路回來。

另外,nat這個table裏的鏈,只在檢測到之前不存在會話時,纔會進,後續就不會再進了;也就是隻有首次報文的時候進nat的鏈

這個可以參考:

https://serverfault.com/questions/741104/iptables-redirect-works-only-for-first-packet/741108#741108

像上面這個案例,只要執行如下命令,關閉會話跟蹤,就執行不成功了:

iptables -t raw -I PREROUTING -p tcp -m tcp -dport 8080 -j NOTRACK

查看會話的命令、工具

[root@hx168-access ~]# cat /proc/net/nf_conntrack
ipv4     2 tcp      6 118 TIME_WAIT src=10.0.240.103 dst=10.80.121.114 sport=8922 dport=8080 src=10.80.121.115 dst=10.80.121.114 sport=8080 dport=8922 [ASSURED] mark=0 zone=0 use=2
yum install conntrack-tools

[root@hx168-access ~]# conntrack -L
tcp      6 118 TIME_WAIT src=10.0.240.103 dst=10.80.121.114 sport=9072 dport=8080 src=10.80.121.115 dst=10.80.121.114 sport=8080 dport=9072 [ASSURED] mark=0 use=1

參考文章

https://www.jianshu.com/p/0fe6aeec8d79,圖不錯

https://www.linux.org/docs/man8/iptables-extensions.html

https://gist.github.com/tomasinouk/eec152019311b09905cd 關於nat

https://www.netfilter.org/documentation/

https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html#ss3.1

https://www.usenix.org/system/files/login/articles/892-neira.pdf

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