
我們有一個 docker 容器的設置,它需要透過 ipv6 與 VPN (openvpn) 上的裝置進行通訊。這是透過在 docker 網路和主機上的 tap0 介面之間建立橋接來完成的。
終端設備將訊息推送到 Docker 容器,並期望收到返回的確認訊息。然而,它們位於不同的子網路上,容器和主機位於bbbb::/64
子網路中,設備位於子網路中abcd::/64
(為了說明目的)。有一個網關將bbbb::abcd:2
流量從一個子網路由到另一個子網,並且 docker 主機具有用於此目的的網關配置。
需要明確的是:
bbbb::4001 <--> bbbb::2105 <--> bbbb::abcd:2 <--> abcd::/64
bbbb::4001
貨櫃地址在哪裡;bbbb::2105
是主機的位址;bbbb::abcd2
是網關設備的位址;abcd::/64
是終端設備所在的子網路。
tshark
在主機和網關上使用,我們觀察到以下情況:
- 主機可以直接與abcd子網路上的終端設備通訊(使用traceroute檢查,可以看到主機和網關上的封包);
- docker容器可以與網關通訊(透過ping檢查,可以看到主機和網關上的封包);
- 碼頭貨櫃不能直接與 abcd 子網路上的終端設備通訊:我們可以看到主機上的資料包,就像我們看到主機通訊中的資料包一樣,但我們沒有看到任何東西到達網關。
我們嘗試修改iptables
規則以允許轉送封包(例如將鏈的預設策略設為FORWARD
)ACCEPT
但無濟於事。
我們不清楚在哪裡尋找這個問題,因為來自 docker 容器的封包發送到它不位於的子網路的封包似乎被丟棄了某處在主機上,或可能被發送到錯誤的地方,但我們確實在主機的br0
介面上看到它們,它們只是永遠不會到達網關。當 docker 容器嘗試與相同子網路上的事物進行通訊時,它就會起作用。
我從哪裡開始尋找這個?
答案1
問題與 docker 的網路有關。我們有一個 Docker 網路設定來使用橋接器連接到 VPN。此網橋是/etc/network/interfaces.d/br0.cfg
使用網關位址(透過 )設定的bbbb::2105
,並且在網橋介面之後建立了 docker 網路。建立docker網路時,沒有指定網關位址,docker預設使用bbbb::1
作為網關位址,它強制br0
使用。此位址與 VPN 伺服器的位址相同。結果是資料包實際上並未在主機上丟棄,而是轉發到 VPN 伺服器的tap
接口,並且 VPN 伺服器沒有設置路由表以使其知道如何處理這些資料包,因此它們實際上一旦他們到達VPN伺服器就被黑洞了。
透過使用 tshark 監控 VPN 伺服器的tap
介面以及tap
網關和 docker 主機上的接口,可以清楚地看出這一點。然後,我們嘗試從 docker 容器內部 ping 終端設備,我們在 docker 主機和 VPN 伺服器上看到了封包,但在網關上沒有看到封包。如果我們在docker 主機上嘗試相同的操作,我們會在docker 主機和網關上看到封包,但在VPN 伺服器上看不到,從而證明docker 容器被配置為將流量發送到VPN 伺服器而不是主機網絡接口。
--gateway
透過在 docker 網路的建立中引入該選項解決了該問題。
這其中未解決的部分是為什麼鑑於該設定自 2016 年以來一直有效,並在 2022 年 6 月的某一天隨機停止工作,因此突然開始出現這種情況。