Verhindern Sie, dass die Anwendung alle IPs auf Port (0.0.0.0:34964) verwendet.

Verhindern Sie, dass die Anwendung alle IPs auf Port (0.0.0.0:34964) verwendet.

Ich habe zwei Anwendungen, die denselben Port für die Netzwerkkommunikation verwenden (34964). Ich habe Kontrolle über (Quellcode) die erste Anwendung und sie verwendet 192.168.0.4:34964. Während die andere Anwendung versucht, alle IP-Adressen (0.0.0.0:34964) zu verwenden/zu „beanspruchen“, habe ich über diese keine Kontrolle. Jede Anwendung läuft einzeln, aber wenn ich versuche, sie gleichzeitig laufen zu lassen, erhalte ich eine Fehlermeldung: Adresse konnte nicht gebunden werden.

Frage

Gibt es eine Möglichkeit, die zweite Anwendung daran zu hindern, alle IP-Adressen (0.0.0.0) zu verwenden/beanspruchen und stattdessen 192.168.0.5 zu verwenden. Entweder vor dem Start oder durch Kapselung in einem Netzwerk-Namespace?

Ich habe nichts versucht und mir gehen die Ideen aus ...

Ausführlichere Version: Zwei Anwendungen zur Kommunikation in zwei separaten Profinet-Netzwerken. Die erste Anwendung fungiert als Profinet-Gerät und kommuniziert mit einem Siemens-Profinet-Controller. Ich habe Zugriff auf den Quellcode dieser Anwendung. Die zweite Anwendung soll als Profinet-Controller fungieren, der mit einem Profinet-Siemens-Gerät kommuniziert. Ich verwende hierfür derzeit Codesys und habe keinen Zugriff, um den Quellcode zu ändern.

Antwort1

Sie haben einige Optionen.

LD_PRELOAD

Sie könnten eine LD_PRELOADBibliothek verwenden, um den bind()Systemaufruf abzufangen und die Bindung an eine bestimmte Adresse zu erzwingen. Ein Beispiel dafür istDas, die Sie wie folgt kompilieren:

gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE

Und so verwenden:

BIND_ADDR=127.0.0.1 LD_PRELOAD=./bind.so /path/to/myprogram

Netzwerk-Namespaces mit Docker

Sie können Ihr Programm auch in seinem eigenen Netzwerk-Namespace ausführen.am einfachstenEine Möglichkeit hierzu besteht darin, ein Docker-Image für Ihre Anwendung zu erstellen, es dann unter Docker auszuführen und die Portzuordnungsfunktionen von Docker zu verwenden, um den Dienst auf der Host-IP Ihrer Wahl verfügbar zu machen.

Hier gibt es Drachen

Ich würde eine der oben genannten Lösungen dringend empfehlen. Ich füge das Folgende nur hinzu, weil Sie nach Netzwerk-Namespaces gefragt haben.

Netzwerk-Namespaces mit Macvlan

Wenn Sie es ohne Docker machen möchten, ist das möglich, aber mit etwas mehr Arbeit verbunden. Erstellen Sie zunächst einen neuen Netzwerk-Namespace:

# ip netns add myns

Erstellen Sie dann eine macvlanSchnittstelle, die mit einer Ihrer Hostschnittstellen verknüpft ist, und fügen Sie sie in den Namespace ein:

# ip link add myiface link eth0 type macvlan mode bridge
# ip link set myiface netns myns

Und weisen Sie ihm eine Adresse in Ihrem lokalen Netzwerk zu:

# ip netns exec myns \
  ip addr add 192.168.0.4/24 dev myiface
# ip netns exec myns \
  ip link set myiface up

Und erstellen Sie entsprechende Routing-Regeln innerhalb des Namespace (ersetzen Sie dabei Ihre tatsächliche Gateway-Adresse durch 192.168.0.1):

# ip netns exec myns \
  ip route add default via 192.168.0.1

Führen Sie nun Ihr Programm innerhalb des Netzwerk-Namespace aus:

# ip netns exec myns \
  /path/to/myprogram

Jetzt läuft Ihr Programm und wird nur an gebunden 192.168.0.4, da dies die einzige im Namespace sichtbare Adresse ist. Aber! Beachten Sie die Schnittstellenbeschränkung mavclan: Während andere Hosts in Ihrem Netzwerk eine Verbindung zum Dienst herstellen können, können Sie von dem Host, auf dem er ausgeführt wird, keine Verbindung zu dieser Adresse herstellen (es sei denn, Sie erstellen eine andere macvlanSchnittstelle auf dem Host und leiten Verbindungen 192.168.0.4über diese Schnittstelle um).

Netzwerk-Namespaces mit Veth-Schnittstellen

Anstatt macvlanSchnittstellen zu verwenden, können Sie ein vethSchnittstellenpaar erstellen, wobei sich ein Ende des Paars in einem Netzwerk-Namespace und das andere auf Ihrem Host befindet. Sie verwenden IP-Masquerading, um Pakete aus dem Namespace an Ihr lokales Netzwerk weiterzuleiten.

Erstellen Sie den Netzwerk-Namespace:

# ip netns add myns

Erstellen Sie ein Schnittstellenpaar:

# ip link add myiface-in type veth peer name myiface-out

Weisen Sie ein Ende des Paares Ihrem Netzwerk-Namespace zu:

# ip link setns myiface-in myns

Konfigurieren Sie an jedem Ende des Paares eine Adresse und rufen Sie die Links auf:

# 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

Konfigurieren Sie IP-Masquerading auf Ihrem Host. Dadurch werden eingehende Pakete auf 192.168.0.4Ihren Namespace umgeleitet:

# 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

Und dies wird ausgehende Pakete maskieren:

# iptables -t nat -A POSTROUTING -s 192.168.99.2 -j MASQUERADE

Sie müssen sicherstellen, dass die IP-Weiterleitung auf Ihrem Host aktiviert ist ( sysctl -w net.ipv4.ip_forward=1) und dass Ihre iptables- FORWARDKette die Weiterleitung der Verbindung zulässt ( iptables -A FORWARD -d 192.168.99.2 -j ACCEPT, wobei zu beachten ist, dass Regeln nacheinander verarbeitet werden, sodass eine AblehnungsregelVordieser hat Vorrang).

verwandte Informationen