アプリケーションがポート (0.0.0.0:34964) のすべての IP を使用しないようにします

アプリケーションがポート (0.0.0.0:34964) のすべての IP を使用しないようにします

ネットワーク通信に同じポート (34964) を使用するアプリケーションが 2 つあります。最初のアプリケーション (ソース コード) は私が制御しており、192.168.0.4:34964 を使用します。一方、他のアプリケーションはすべての IP アドレス (0.0.0.0:34964) を使用/「要求」しようとしますが、このアプリケーションは制御できません。各アプリケーションは単独で実行しても動作しますが、同時に実行しようとすると、次のエラーが発生します: アドレスのバインドに失敗しました。

質問

2 番目のアプリケーションがすべての IP アドレス (0.0.0.0) を使用/要求するのを防ぎ、代わりに 192.168.0.5 を使用する方法はありますか。起動する前に行うか、ネットワーク名前空間にカプセル化することで行うかのどちらかです。

何も試していないし、アイデアも尽きてしまいました...

より詳細なバージョン: 2 つの別々の Profinet ネットワークで通信するための 2 つのアプリケーション。最初のアプリケーションは Profinet デバイスとして機能し、Siemens Profinet コントローラーと通信します。このアプリケーションのソース コードにアクセスできます。2 番目のアプリケーションは、Profinet Siemens デバイスと通信する 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ホスト インターフェイスの 1 つに関連付けられたインターフェイスを作成し、それを名前空間に配置します。

# 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ルールは順番に処理されるため、拒否ルールは前にこちらが優先されます。

関連情報