日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

docker ip地址_理解 Docker 网络(番外) -- 《Docker 源码分析》勘误

發布時間:2024/9/19 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 docker ip地址_理解 Docker 网络(番外) -- 《Docker 源码分析》勘误 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本來打算這篇文章是分析 Docker Overlay 網絡是如何建立以及如何手動實現 Docker 的跨主機通信的。但是在完成了上一篇文章之后,打算找一些文章或者書籍印證我的文章是否正確。這時看了一下案頭的《Docker源碼分析》,翻到 Docker 容器網絡部分,然后快速過了一遍,發現了有一段和我的觀點不太一致。

有問題的部分是 95 頁的一段話,摘錄如下[1]:

5)宿主機將經過 SNAT 處理后的報文通過請求的目的IP地址(宿主機以外世界的IP地址)發送至外界。
在這里,很多人肯定要問:對于 Docker 容器內部主動發起的網絡請求,請求到達宿主機進行 SNAT 處理發給外界之后,當外界響應請求時,響應報文中的目的IP地址肯定是 Docker Daemon 所在宿主機的 IP 地址,那響應報文回到宿主機的時候,宿主機又是如何轉給 Docker 容器的呢?關于這樣的響應,由于沒有做相應的 DNAT 轉換,原則上不會被發送到容器內部。為什么說對于這樣的響應,不會做 DNAT 轉換呢。原因很簡單,DNAT 轉換是針對特定容器內部服務監聽的特定端口做的,該端口是供服務監聽使用,而容器內部發起的請求報文中,源端口肯定不會占用服務監聽的端口,故容器內部發起請求的響應不會在宿主機上經過 DNAT 處理。
其實,這一環節的關鍵在于 iptables,具體的 iptables 規則如下: iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ...

所以這篇文章將會從邏輯,理論,實驗來分析這段文字是否正確。

邏輯性和理論性分析

邏輯性分析

按照這段文字,如果我沒有理解錯的話,作者的意思是 Docker 容器通過 SNAT 向外發送請求,但是此時宿主機的 iptables 沒有配置 DNAT 那么在不配置 DNAT 的情況下必須要通過 iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 來保證響應能夠正確返回到 Docker 容器中。首先分析 iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT,這里可以直接引用作者的分析[1]

此 iptables 規則的意思是:在宿主機發往 docker0 網橋的網絡數據報文,如果該數據報文所處的連接已經建立,則無條件接受,并且有 Linux 內核轉發到原來的連接上,即回到 Docker 容器內部。

這里的意思有些偏頗,但不影響邏輯分析。這里要知道關于路由轉發的一些知識:數據包會發往 docker0 網橋的充分必要條件是路由表上由能將數據包正確轉發到 docker0 網橋的項。有這些作為基礎就可以開始邏輯性分析了:

