AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 1121736
Accepted
Rino Bino
Rino Bino
Asked: 2023-02-02 15:24:28 +0800 CST2023-02-02 15:24:28 +0800 CST 2023-02-02 15:24:28 +0800 CST

O Nginx não está lidando com auth_request antes da instrução if

  • 772

Provavelmente é mais fácil apenas mostrar por exemplo onde estou encontrando problemas, então vou direto ao ponto ...

Este snippet funcionará como está para Nginx com módulos de reescrita/autenticação ativados. Portanto, esperamos que esse problema seja rápido e fácil de reproduzir em praticamente qualquer instalação do Nginx ...

server {
  listen 8081;
  add_header x-user bar;
  return 200;
}

server {
  listen 8080;

  location = /auth {
    internal;
    proxy_pass http://localhost:8081;
  }

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }
}

O exemplo de configuração do site Nginx acima faz o seguinte:

  1. Envia qualquer solicitação para /authvia auth_request chamada
  2. O local /auth envia a solicitação para outro servidor que adiciona um cabeçalhox-user bar
  3. auth_request_setdefine uma nova variável $foocom base no valor do cabeçalho upstream x-userdefinido na etapa 2 acima.
  4. Um novo cabeçalho é definido x-testcom o valor de$foo
  5. A solicitação prossegue para um destino externo.

A resposta é exatamente como eu esperaria e confirmei que o $foovar foi definido corretamente:

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 200 OK
x-test: bar

Então, aí vem o problema...
Preciso ajustar essa configuração para que retorne 403 caso o valor do cabeçalho upstream esteja incorreto.

Parecia uma tarefa simples. Então adicionei uma if{}condicional para verificar o cabeçalho:

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    # this 'if' is the only part added to the original config
    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

A ifcondicional foi avaliada como verdadeira, então obtive um 403, que não era o que eu esperava. Então, isso não funciona :

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 403 Forbidden

Eu percebo que se é mau, no entanto, parece que estou usando apenas para retornar , o que deve estar ok. Estou aberto a usar qualquer método para atingir o mesmo objetivo - com ou sem if , então estou aberto a ideias!!

Eu tentei fazer coisas como mover as instruções auth_requeste/ou ifpara o server{}bloco, mas nada parece fazer com que isso seja avaliado da maneira que eu esperava.


Resolução de problemas / detalhes adicionais:

Eu verifiquei que o problema é que o ifé avaliado ANTES do auth_request_seté

  location / {
    auth_request /auth;
    auth_request_set $foo $upstream_http_x_user;

    if ($foo != bar) {
      # x-test never gets set because $foo is null when if evaluates
      add_header x-test $foo always;
      add_header success false always;
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }
$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success'
HTTP/1.1 403 Forbidden
success: false

Eu verifiquei que isso não é um problema se usar setem vez deauth_request_set . Isso funciona (mas não atinge o objetivo):

  # set works, but not auth_request_set
  location / {
    set $foo bar;

    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

Essa configuração funciona. seté avaliado antes if:

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test'
HTTP/1.1 200 OK
x-test: bar

O comportamento persiste mesmo se auth_requestestiver no server{}contexto :

server {
  listen 8081;
  add_header x-user bar;
  return 200;
}

server {
  listen 8080;

  auth_request /auth;
  auth_request_set $foo $upstream_http_x_user;

  location = /auth {
    internal;
    proxy_pass http://localhost:8081;
  }

  location / {

    if ($foo != bar) {
      return 403;
    }

    add_header x-test $foo;
    add_header success true;

    proxy_pass http://example.com/;
  }

}

$ curl -s --head http://localhost:8080 | grep -E 'HTTP|x-test|success'
HTTP/1.1 403 Forbidden
success: false

Analisei os seguintes documentos e perguntas:

  • Posso comparar uma variável definida por auth_request_set depois que auth_request retornou no nginx?
  • https://stackoverflow.com/questions/73431103/cant-access-added-headers-using-nginx-auth-request-set
  • O cabeçalho personalizado Nginx $ upsteam_cache_status não aparecerá
  • auth_request não bloqueia a diretiva de retorno, não pode retornar o status?
  • https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil
  • http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
  • http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
  • https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
nginx
  • 2 2 respostas
  • 116 Views

2 respostas

  • Voted
  1. Best Answer
    Tero Kilkanen
    2023-02-04T12:36:06+08:002023-02-04T12:36:06+08:00

    O ifé problemático, porque é uma construção imperativa em uma configuração declarativa.

    Portanto, nem sempre funciona como esperado. Mais informações podem ser encontradas no artigo IfIsEvil .

    Nesse caso, sete auth_request_setocorrem em diferentes estágios do processamento da solicitação nginx, e o ifprocessamento ocorre entre esses dois estágios.

    Infelizmente, não sei como fazer o que você deseja no nginx. Talvez isso precise ser feito no servidor upstream para o qual você faz proxy da solicitação.

    • 2
  2. Rino Bino
    2023-02-07T22:32:30+08:002023-02-07T22:32:30+08:00

    Isso não responde à pergunta, veja a resposta de Tero aqui para a resposta real (spoiler: ifé verdadeiramente mau, mesmo se for usado com return).

    No entanto, como uma resposta funcional fornecendo uma solução alternativa: Aqui está pelo menos uma maneira de fazer com que solicitações invalidadas sejam enviadas como 403. O ponto de extremidade proxy_pass é dinâmico, dependendo do cabeçalho testado. Isso parece resolver o caso de uso ...

    upstream barhost {
      server example.com;
    }
    
    
    map $foo $choose_upstream {
      default 127.0.0.1:8999;
    
      # cannot use hostnames here since they don't resolve. Using an upstream instead. 
      bar barhost;
    }
    
    server {
      listen 8999;
      return 403;
    }
    
    server {
      listen 8081;
      add_header x-user bar;
      return 200;
    }
    
    server {
      listen 8080;
    
      auth_request /auth;
    
      location = /auth {
        internal;
        proxy_pass http://localhost:8081;
      }
    
      location / {
        auth_request_set $foo $upstream_http_x_user;
        proxy_set_header Host example.com;
        proxy_pass http://$choose_upstream/;
      }
    }
    
    • 1

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve