阻止應用程序使用埠上的所有 IP (0.0.0.0:34964)
我有兩個應用程序使用相同的埠進行網路通信 (34964)。我可以控制(原始碼)第一個應用程序,它使用 192.168.0.4:34964。而另一個應用程序嘗試使用/“聲明”所有 IP 地址(0.0.0.0:34964),但我無法控制這個。每個應用程序都單獨執行,但是當我嘗試讓它們同時執行時,我得到一個錯誤:無法綁定地址。
問題
有什麼方法可以阻止第二個應用程序使用/聲明所有 IP 地址(0.0.0.0),而是使用 192.168.0.5。是在啟動它之前,還是通過將它封裝在網路命名空間中?
我什麼都沒試過,我完全沒有想法……
更詳細的版本: 兩個應用程序在兩個獨立的 Profinet 網路上進行通信。第一個應用程序充當 Profinet 設備並與 Siemens Profinet 控制器通信,我可以訪問此應用程序的原始碼。第二個應用程序應充當與 Profinet Siemens 設備對話的 Profinet 控制器,我目前正在為此使用 Codesys,並且無權更改原始碼。
你有幾個選擇。
LD_PRELOAD
您可以使用
LD_PRELOAD
庫來攔截bind()
系統呼叫以強制綁定到特定地址。一個例子是this,你可以這樣編譯: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
您需要確保在您的主機 (
sysctl -w net.ipv4.ip_forward=1
) 上啟用了 ip 轉發,並且您的 iptablesFORWARD
鏈允許轉發連接 (請iptables -A FORWARD -d 192.168.99.2 -j ACCEPT
記住,規則是按順序處理的,因此在此之前的拒絕規則將優先)。