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).