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

1

Eu tenho dois aplicativos que usam a mesma porta para comunicação de rede (34964). Eu tenho controle sobre (código fonte) o primeiro aplicativo e ele usa 192.168.0.4:34964. Considerando que o outro aplicativo tenta usar / "reclamar" todos os endereços IP (0.0.0.0:34964), mas este não tenho controle sobre. Cada aplicativo funciona em execução sozinho, no entanto, quando tento executá-los ao mesmo tempo, recebo um erro: Falha ao vincular endereço.

Pergunta

Existe alguma maneira de evitar que o segundo aplicativo use / reivindicando 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?

Eu não tentei nada e estou sem ideias ...

Versão mais detalhada: Dois aplicativos para se comunicar em duas redes Profinet separadas. O primeiro aplicativo atua como um dispositivo Profinet e se comunica com um controlador Profinet da Siemens, eu tenho acesso ao código-fonte para este aplicativo. O segundo aplicativo deve atuar como um Profinet Controller que fala com um dispositivo Profinet Siemens, atualmente estou usando a Codesys para isso e não tenho acesso para alterar o código-fonte.

    
por Heneer 06.04.2017 / 13:52

1 resposta

2

Você tem algumas opções.

LD_PRELOAD

Você pode usar uma biblioteca LD_PRELOAD para interceptar a chamada de sistema bind() para forçar a vinculação a um endereço específico. Um exemplo disso é este , 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

Espaços de nomes de rede com o Docker

Você também pode optar por executar seu programa dentro de seu próprio namespace de rede. A maneira mais fácil de fazer isso seria criar uma imagem do 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 host de sua preferência.

p>

Aqui tem dragões

Eu recomendaria strongmente uma das soluções acima. Eu só incluo o seguinte porque você perguntou sobre namespaces de rede.

Espaços de nomes de rede com / macvlan

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

# ip netns add myns

Em seguida, crie uma interface macvlan 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 à 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 o seu endereço de gateway real por 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 se ligará apenas a 192.168.0.4 , porque esse é o único endereço visível dentro do namespace. Mas! Esteja ciente da limitação das interfaces mavclan : enquanto outros hosts em sua rede poderão 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 outro macvlan interface no host e conexões de rota para 192.168.0.4 via aquela interface).

Espaços de nomes de rede com interfaces veth

Em vez de usar macvlan interfaces, você pode criar um par de interfaces veth , 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 interface:

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

Atribua uma extremidade do par ao seu namespace de 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 no seu host. Isso redirecionará os pacotes recebidos em 192.168.0.4 para 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 vai mascarar os pacotes de saída:

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

Você precisará garantir que você tenha o encaminhamento de ip ativado em seu host ( sysctl -w net.ipv4.ip_forward=1 ) e que sua cadeia iptables FORWARD permita o encaminhamento da conexão ( iptables -A FORWARD -d 192.168.99.2 -j ACCEPT , lembrando que as regras são processadas em sequência, portanto rejeitar regra antes esta terá precedência).

    
por 06.04.2017 / 14:50