網路埠對映的原理

2022-04-13 21:22:07 字數 4082 閱讀 9279

docker有容器內外的埠對映,是怎麼做到的呢?這是要起乙個新的網路的namespace吧;

啟動了docker之後,在docker上面還是有確實是有iptables的項,但是此時應該是有兩個網路的namespace吧,使用ip netns list是沒有看到的,也就是說其實是在乙個網路的namespace中的網路埠的對映;

chain postrouting (policy accept)

target prot opt source destination

masquerade all -- 172.17.0.0/16

anywhere

masquerade tcp -- 172.17.0.2

172.17.0.2 tcp dpt:1234

chain docker (

2references)

target prot opt source destination

return all --anywhere anywhere

dnat tcp -- anywhere anywhere tcp dpt:32769 to:172.17.0.2:1234

在iptables的輸出中有如上的兩條規則,然後docker會啟動乙個proxy:

/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32769 -container-ip 172.17.0.2 -container-port 1234

把收到的tcp包透傳給容器?

這種埠的對映在核心裡做個轉化就好了吧?0.0.0.0:32769 --> 172.17.0.2:1234

系統中多了這樣一張網絡卡:

veth485dee9 link encap:乙太網  硬體位址 f2:c6:f3:6c:4f:7a  

up broadcast running multicast mtu:1500 躍點數:1接收資料報:14 錯誤:0 丟棄:0 過載:0 幀數:0傳送資料報:46 錯誤:0 丟棄:0 過載:0 載波:0碰撞:0 傳送佇列長度:0接收位元組:1088 (1.0 kb) 傳送位元組:4987 (4.9kb)

這裡就是個veth裝置了,容器內外各有乙個,從容器中來的資料直接就導流到了網橋上

啟動了多個docker,

ip netns list 看到的內容和 ip netns list-id看到的內容為啥不是一樣的?

如果多個容器把自己的都繫結到宿主機的8080埠咋樣?不能做,本地的埠已經被對映掉了;也就是說,不可能實現,同一臺主機兩個容器內同時監聽8080埠;回到原來的問題上,建立乙個

ip netns list是從/var/run/netns中去讀取內容,但是現在如果沒有內容呢?

核心是如何檢視網路的引數的? man ip-netns

ip netns list-id - list network namespace

ids (nsid)

network

namespace

ids are used to identify a peer network

namespace

. this command displays nsid of the current network

namespace

and provides the corresponding iproute2 netns name

(from /var/run/netns) if any.

看下這個命令是幹嘛的? network namespace ids(nsid) 列出系統中所有的peer網路ns,如果這個對等網路有名字,那麼會列出名字;所以ip netns list-id中所有的明明空間呢;

所以命名空間分為兩類:named network namespace  & peer network namespace [不糾結這個小事了,因為從/proc//ns/net看確實是不同的網路的命名空間了]

下面看在宿主機上如何完成埠的對映;使用iptables;

想下之前的nat的設定,都是在postrouting時轉換網路的ip位址,然後在接收到資料報時,系統會用自動生成的reverse功能把資料報給轉回來,這樣的話宿主機內的路由就會把這包送給容器內位址了【這裡有個小gap:宿主機什麼時候決定丟包?

step3:進入本機的路由;【是哪個引數可以本機路由了呢?ipv4.ip_forward=1?】在協議棧裡面是如何處理的呢?是否真的有本機路由這件事情? 從wireshark看確實是有的,這一點是wuyongzhiyi.

//外面的機器不應該能訪問到我本機器上的一台虛擬機器,因為這台虛擬機器是我內網的,要保護起來,現在的各種nat機制也不支援;但是我這台docker虛擬機器是可以對外提供服務的呀;比如所有對1000號埠的訪問都引流到我這台機器上就好啦:

作如下試驗:網路拓撲結構

樹莓派       a:

主機pc       b:

主機上docker容器: c:

sudo iptables -t nat -a prerouting -d [b位址] -p tcp -m tcp --dport 10000 -j dnat --to-destination 【容器c位址】:10000

測試時在容器上啟動乙個伺服器監聽10000埠,在主機b上也啟動乙個程序監聽10000埠,如果在容器內監聽到資料,那麼就說明設定成功了。

------

說一些題外話,剛才我們發現樹莓派其實是ping不同我容器的位址的,那麼我們能不能hack一下,通過增加一段路由以及icmp的配置來讓我的樹莓派能平通我的容器呢?

我們首先來分析下為啥我的容器收不到這個包,是因為我的主機上並沒有172.17.0.2這樣的乙個裝置,所以甚至這個包都進入不了路由。。。所有關鍵的問題還是變成扔包到底發生在哪一步?!

我宿主機根本就不會去應答這個資料報,是因為宿主機上現在沒有乙個網絡卡的位址是172.17.0.2,如果想讓我的網絡卡收到包,是不是配置乙個附屬的ip位址就可以了?

1) 首先我隨便新增了乙個乙個tap0裝置在我的機器山,發現ping是ping通了【注意此時tap0上並沒有流量】

