
我正在學習私有/公用 IP、連接埠轉送和 NAT,但仍然看不到一個簡單問題的答案:
假設同一網路上的兩個使用者正在與其網路外部的單一伺服器進行通訊(例如,我和我的妻子向 yahoo.com 發送 http 請求)。伺服器將兩個使用者視為單一公用 IP,並且通常(如本例所示)在同一連接埠上進行通訊。路由器如何根據這兩個不同的連線來路由封包呢?資料包內是否有 ip/連接埠之外的任何路由資訊?是否在某處維護了一些「會話表」?它由誰以及具體包括哪些內容?
答案1
電腦內部、行程之間
首先讓我們看看如何單身的電腦區分並發連接。
大多數傳輸協議,例如 TCP、UDP、SCTP使用二港口、來源地和目的地– 即連接兩端各一個。也就是資料包不要只需“穿過”港口即可;相反,他們旅行從埠 X到Y 港。
這目的地連接埠通常是眾所周知的(80 用於 HTTP,53 用於 DNS…),但是來源連接埠通常由作業系統本身隨機選擇,這也確保了 src/dst 組合是唯一的。
因此,當您的瀏覽器建立多個「到雅虎連接埠 80」的連線時,所有這些連線實際上都有不同的來源連接埠,並且作業系統保留一個套接字表,例如:
PROCESS PROTO LOCAL REMOTE STATE
9894/firefox tcp 192.168.6.175:39163 google.server:80 established
9894/firefox tcp 192.168.6.175:52909 yahoo.server:80 established
17463/chrome tcp 192.168.6.175:64981 yahoo.server:80 established
9894/firefox udp 192.168.6.175:4984 8.8.8.8:53 --
因此,當作業系統從yahoo.server:80
本機連接埠 52909 接收到 TCP 封包時,它可以將其對應到 Firefox 建立的特定連線。
需要注意的是,這與 NAT 無關然而,即使您直接連接,也會以相同的方式發生。 (不過 NAT 會利用它。)
(您可以使用netstat -n
、 或 Windows 上的各種圖形工具查看此表。通常“本地/遠端”被標記為“來源/目標”,儘管這並不完全準確。)
在 NAT 網路內、電腦之間
關於 NAT 的問題的答案非常相似,只是一切都是在更大範圍內完成的。
執行 NAT 的路由器保留一個包含內部和外部位址和連接埠的「狀態」表。例如,如果您的兩個 HTTP 請求使用單獨的 TCP 連接,則它們可能會被追蹤為:
PROTO ORIG-SRC ORIG-DST REPLY-SRC REPLY-DST
6/tcp 192.168.6.42:52909 yahoo.server:80 yahoo.server:80 your.public.ip.addr:52909
6/tcp 192.168.6.175:39163 yahoo.server:80 yahoo.server:80 your.public.ip.addr:39163
6/tcp 192.168.6.175:52909 yahoo.server:80 yahoo.server:80 your.public.ip.addr:28330
17/udp 192.168.6.175:4984 8.8.8.8:53 8.8.8.8:53 your.public.ip.addr:4984
當路由器收到來自 REPLY-SRC (Yahoo) 的發送至 REPLY-DST(您的公共 IP 位址)的封包時,它知道真實的為了撤銷 NAT,必須從 ORIG-SRC 欄位取得目的地。
(如果沒有匹配狀態,則處理手動配置的連接埠轉送規則。如果仍然沒有匹配,則封包實際上是發送給路由器本身的。)
注意狀態表如何包含地址和連接埠,允許透過連接埠組合區分對同一伺服器的多個連接。在我的範例中,兩台電腦意外地使用了相同的連接埠組合,因此第二個連接的連接埠也被轉換。
(事實上,有些 NAT 看起來僅有的在連接埠處並完全忽略來源位址;這減少了可能的連線數量,但使點對點程式更容易執行「NAT 打洞」。
即使對於無連線協定(例如 UDP 或 ICMP)也會保留這種狀態,因此即使沒有明確的「關閉連線」資料包,條目也會在一段不活動時間間隔後過期。 (狀態表實際上是防火牆的一部分,因此即使未完成 NAT,路由器仍可能使用它來區分「活動」連線和雜散資料包。)
(如果您的路由器是基於 Linux 的,conntrack -L
或cat /proc/net/nf_conntrack
會顯示此表。對於 OpenBSD 或 pfSense,請嘗試pfctl -s state
。)