Herança Nginx limit_conn

Herança Nginx limit_conn

Estou tentando proteger o Drupal em execução no Nginx contra DDoS simples com limit_conn e limit_req. Mas encontrei um comportamento estranho com herança de limit_conndiretiva que não consigo explicar.

Reduzi minha configuração do nginx (1.8.0) a este mínimo, o que mostra o problema:

limit_conn_zone $binary_remote_addr zone=perip:10m;

server {
    server_name test.dev;
    root /var/nginx/drupal; ## <-- Your only path reference.

    #Allow not more than 10 simultaneous connections from one address.
    limit_conn perip  10;

    location / {
        #limit_conn perip 1;
        # This is cool because no php is touched for static content
        try_files $uri @rewrite;
    }

    location @rewrite {
        # Clean URLs are handled in drupal_environment_initialize().
        rewrite ^ /index.php;
    }

    location ~ \.php$ {
        #Allow not more than 1 simultaneous *connection_to_PHP* from one address.
        limit_conn perip 1; 

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi.conf;
        fastcgi_intercept_errors on;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}

Como você pode ver, quero limitar o número de conexões simultâneas a 10 para todas as solicitações e a 4 para o backend php.(Neste exemplo modifiquei a conexão 4 para 1, assim seria mais fácil acionar)

A documentação do Nginx emhttp://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_connafirma que:

Estas directivas são herdadas do nível anterior se e só se não existirem limit_conndirectivas no nível actual.

Mas algo estranho acontece nos meus testes, parece que o nginx está ignorando a diretiva limit_conndentro do location ~ \.php$bloco:

  1. Quando testo essa configuração com 5 conexões simultâneas ab -n 100 -c 5 http://test.dev/, nenhum bloqueio acontece. Assim que aumento o
    limite para 11, -c 11o nginx começa a bloquear solicitações.
  2. Se eu modificar o limite global de conexões de 10 para 5, o nginx limitará mais de 6 conexões ( -c 6) - parece que a diretiva no location ~ \.php$bloco é ignorada.
  3. Se eu excluir a conn_limitdiretiva no nível do servidor, a diretiva em location ~ \.php$bloco de repente começa a funcionar!
  4. Ainda mais confuso: se eu adicionar a conn_limitdiretiva ao location /bloco, ela substituirá corretamente a global!

Talvez o problema esteja na try_filesdiretiva ou em múltiplos redirecionamentos? Ficaria muito grato se alguém pudesse explicar por que razão a conn_limitdirectiva não está a ser substituída, como esperado.

Responder1

Graças a @AlexeyTen, espero poder responder à pergunta.

Importantes são dois pontos:

  • A limit_conndiretiva é processada apenas uma vez por solicitação!
  • Estas directivas são herdadas do nível anterior se e só se não existirem limit_conndirectivas no nível actual.

DR: se houver uma limit_conndiretiva, o nginx espia o bloco filho na cadeia de execução, se não houver limit_conn, o pai é processado. Depois disso, todas as outras limit_conndiretivas serão ignoradas.

Tento explicar com meu exemplo:

No exemplo que postei, quando um "http://test.dev/"A solicitação chega, a princípio, o nginx não está processando limit_connno servernível, mas espera para verificar o local correspondente location /. Mas neste nível não há limit_conndiretiva, então o nginx processa aquela no servernível. Depois disso, todas limit_connas diretivas são ignoradas, porque já foi processado. Isso explica meus testes 1-3.

No teste 4, o nginx encontra uma limit_conndiretiva em location location /e a processa, mas novamente, em location location @rewriteno limit_conné encontrado, então a diretiva at location /é processada. Novamente, estamos ignorando o location ~ \.php$bloco.

informação relacionada