ネットワーク通信(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ネットワークで通信します。最初のアプリケーションは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にサービスを公開することです。
ここで龍があります。
上記の解決策の1つを強くお勧めします。ネットワークネームスペースについてお問い合わせいただいたため、次の内容のみを含めました。
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
ホスト(sysctl -w net.ipv4.ip_forward=1
)でIP転送が有効になっており、iptablesFORWARD
チェーンが転送接続()を許可していることを確認する必要がありますiptables -A FORWARD -d 192.168.99.2 -j ACCEPT
。ルールは順番に処理されるため、ルールを拒否する必要があります。今後これが優先されます)。