2) 去掉tap0,然後試著在這個網絡卡上配置多個ip試一下:試過同樣可以。。。。但是不知道怎麼把這個副網絡卡給刪除掉了;

好了,今天算是搞明白了在prerouting處加dnat是怎麼把包匯入到容器裡的;其實,新手看東西總是想象力豐富,之前自己還在prerouting處我如何能把特定的ip位址匯入到特定的容器,即根據ip位址路由,。。。這個好像是沒有應用場景。。。不,等等,這個不就是負載均衡的實現麼,根據ip位址把流量匯入到不同的機器中;這個該咋做?答案:sudo iptables -t nat -i prerouting -p tcp -m tcp -j dnat --to-destination 172.17.0.2【測試通過,符合預期】

///-----剛一眨眼,發現,樹莓派竟然和我容器裡的位址去通訊了,所以這裡副網絡卡的作用真是不得了,他告訴了區域網我能達到的網路的能力

說道這裡,乙個網絡卡接收到了資料報怎麼還會路由呢。因為有的時候這台機器就是個網絡卡,是路由器,怎麼說?

還是那剛才說我怎麼樣從樹莓派ping通我的容器來說,我的目的位址是172.0.0.2,然後我把pc當成了閘道器,這個時候奇妙的事情發生了,我的pc機收到了乙個網路包,但是這個包的目的位址不是自己,於是這個資料報開始在主機內路由了,路由表發現我所有172.0.0.2的資料報都交給docker網橋傳送出去,於是把包發給了網橋bridge0,bridge拿到了資料報之後,網橋就開始在自己的域內廣播,廣播後發下了我的docker容器裡的位址了,所以容器裡的網絡卡就接受這個資料報咯,然後應答,通過網橋傳送到主機上,主機根據路由選擇出口,加上咱們docker裡的snat,所以這樣就傳送出去了。

還要乙個設定dnat的地方是output規則;output規則是本地生成資料報,然後如何重定位

UPnP 埠對映原理

三.miniupnp 參考實現 upnp 條件 簡單來理解的話,upnp 是一種裝置間通訊協議,功能是建立裝置和 nat 閘道器的埠對映,目的是希望接入 internet 的任意兩個裝置在 lan 下可以相互通訊。裝置加入網路時,通過簡單服務發現協議 ssdp 尋找網路上可用裝置。internet ...

埠對映 配置ssh埠對映

此手段用於在單向連通網路中進行雙向網路打穿 適用於未配埠對映的docker容器,不能反向訪問的受限網路等 在封閉網路內伺服器 容器執行以下命令,結果可以使目標伺服器通過訪問封閉網路內伺服器 容器的 ssh fgn r localhost root p 在目標伺服器執行以下命令,結果可以使目標伺服器通...

關於普通埠對映的原理

對於埠隱射,我們並不陌生,因為在很多場合,我們都會使用到它,比如 交換機 比如路由器 比如內網轉外網等 但如果用程式設計者的角度來解釋的話,可能大多數人會有點暈,到底該如何實現這樣的功能呢?下面我根據自己的理解站在 遠端控制類軟體 的角度來解釋一下普通資料 的埠對映 大致的原理如下 假設b處於內網且...