Impedir que o aplicativo use todos os IPs na porta (0.0.0.0:34964)

Impedir que o aplicativo use todos os IPs na porta (0.0.0.0:34964)

Tenho dois aplicativos que usam a mesma porta para comunicação em rede (34964). Eu tenho controle sobre (código-fonte) o primeiro aplicativo e ele usa 192.168.0.4:34964. Enquanto o outro aplicativo tenta usar/"reivindicar" todos os endereços IP (0.0.0.0:34964), mas sobre este não tenho controle. Cada aplicativo funciona sozinho, porém quando tento fazê-los rodar ao mesmo tempo recebo um erro: Failed to bind address.

Pergunta

Existe alguma maneira de evitar que o segundo aplicativo use/reivindica todos os endereços IP (0.0.0.0) e, em vez disso, use 192.168.0.5. Antes de iniciá-lo ou encapsulando-o em um namespace de rede?

Não tentei nada e estou sem ideias...

Versão mais detalhada: Duas aplicações para comunicação em duas redes Profinet separadas. A primeira aplicação atua como um dispositivo Profinet e se comunica com um controlador Siemens Profinet, tenho acesso ao código fonte desta aplicação. A segunda aplicação deve funcionar como um Controlador Profinet que se comunica com um dispositivo Profinet Siemens, atualmente estou usando o Codesys para isso e não tenho acesso para alterar o código fonte.

Responder1

Você tem poucas opções.

LD_PRELOAD

Você poderia usar uma LD_PRELOADbiblioteca para interceptar a bind()chamada do sistema para forçar a ligação a um endereço específico. Um exemplo disso éesse, que você compila assim:

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

E use assim:

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

Namespaces de rede com Docker

Você também pode optar por executar seu programa dentro de seu próprio namespace de rede. Omais fácilA maneira de fazer isso seria construir uma imagem Docker para seu aplicativo e, em seguida, executá-la no Docker e usar os recursos de mapeamento de porta do Docker para expor o serviço no IP do host de sua escolha.

Aqui há dragões

Eu recomendaria fortemente uma das soluções acima. Incluo apenas o seguinte porque você perguntou sobre namespaces de rede.

Namespaces de rede com macvlan

Se você quiser fazer isso sem o Docker é possível, mas com um pouco mais de trabalho. Primeiro, crie um novo namespace de rede:

# ip netns add myns

Em seguida, crie uma macvlaninterface associada a uma de suas interfaces de host e coloque-a no namespace:

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

E atribua um endereço na sua rede local:

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

E crie regras de roteamento apropriadas dentro do namespace (substituindo seu endereço de gateway real 192.168.0.1):

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

Agora, execute seu programa dentro do namespace da rede:

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

Agora seu programa está em execução e será vinculado apenas a 192.168.0.4, porque esse é o único endereço visível dentro do namespace. Mas! Esteja ciente da limitação das mavclaninterfaces: embora outros hosts na sua rede possam se conectar ao serviço, você não poderá se conectar a esse endereço a partir do host no qual ele está sendo executado (a menos que você crie outra macvlaninterface no host e rotear conexões por 192.168.0.4meio dessa interface).

Namespaces de rede com interfaces veth

Em vez de usar macvlaninterfaces, você pode criar um vethpar de interfaces, com uma extremidade do par dentro de um namespace de rede e a outra em seu host. Você usará o mascaramento de IP para passar pacotes do namespace para sua rede local.

Crie o namespace da rede:

# ip netns add myns

Crie um par de interfaces:

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

Atribua uma extremidade do par ao namespace da sua rede:

# ip link setns myiface-in myns

Configure um endereço em cada extremidade do par e abra os links:

# 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

Configure o mascaramento de IP em seu host. Isso redirecionará os pacotes recebidos 192.168.0.4para o seu namespace:

# 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

E isso mascarará os pacotes de saída:

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

Você precisará garantir que o encaminhamento de IP esteja habilitado em seu host ( sysctl -w net.ipv4.ip_forward=1) e que sua FORWARDcadeia iptables permita o encaminhamento da conexão ( iptables -A FORWARD -d 192.168.99.2 -j ACCEPT, tendo em mente que as regras são processadas em sequência, portanto, uma regra de rejeiçãoanteseste terá precedência).

informação relacionada