.png)
У меня есть два приложения, которые используют один и тот же порт для сетевой связи (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, взаимодействующий с устройством Profinet Siemens, в настоящее время я использую для этого Codesys и не имею доступа для изменения исходного кода.
решение1
У вас есть несколько вариантов.
LD_PRELOAD
Вы можете использовать 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
) и что ваша цепочка iptables FORWARD
разрешает переадресацию соединения ( iptables -A FORWARD -d 192.168.99.2 -j ACCEPT
, имея в виду, что правила обрабатываются последовательно, поэтому правило отклонениядоэтот будет иметь приоритет).