Como fazer um proxy Nginx em cache existente usar outro proxy para ignorar um firewall?

4

Minha pergunta é sobre como usar o Nginx como um proxy por trás de outro proxy. (Um pouco confuso.)

Eu quero configurar o Nginx para que ele funcione como um servidor proxy de armazenamento em cache para um espelho npm. Aqui está o link: link

Na minha máquina local, que não é restrita por um firewall, a seguinte configuração funciona bem:

proxy_cache_path /var/cache/npm/data levels=1:2 keys_zone=npm:20m max_size=1000m
inactive=365d;
proxy_temp_path /var/cache/npm/tmp;

server {
   listen 80;
   server_name classen.abc.lan;
   location / {
      proxy_pass http://registry.npmjs.org/;
      proxy_cache npm;
      proxy_cache_valid 200 302 365d;
      proxy_cache_valid 404 1m;
      sub_filter 'registry.npmjs.org' 'classen.abc.lan';
      sub_filter_once off;
      sub_filter_types application/json;
   }
}

Agora, quero aplicá-lo a um servidor que está protegido por um firewall adicional. Nos logs, posso confirmar que ele acessa o IP upstream correto, mas a solicitação falha por causa do firewall interno.

Temos um proxy interno, que eu posso usar para ignorar o firewall, por exemplo:

$ curl http://registry.npmjs.org
curl: (7) couldn't connect to host
$ http_proxy=http://proxy.abc.lan:1234/ curl http://registry.npmjs.org
... succeeds ...

Esse truque não funciona com o Nginx, pois ignora a variável de ambiente http_proxy . Depois de ler a documentação, ainda não consegui descobrir como modificar a configuração, para que ela possa usar o proxy internamente.

É possível combinar as duas soluções? É importante que o cache ainda funcione, caso contrário, você pode simplesmente usar o registro espelho externo.npmjs.org diretamente.

Talvez, o Nginx deva usar o proxy interno (proxy.abc.lan) como proxy_pass , mas como o proxy interno sabe que a solicitação deve ser enviada para o espelho npm externo ( link )?

Atualize para a resposta do Lukas

Eu tentei a solução da Lukas:

rewrite ^(.*)$ "http://registry.npmjs.org$1" break;
proxy_pass http://proxy.abc.lan:1234;

Os registros mostram que o URL é reescrito, mas resulta em um redirecionamento (acionado por curl classen.abc.lan/test-url ):

2014/03/24 11:31:16 [notice] 13827#0: *2 rewritten redirect: "http://registry.npmjs.org/test-url", client: 172.18.40.33, server: classen.abc.lan, request: "GET /test-url HTTP/1.1", host: "classen.abc.lan"

O resultado da chamada curl não é a sequência JSON esperada do link , mas uma página html gerada pelo Nginx:

$ curl classen.abc.lan/test-url
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.4.7</center>
</body>
</html>
    
por Philipp Claßen 21.03.2014 / 19:11

3 respostas

4

O problema com a solução de Lukas é o HttpRewriteModule , que automaticamente transforma tudo com http (s) na frente em um 302 .

Se você fizer a reescrita em dois estágios - o segundo 'break' - deve funcionar. por exemplo,

rewrite ^(.*)$ "://registry.npmjs.org$1";
rewrite ^(.*)$ "http$1" break;
proxy_pass http://proxy.abc.lan:1234;

Suspeito que exista uma maneira mais agradável de fazer isso, mas parece funcionar.

    
por 20.04.2015 / 06:38
2

RFC 2616, Seção 5.1.2 declara

The absoluteURI form is REQUIRED when the request is being made to a proxy.
[...]
An example Request-Line would be:

  GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

Então, o que você deve fazer é passar a solicitação para o proxy com as diretivas modificadas:

rewrite ^(.*)$ "http://registry.npmjs.org$1" break;
proxy_pass http://proxy.abc.lan:1234;

De acordo com os documentos nginx , o uso de rewrite ... break; forçará o nginx a usar o < em> reescrito URI (agora um absoluto URI como o protocolo requer) em vez de tentar construí-lo a partir da diretiva proxy_pass .

    
por 23.03.2014 / 05:12
0

Eu acho que pode ser mais simples do que qualquer um dos exemplos acima. Eles estão usando reescrita para reescrever o url, eu acho que você pode usar proxy_pass, mas passar a url para o proxy configurando o parâmetro de cabeçalho do host para o local que você deseja ir. por exemplo,

http {

  upstream corporate_proxy  {
      server web-proxy.mycorp.com:8080;
  }

server {
   listen 80;
   server_name classen.abc.lan;
   location / {
      proxy_pass_header on;
      proxy_set_header Host "registry.npmjs.org";
      proxy_pass http://corporate_proxy;
      proxy_cache npm;
      proxy_cache_valid 200 302 365d;
      proxy_cache_valid 404 1m;
      sub_filter 'registry.npmjs.org' 'classen.abc.lan';
      sub_filter_once off;
      sub_filter_types application/json;
   }
}
    
por 28.10.2015 / 09:45