假設條件:
  • Docker 容器發往外網的請求響應地址是本機 ip 地址
  • 本機沒有配置 DNAT ,數據包目標地址沒有被改寫為容器 IP
  • 通過設置 iptables 的 FORWARD 鏈,放行發往 docker0 網橋的數據包
  • 結論:

    • Docker 容器收到了數據包

    如果按照沒有 DNAT 就不會將目標地址改寫為容器 IP 這個邏輯的話,數據包會直接進入到 INPUT 鏈而不是進入到 FORWARD 鏈[5],就算進入到 FORWARD 鏈數據包目標地址不是目標容器的 IP ,數據包也不會經 docker0 輸出,此時 -o docker0 的 iptables 也不會生效,所以作者認為的關鍵 iptables 規則并沒有生效,因而在這里作者的邏輯是不通的。

    理論性分析

    作者在這里對 SNAT, DNAT 和 iptables 的理論基礎還不夠扎實,至少在寫作的時候還不扎實。這里會補充一些作者在寫作的時候遺漏的一些知識。

    無論是 SNAT 還是 DNAT,Linux 在實現 NAT 的時候都會生成一個 NAT 轉換表[3],用來對發送的請求和接受的響應進行轉換,SNAT 映射的轉換也會在 PREROUTING 鏈后 FORWARD 鏈前進行。以 Docker 容器 SNAT 的場景舉例, Docker 容器通過 iptables -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE 實現 SNAT。在發生 SNAT 轉換的時候 iptables 就會保存一個映射表。以 Docker 容器訪問遠程數據庫為例,容器使用 172.17.0.2:1234 發出請求到 14.215.177.39:3306,當容器請求的數據包進入到 POSTROUTING 鏈之后被偽裝成主機的 192.168.0.2:4567 端口,這時候 iptables 保存了 172.17.0.2:1234<->192.168.0.2:4567 的映射。遠程服務器收到的是 192.168.0.2:4567 的請求,然后 14.215.177.39:3306 返回響應給 192.168.0.2:4567 ,根據映射規則 iptables 將響應數據包的目標地址改寫為 172.17.0.2 將目標端口改寫為 1234,由于 172.17.0.2 地址不屬于宿主機,數據包進入 FORWARD 鏈處理。

    DNAT 的例子可以自己類推,重點是 DNAT 的映射也會在 POSTROUTING 鏈之后進行轉換。不然發送的數據包的目標地址沒有改寫為外網地址,數據包就無法發往外網。

    接著是 iptables 的處理流程,iptables 的處理流程如下圖所示

    詳細的可以查看參考資料[5],請求通過 PREROUTING 之后會判斷數據包的目標地址是不是本機的 IP 地址,如果屬于本機 IP 地址的話就跳轉到 INPUT 鏈處理,通過 INPUT 鏈進入到用戶空間進行處理,否則進入 FORWARD 鏈,交由內核進行路由轉發。

    接著是 iptables 命令的 -i 和 -o 參數,-i 參數是指在知道數據包由某端口(在路由交換設備上稱為端口,對應服務器的網卡)傳入的時候該 iptables 規則才生效,例如 -i eth0 是數據包由 eth0 傳入的時候該規則生效,如何知道數據包由 eth0 傳入呢?目標地址和 eth0 的 ip 地址相同,那么數據包肯定是通過 eth0 傳入的;那么 -i docker0 的情況呢?數據包的源地址址的網段和 docker0 IP 地址屬于同一個網段,數據包就是從 docker0 傳入的,例如主機接收到一個數據包,源地址為 172.17.0.2/16,和 docker0 的 IP 地址 172.17.0.1/16屬于同一個網段,那么這個數據包是通過 docker0 傳入的。

    -o 同理,-o 參數就是是在知道數據包要發往哪個端口時 iptables 規則才生效。iptables 怎么知道數據包要發往哪個端口呢?一個是路由表,一個是網段。如果路由表中指定了目標地址符合什么要求就發往某端口, 那么就能根據路由表知道數據包發往哪個端口。如果路由表沒有指定那么可以根據主機自身已有的端口所屬的網段來判斷發往哪個端口,如數據包的目標地址為 172.17.0.2/16 和 docker0 的網段 172.17.0.0/16 一致,那么就發往 docker0 端口。

    實驗分析

    實驗主要圍繞兩部分驗證:

  • iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 這條規則是不是 Docker 容器接收到響應的關鍵點
  • 只指定了 SNAT 沒有指定 DNAT,接收到的數據包的目標地址會不會被改寫
  • 增加實驗內容

  • 指定了 SNAT 后,外網響應數據包的目標地址的改寫是發生在進入 PREROUTING 鏈前還是出 PREROUTING 鏈后
  • 指定了 DNAT 后,響應外網的數據包的源地址的改寫是發生在進入 POSTROUTING 鏈前還是出 POSTROUTING 鏈后
  • 1.1 驗證 iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 是否數據包發往容器的關鍵點

    這個實驗在理解 Docker 網絡(一) -- Docker 對宿主機網絡環境的影響已經做過一次類似的。實驗過程很簡單,首先在宿主機上執行下面的命令刪除該規則

    iptables -D FORWARD -o docker0 -m conntrack --ctsate RELATED,ESTABLISHED -j ACCEPT

    然后創建容器并執行簡單的 ping 指令

    docker run --rm debian:stretch-slim bash -c " echo 'deb http://mirrors.163.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list && apt-get update > /dev/null && apt-get install -y inetutils-ping >/dev/null 2>&1 && ping -c4 www.baidu.com"

    執行結果如下

    -o docker0 的規則是否為關鍵

    可見是不能獲取正確的響應的。但這就說明這條規則是關鍵了嗎,請繼續往下看

    接下來為了簡化實驗步驟,這里不對 DOCKER 鏈進行處理,只對 FORWARD 鏈進行處理。由于 iptables 默認的 FORWARD 規則是 DROP 此時任何的數據包都不會被轉發,只要執行下面命令將 FORWARD 鏈的默認規則設置為 ACCEPT

    iptables -P FORWARD ACCEPT

    再次執行創建容器并執行簡單 ping 指令

    docker run --rm debian:stretch-slim bash -c " echo 'deb http://mirrors.163.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list && apt-get update > /dev/null && apt-get install -y inetutils-ping >/dev/null 2>&1 && ping -c4 www.baidu.com"

    執行結果如下

    -o docker0 的規則是否為關鍵

    可見 Docker 容器能夠正確的接收響應了。

    所以得出 iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 并不是數據包能發往容器的關鍵點,這條規則也沒有作者所說的“Linux 內核轉發到原來的連接上” 這個功能。

    1.2 驗證只指定了 SNAT 沒有指定 DNAT,接收到的數據包的目標地址會不會被改寫

    首先我們執行兩條指令將 iptables 復原

    iptables -I FORWARD -o docker0 -m conntrack --ctsate RELATED,ESTABLISHED -j ACCEPT iptables -P FORWARD DROP

    在這里需要用到抓包工具和數據包分析工具,抓包工具使用 Linux 的 TCPdump,數據包分析工具使用 Windows 的 Wireshark

    TCPdump 需要抓取宿主機外網網絡設備(在這里是 enp0s3,一般是 eth0)的數據包和 docker0 的數據包。在這里開啟三個終端。

    先執行 ip a 查看主機的網絡設備信息

    網絡設備信息

    可以得出主機 enp0s3 網卡的 IP 地址是 10.0.2.15,docker0 網卡的 IP 地址是 172.17.0.1,推算出 Docker 容器的 IP 地址應該符合 172.17.0.0/16 的模式

    終端一中監聽 enp0s3 ,執行命令

    tcpdump -i enp0s3 -w ./enp0s3.cap

    終端二中監聽 docker0 ,執行命令

    tcpdump -i docker0 -w ./docker0.cap

    終端三中創建容器并執行 ping 命令

    docker run --rm debian:stretch-slim bash -c " echo 'deb http://mirrors.163.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list && apt-get update > /dev/null && apt-get install -y inetutils-ping >/dev/null 2>&1 && ping -c4 www.baidu.com"

    等 ping 命令執行完之后,結束終端一和終端二的命令。在 Windows 上使用 Wireshark 分析 enp0s3.cap 和 docker0.cap,在這里可以直接查看最后一個數據包。

    Wireshark 可視化數據包分析

    通過 Data 段可以得出這兩個數據包的內容是一致的, Internet Protocol Version 4段可以得出兩個包的源IP Src 都為 14.215.177.38,而目標IP Dst 不一樣。enp0s3 中抓取的數據包 Dst 為 10.0.2.15 與 enp0s3 的 IP 地址一致。 docker0 抓取的數據包 Dst 為 172.17.0.2 IP 符合 172.17.0.0/16 的模式。

    可以看出數據包的目標 IP 被重寫了,而這時并沒有設置 DNAT。因此可以得出,只設置了 SNAT 沒有設置 DNAT ,接收到的數據包的目標地址一樣會被重寫。

    2.1 指定了 SNAT 后,外網響應的數據包的目標地址的改寫是發生在進入 PREROUTING 鏈前還是出 PREROUTING 鏈后

    為了確定在 POSTROUTING 指定了 SNAT 之后,外網響應的數據包目標地址的改寫出現在 PREROUTING 之前還是之后,只需要在 PREROUTING 鏈上加上規則

    iptables -t nat -A PREROUTING -d 172.17.0.0/16 -j DNAT --to 10.0.2.15

    如果目標地址改寫發生在 PREROUTING 之前,那么響應數據包的目標地址將會被重寫為本機的 enp0s3 地址,因而數據包不會進入到 FORWARD 流程,容器就不能收到響應數據包。

    docker run --rm debian:stretch-slim bash -c " echo 'deb http://mirrors.163.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list && apt-get update > /dev/null && apt-get install -y inetutils-ping >/dev/null 2>&1 && ping -c4 www.baidu.com"

    執行結果如下

    SNAT 也會作用在 PREROUTING 之后

    可以得出指定 SNAT 后, 外網響應數據包目標地址的改寫是發生在數據包出 PREROUTING 鏈之后進入 FORWARD 鏈之前。

    2.2 指定了 DNAT 后,響應外網的數據包的源地址的改寫是發生在進入 POSTROUTING 鏈前還是出 POSTROUTING 鏈后

    這里先恢復 PREROUTING 鏈

    iptables -t nat -A PREROUTING -d 172.17.0.0/16 -j DNAT --to 10.0.2.15

    然后使用端口映射創建一個 nginx 容器

    docker run --name nginx -d -p 8080:80 nginx

    接著修改 POSTROUTING 鏈,這里要做的修改有,將 Docker 自帶的 SNAT 和創建端口映射容器產生的 SNAT 刪除

    iptables -t nat -D POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE iptables -t nat -D POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE

    然后增加一條新的 SNAT

    iptables -t nat -D POSTROUTING -p tcp -m tcp --dport 8080 -j SNAT --to 172.17.0.2

    打開一個新終端,使用 tcpdump 監聽連接外網網卡的信息(這里使用的是 enp0s8)

    tcpdump -i enp0s8 -w ./enp0s8.cap

    接著外網訪問 8080 端口,結束 tcpdump ,使用 Wireshark 打開 enp0s8.cap

    DNAT也會作用在POSTROUTING之后

    可以看到從 enp0s8 端口輸出的數據包的 Src 都是 192.168.99.1 。

    這說明指定了 DNAT 沒有指定 SNAT 的時候在 POSTROUTING 鏈之后也會對數據包進行源地址和源端口重寫。

    總結

    這篇文章主要從邏輯,理論和實驗分析了《Docker 源碼分析》中關于 Docker 容器網絡 SNAT,DNAT 和 iptables 的一些錯誤。考慮到書籍作者 @孫宏亮 也在知乎上,希望作者在確認了問題后下版能夠做出相應的修改。如果已經有人提出過這個問題并已經打算修正那么大可以忽略這篇文章。

    這篇文章主要是分析了 SNAT 和 DNAT 在 Docker 容器中的作用,使用 tcpdump + Wireshark 的工具組合抓取和分析數據包。這本來是三言兩語就能夠說出對錯的問題,但為了增加文章的篇幅特地的將問題分解為邏輯分析,理論分析和實驗驗證三個步驟,希望對大家有用。

    參考資料

    • [1] 《Docker 源碼分析》
    • [2] SNAT 與 DNAT
    • [3] 聊聊 NAT 技術那些事
    • [4] 理解 Docker 網絡(一) -- Docker 對宿主機網絡環境的影響
    • [5] iptables詳解(1): iptables概念

    總結

    以上是生活随笔為你收集整理的docker ip地址_理解 Docker 网络(番外) -- 《Docker 源码分析》勘误的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲乱码一区二区 | 色热热 | 久艹在线 | 亚洲成人a∨| 特级做a爰片毛片免费69 | 日本特黄成人 | 久久成人免费视频 | 黄色大片视频 | 日本大胆裸体做爰视频 | 6080亚洲精品一区二区 | 久操网在线 | 一级看片 | 国产高潮自拍 | 亚洲欧美另类一区 | 日本美女黄色 | 伊人亚洲| 日韩精品成人无码专区免费 | 嫩嫩av| 日本人妻不卡一区二区三区中文字幕 | 神马午夜dy888 | 国产一二三区精品 | 久久涩视频 | 尤果网福利视频在线观看 | 日本韩国免费观看 | www.88av| 韩国av一区二区 | 污污内射在线观看一区二区少妇 | 一区二区三区四区视频在线观看 | a天堂资源在线 | 亚洲国产成人精品久久 | 欧美成人一区二区在线 | 我要色综合网 | 大肉大捧一进一出视频 | 裸体毛片 | 欧美日韩 一区二区三区 | www.色黄| 国产免费黄色网址 | 亚洲欧美精品suv | 香蕉久久精品日日躁夜夜躁 | 91偷拍精品一区二区三区 | 国产123区在线观看 91国产一区二区 | 亚洲性视频网站 | 非洲黑人狂躁日本妞 | 亚洲综合激情另类小说区 | 一本大道久久久久精品嫩草 | 都市激情亚洲一区 | 国产一区二区在线免费 | jizz性欧美17 | 日韩一区欧美二区 | 污视频在线观看网站 | 亚洲免费激情视频 | 九九在线精品视频 | 69xav| 亚洲成人不卡 | 国产男女猛烈无遮挡免费视频 | 中文字幕在线观看免费视频 | 国产精品视频福利 | 午夜电影福利网 | 婷婷亚洲五月 | 久久99精品久久久久久琪琪 | 午夜三级视频 | 中文字幕 亚洲一区 | 网红av在线| 色噜av | 久久精品片 | 一区免费观看 | 亚洲av永久一区二区三区蜜桃 | 免费黄色看片 | 97超视频在线观看 | jizz在线观看| 肥熟女一区二区三肥熟女 | 青娱网电信一区电信二区电信三区 | 男女在楼梯上高潮做啪啪 | 日韩精品一区二区三区免费视频 | 暧暧视频在线观看 | 91夜色视频| 国产精品网站免费 | 岳狂躁岳丰满少妇大叫 | 波多野结衣人妻 | 国产又黄又粗又长 | 日韩欧美一区二区三区久久婷婷 | 伊人网影院 | 欧美成人三级伦在线观看 | 黄网站在线播放 | 巨胸爆乳美女露双奶头挤奶 | 日韩一级免费视频 | 激情欧美综合 | 免费黄色大片网站 | 中文一二区 | 国产又黄又大又粗视频 | 亚洲自拍偷拍一区 | 玖玖色在线 | 国产国产乱老熟女视频网站97 | 天堂在线中文 | av久久久久久 | 亚洲高清在线 | 欧美乱妇高清无乱码 | chien国产乱露脸对白 | 国产污污视频在线观看 |