.png)
我有兩個應用程式使用相同的連接埠進行網路通訊 (34964)。我可以控制(源代碼)第一個應用程序,它使用 192.168.0.4:34964。儘管另一個應用程式嘗試使用/「聲明」所有 IP 位址 (0.0.0.0:34964),但我無法控制這個位址。每個應用程式都單獨運行,但是當我嘗試使它們同時運行時,我收到錯誤:無法綁定地址。
問題
有什麼方法可以防止第二個應用程式使用/聲明所有 IP 位址 (0.0.0.0) 並改為使用 192.168.0.5。要么在啟動之前,要么將其封裝在網路命名空間中?
我什麼也沒嘗試,我已經沒有想法了...
更細緻的版本: 兩個應用程式在兩個獨立的 Profinet 網路上進行通訊。第一個應用程式充當 Profinet 設備並與西門子 Profinet 控制器通信,我可以存取該應用程式的原始程式碼。第二個應用程式應充當與 Profinet 西門子設備通訊的 Profinet 控制器,我目前正在使用 Codesys 來實現此目的,並且無權更改原始程式碼。
答案1
你有幾個選擇。
LD_預先載入
您可以使用LD_PRELOAD
庫來攔截bind()
系統呼叫以強制綁定到特定位址。其中一個例子是這,你可以這樣編譯:
gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE
並且像這樣使用:
BIND_ADDR=127.0.0.1 LD_PRELOAD=./bind.so /path/to/myprogram
使用 Docker 的網路命名空間
您也可以選擇在自己的網路命名空間內執行您的程式。這最簡單的實現此目的的方法是為您的應用程式建立 Docker 映像,然後在 Docker 下運行它,並使用 Docker 的連接埠對映功能在您選擇的主機 IP 上公開服務。
這裡有龍
我強烈推薦上述解決方案之一。我只包含以下內容,因為您詢問了網路名稱空間。
帶有 macvlan 的網路命名空間
如果您想在不使用 Docker 的情況下完成此操作,也是可以的,但需要做更多的工作。首先,建立一個新的網路命名空間:
# ip netns add myns
然後建立一個macvlan
與主機介面之一關聯的介面並將其放入命名空間中:
# ip link add myiface link eth0 type macvlan mode bridge
# ip link set myiface netns myns
並為其分配本地網路上的位址:
# ip netns exec myns \
ip addr add 192.168.0.4/24 dev myiface
# ip netns exec myns \
ip link set myiface up
並在命名空間內建立適當的路由規則(用您的實際網關位址取代192.168.0.1
):
# ip netns exec myns \
ip route add default via 192.168.0.1
現在,在網路命名空間內執行您的程式:
# ip netns exec myns \
/path/to/myprogram
現在您的程式正在運行並且將僅綁定到192.168.0.4
,因為這是命名空間內唯一可見的位址。但!請注意介面的限制mavclan
:雖然網路上的其他主機能夠連接到該服務,但您將無法從執行該服務的主機連接到該位址(除非您macvlan
在該主機上建立另一個介面)並透過該介面路由連接192.168.0.4
)。
帶有 veth 介面的網路命名空間
macvlan
您可以建立一對接口,而不是使用接口veth
,該對的一端位於網路命名空間內,另一端位於您的主機上。您將使用 ip 偽裝將封包從命名空間傳遞到本地網路。
建立網路命名空間:
# ip netns add myns
建立介面對:
# ip link add myiface-in type veth peer name myiface-out
將這一對的一端分配給您的網路命名空間:
# ip link setns myiface-in myns
在該對的每一端配置一個位址並開啟連結:
# ip addr add 192.168.99.1/24 dev myiface-out
# ip link set myiface-out up
# ip netns exec myns ip addr add 192.168.99.2/24 dev myiface-in
# ip netns exec myns ip link set myiface-in up
在您的主機上設定 ip 偽裝。這會將傳入的封包重新導向192.168.0.4
到您的命名空間:
# iptables -t nat -A PREROUTING -d 192.168.0.4 -p tcp --dport 34964 -j DNAT --to-destination 192.168.99.2
# iptables -t nat -A OUTPUT -d 192.168.0.4 -p tcp --dport 34964 -j DNAT --to-destination 192.168.99.2
這將偽裝出站資料包:
# iptables -t nat -A POSTROUTING -s 192.168.99.2 -j MASQUERADE
您需要確保您的主機上啟用了 ip 轉送 ( sysctl -w net.ipv4.ip_forward=1
) 並且您的 iptablesFORWARD
鏈允許轉送連線 ( iptables -A FORWARD -d 192.168.99.2 -j ACCEPT
,請記住,規則是按順序處理的,因此拒絕規則前這一項將優先)。