Proxy transparente de um único contêiner docker para outro contêiner docker

2

Eu tenho um par de contêineres docker em execução na máquina host. Esses contêineres juntos fazem meu aplicativo atender. Portanto, para cada iteração / instância do meu aplicativo, é necessário um par de contêineres de encaixe para ser executado. Até agora, estou usando o parâmetro --link ao executar o segundo contêiner para vincular o primeiro contêiner e obter o IP do primeiro contêiner do arquivo hosts para usá-lo programaticamente.

Agora, preciso configurar um proxy transparente para o segundo contêiner do Docker. então, todo o tráfego http (porta 80) do segundo container deve passar pela porta 8080 do primeiro container.

Primeiro IP do contêiner: 172.17.0.4 (tem serviço de proxy em execução na porta 8080 ). IP do segundo container: 172.17.0.6 (possui ferramentas de cliente como navegador). Eu queria encaminhar todo o tráfego HTTP (Porta 80 ) do 172.17.0.6 para a porta 8080 do 172.17.0.4 .

i.e) Tráfego para 80 de 172.17.0.4 < --- > 8080 de 172.17.0.6

Eu tentei adicionar as regras do iptables dentro do segundo container para a configuração acima. Mas nenhum deles funcionou.

~# sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

Não funciona.

~# sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

Não funciona.

~# sudo iptables -t nat -A POSTROUTING -j MASQUERADE

Então, minha pergunta é: como posso configurar um proxy transparente dentro de um contêiner docker que possa encaminhar todo o tráfego de uma porta especificada para a porta de outro contêiner?

P.S: Se eu adicionar manualmente as configurações de proxy ao navegador no segundo container. Está funcionando bem. Mas eu queria definir o proxy transparente para todo o contêiner, não apenas o navegador. para que qualquer solicitação de rede de qualquer ferramenta dentro do segundo contêiner seja encaminhada para a porta do proxy do primeiro contêiner.

Eu li alguns tutoriais sobre proxy reverso de todos os contêineres que estão sendo executados juntos usando nginx / HAProxy. Mas eu queria configurar o contêiner individual com seu próprio contêiner de proxy como um par.

    
por Gowtham Sadasivam 26.01.2015 / 01:00

3 respostas

2

Obrigado a todos pelo seu tempo para responder. Basicamente, o que eu estou tentando fazer é fazer proxy no tráfego de saída / originado do segundo contêiner ( OBSERVAÇÃO: estou NÃO tentando Proxy o tráfego de entrada, portanto, não pode usar o Apache mod_proxy ou Nginx proxy_pass. Estes módulos funciona para o tráfego de entrada). O primeiro contêiner executa um serviço de proxy na porta 8080.

Como Thierno sugeriu, posso usar as variáveis ENV http_proxy e https_proxy para fazer proxy do tráfego de saída, mas infelizmente NÃO todos os aplicativos / serviços executados em seu sistema operacional respeitam essas variáveis ENV http_proxy e https_proxy. Existem aplicativos que forçam a ignorar as configurações de proxy. Essa é a razão pela qual eu queria usar iptables para impor as regras de tráfego . Assim, nenhum dos aplicativos / serviços podem pular o proxy.

O erro que cometi nas configurações anteriores na pergunta é que eu estava tentando rotear o tráfego de entrada para a porta 80 a 8080 do servidor proxy. Como o primeiro contêiner não tem nenhum tráfego de entrada, ele não funcionará e é logicamente errado PREROUTE / POSTROUTE o tráfego para alcançar o que eu estava procurando. Para rotear o tráfego originado / enviado, precisamos usar cadeia OUTPUT dos iptables.

Minha solução:

Eu usei RedSocks com a combinação iptables para impor o proxy para o tráfego de saída completo do servidor. Aqui está a configuração do iptables que usei:

# Crie uma nova cadeia para RedSocks

root# iptables -t nat -N REDSOCKS

# Ignora as LANs e alguns outros endereços reservados

root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
root# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
root# iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

# Redirecionar todas as portas locais http para redsocks

root# sudo iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports 12345

# para o tráfego https basta substituir a porta 80 por 443

# Use toda a cadeia REDSOCKS para todo o tráfego de saída em eth0

root# sudo iptables -t nat -A OUTPUT -p tcp -o eth0 -j REDSOCKS

Agora, configure os redsocks para ouvir a porta local 12345 do tráfego de entrada e encaminhá-la para o IP e a porta do servidor proxy. Para fazer isso edite o redsocks.conf como este,

redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = 172.17.0.4;
port = 8080;
type = http-relay;
}

salve o conf e reinicie o serviço redsocks . Agora todo o tráfego de saída originado do primeiro contêiner será imposto para usar o proxy. ( OBSERVAÇÃO: Eu usei o iptables-persistent para persistir as regras sobre reinicializações do servidor). Na verdade eu implementei o mesmo para o tráfego http e https adicionando outra linha à configuração do iptables. Embora não seja um proxy transparente, faz o trabalho para mim.

Se alguém tiver outras soluções alternativas, sugiro.

    
por 31.01.2015 / 07:18
0

Vinculação recíproca não é algo que o docker tenha, até onde eu sei (informações reveladas em tempo de execução sobre um contêiner transportado ou retribuído para um progenitor). É provavelmente por isso que a maioria dos tutoriais tem um terceiro ancestral comum, 'proxy' sendo usado.

Se você estiver disposto a usar frameworks como fig ou weave, que eu acredito ter arquivos de configuração yaml ou json, você provavelmente poderá configurá-lo com apenas dois contêineres recíprocos.

Se você estiver disposto a ter um terceiro, todas as portas e encanamentos poderão ser vinculadas por meio do ancestral comum para os dois contêineres 'irmãos'.

    
por 27.01.2015 / 06:52
0

Acho que usar o $http_proxy env var deve ajudar.

Você pode definir um ponto de entrada no seu arquivo de encaixe (para o contêiner # 2) para exportar o env var quando o contêiner estiver iniciando. Em algum lugar no seu ponto de entrada, você deve ter algo assim:

export http_proxy=http://$CONATAINER1_PORT_8080_TCP_ADDR:$CONATAINER1_PORT_8080_TCP_PORT

Eu não sei exatamente se o seu cliente (navegador) pode usar o $ http_proxy env var, mas deve existir um método similar. Por exemplo, para o firefox:

user_pref("network.proxy.http", "$CONATAINER1_PORT_8080_TCP_ADDR");
user_pref("network.proxy.http_port", $CONATAINER1_PORT_8080_TCP_PORT);
user_pref("network.proxy.type", 1);

Dicas: use printenv no segundo container para saber que nome de variáveis você deve usar em seu entrypoint

    
por 29.01.2015 / 22:22