Protegendo o proxy Nginx

2

Estou usando o Nginx como um proxy para um serviço da Web em Java.

Minha configuração é assim:

location /webservice {
    proxy_read_timeout 240;
    proxy_connect_timeout 240;
    proxy_pass      http://127.0.0.1:8080/;
}

Nos meus registros, vejo muitas entradas como esta:

xx.xx.xx.xx - - [18/Oct/2011:02:44:23 +0000] "GET http://l04.member.in2.yahoo.com/config/[email protected]&passwd=password HTTP/1.0" 200 9 "-" "Mozilla/4.0 (compatible; MSIE 5.0; Series60/2.8 Nokia6630/4.06.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)"

Eu fiz alguns testes, até onde eu posso ver meu proxy não é encaminhando solicitações para sites externos, mas eu gostaria de bloquear essas solicitações todos juntos e / ou retornam um código de status diferente de 200.

Eu fiz isso:

if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }

que bloqueia as tentativas de CONNECT. Qualquer idéia (além do bloqueio de IP) seria apreciada.

    
por Nick Lothian 18.10.2011 / 05:11

2 respostas

3

O Nginx aceitará conexões e as processará com base na correspondência do server_name (que verifica no cabeçalho do host). O Nginx vem com um bloco de servidores padrão configurado para corresponder a todos os hosts. Isso permite o processamento de qualquer solicitação que chegue ao servidor.

Gosto de configurar um bloco de servidor para verificar um cabeçalho de host vazio e também configurar o servidor padrão para retornar um erro 403 (por exemplo, se você tentar acessar meu servidor por meio de seu endereço IP). Cada host virtual obtém sua própria configuração (ou seja, qualquer host válido corresponde a uma configuração, todos os outros atingem o bloco de servidor padrão ou o bloco de host vazio).

Servidor para verificar o host vazio:

server {
    listen       80;
    server_name  "";
    return       444;
}

Servidor para lançar um 403 em todos os hosts não configurados:

server {
        listen       80;
        server_name  _;
        root /path/to/error/files;
        error_page 403 /403.html;
                location  /403.html {
                allow all;
        }
        deny all;
}

Deve-se notar que a diretiva de escuta não é necessária acima (nginx escuta na porta 80 por padrão) - mas meu nginx está rodando atrás do verniz, então não escuta realmente na porta 80.

No seu caso, você adicionará um terceiro servidor que manipulará suas solicitações de proxy reverso:

server {
server_name mydomain.com;
...your other blocks...
}

Você pode testar sua configuração de várias formas (tenho certeza de que há mais, mas isso vem à mente no momento):

(Estou usando o google.com como meu domínio de teste abaixo, mude para o seu site de preferência):

Especifique a solicitação inteira de uma só vez:

telnet mydomain.com 80
GET http://google.com

Especifique a solicitação e o cabeçalho do host separadamente:

telnet mydomain.com 80
GET / HTTP/1.1
Host: google.com

Configure uma entrada no seu arquivo de hosts (no seu servidor):

127.0.0.1 google.com

Use o curl para tentar buscar uma página:

curl google.com

(Nesse caso, o arquivo de hosts informa ao seu servidor que google.com pode ser encontrado em sua máquina - que recebe a solicitação para nginx - remove a entrada quando terminar o teste.)

Editar: Parece que a conseqüência não intencional do acima é que solicitações inválidas resultam em um erro 400. Você pode determinar a causa raiz disso, se estiver interessado, adicionando o parâmetro 'info' à sua diretiva error_log. No meu caso, as seguintes causas foram associadas aos 400 erros que vi:

Usando o telnet com a solicitação GET de uma linha (e nenhum cabeçalho de host):

client sent invalid request while reading client request line

Solicitações aleatórias (não padronizadas) feitas:

client sent invalid method while reading client request line

Usando o telnet, esperei demais:

client timed out (110: Connection timed out) while reading client request headers

Outras causas comuns foram:

client sent invalid host header while reading client request headers
recv() failed (104: Connection reset by peer) while reading client request line
client closed prematurely connection while reading client request line

O uso do curl produziu o erro esperado de 444. Imagino que exista alguma sintaxe adicional para um pedido válido. De qualquer forma, os 400 erros são processados antes dos 444 do meu entendimento, então é provável que eles não desapareçam para solicitações realmente inválidas.

No entanto, consegui obter um erro 444 usando o telnet, foi necessário modificar um pouco minha configuração:

server {
    listen       80 default;
    server_name  _ "";
    return       444;
}

Observe que, acima, o 'nome do servidor não especificado' (sublinhado) e o host em branco (aspas duplas) não definem explicitamente o servidor padrão, portanto, você deve adicionar 'padrão' à linha de escuta.

Saída Telnet:

telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Host: google.com

Resultado do log de acesso:

127.0.0.1 - - [19/Oct/2011:00:51:16 -0400] "GET / HTTP/1.1" 444 0 "-" "-" "-"
    
por 19.10.2011 / 04:01
1

Recomendamos que você reduza o tamanho dos cabeçalhos enviados (tamanho do URL).

Por favor, dê uma olhada em client_header_buffer_size e large_client_header_buffers

A limitação do URI do cliente é uma maneira comum de impedir que um verificador ou um cliente corrompido envie solicitações grandes que possam causar um estouro de buffer.

Portanto, se você configurar large_client_header_buffers 1 1k , seu serviço nginx não aceitará um URI maior que (1x1K = 1K) 1 kilobyte de dados (incluindo cookies).

Além disso, você pode configurar ignore_invalid_headers off caso não espere receber cabeçalhos personalizados.

    
por 18.10.2011 / 07:06