HAProxy retorna Bad Request (Host Inválido) por aparentemente nenhum motivo

4

Estou tentando testar uma configuração assim:

Website: Http GET Request - > Nginx - > HAProxy - > Aplicação .Net

Eu coloquei Nginx e HAProxy na mesma máquina Debian. No entanto, HAProxy constantemente retorna "Solicitação incorreta (host inválido)". Eu determinei que o HAProxy está em falta enviando primeiro a solicitação diretamente do site para o aplicativo .Net, que funciona. Ter o link Nginx para o aplicativo .Net também funciona. No entanto, quando tento testar isso com o HAProxy no lugar, começo a receber o erro. Não importa se o aplicativo .Net está realmente sendo executado por trás do HAProxy, sempre recebo o erro.

Um exemplo da mensagem que estou tentando enviar é http://192.168.7.119:81/a:diff1 . A resposta esperada é uma imagem JPG. Isso parece funcionar bem quando enviado para algo diferente de HAProxy (Apache, Nginx, o aplicativo), mas o HAProxy apenas diz "Solicitação incorreta". Estranhamente, não vejo nenhum erro no meu arquivo de log.

Veja um exemplo do arquivo de log:

Feb  2 15:10:08 companyDebian haproxy[5566]: 192.168.7.114:51105 [02/Feb/2015:15:10:08.415] renderfarm renderfarm/renderA 0/0/0/1/1 400 212 - - ---- 1/1/0/1/0 0/0 "GET /a:diff1 HTTP/1.1"
Feb  2 15:10:08 companyDebian haproxy[5566]: 192.168.7.114:51105 [02/Feb/2015:15:10:08.417] renderfarm renderfarm/renderA 73/0/0/4/77 400 212 - - ---- 1/1/0/1/0 0/0 "GET /favicon.ico HTTP/1.1"

Meu arquivo de configuração é assim:

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    # Default ciphers to use on SSL-enabled listening sockets.
    # For more information, see ciphers(1SSL).
    ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
    ssl-default-bind-options no-sslv3

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

listen renderfarm
    bind 192.168.7.119:81
    mode http
    balance roundrobin     
    server renderA 192.168.7.114:40000 maxconn 1

Eu não tenho experiência anterior com o HAProxy e estou usando-o porque foi recomendado para mim. Como tal, não sei quais os outros passos que posso dar para corrigir este problema. O manual de configuração menciona várias opções que você pode definir, como tune.bufsize e opção accept-invalid-http-request, mas elas não têm efeito.

Nota : A ideia é adicionar mais servidores executando o aplicativo assim que essa configuração funcionar. Cada servidor realmente só pode processar um pedido de cada vez.

    
por David 02.02.2015 / 15:25

4 respostas

2

Eu enfrentei o mesmo problema e demorei um pouco para descobrir por que isso estava acontecendo.

Meu ambiente é formado por 1 HAproxy e 2 nginx como backend com nodejs como um CGI.

A causa raiz é baseada em como o HAproxy cria a solicitação HTTP. Por padrão, o HAproxy não incluiria o cabeçalho do host na solicitação, portanto você precisa ser adicionado manualmente, caso contrário, o nginx retornará 400 como padrão e o HAproxy o marcará como não íntegro.

Exemplo abaixo:

  • Verificação de integridade do haproxy:

    option httpchk HEAD / HTTP/1.1
    
  • Solicitação HTTP equivalente:

    tony@calderona:~ $ telnet A.B.C.D 80
    Trying A.B.C.D...
    Connected to A.B.C.D.
    Escape character is '^]'.
    HEAD / HTTP/1.1
    
    HTTP/1.1 400 Bad Request
    Server: nginx/1.10.3
    Date: Sun, 10 Dec 2017 09:52:12 GMT
    Content-Type: text/html
    Content-Length: 173
    Connection: close 
    
  • Verificação de integridade do haproxy:

    option httpchk HEAD / HTTP/1.1\r\nHost:\ www.temporaryworkaround.org
    
  • Solicitação HTTP equivalente:

    tony@calderona:~ $ telnet A.B.C.D 80
    Trying A.B.C.D...
    Connected to A.B.C.D.
    Escape character is '^]'.
    HEAD / HTTP/1.1
    host: www.temporaryworkaround.org
    
    HTTP/1.1 200 OK
    Server: nginx/1.10.3
    Date: Sun, 10 Dec 2017 09:52:24 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 10282
    Connection: keep-alive
    

Felicidades

    
por 10.12.2017 / 11:12
0

Colocar o HAProxy por trás do Nginx parece frívolo, já que tanto o Nginx quanto o HAProxy podem fornecer a funcionalidade que você requer.

Considere a divisão da seção de escuta em frontend e backend seções com host ou path_beg acls e simplifique a configuração até obter uma resposta. Considere também usar unicamente forwardfor com um servidor ou adicionar outro servidor para roundrobin . Alguns exemplos -

frontend http-in
     bind 0.0.0.0:80
     acl host_1 hdr(host) -i firstsite.com
     acl host_nginx hdr(host) -i secondsite.com

Pareamento de frente e backends -

use_backend firstsite_redirect if host_1
use_backend nginx if host_nginx

Configuração de back-end -

backend firstsite_redirect
    mode http
    option forwardfor
    server firstserver 192.168.0.2:8080

backend nginx
    mode http
    balance roundrobin
    option httpclose
    option forwardfor
    cookie SRVNAME insert
    server nginx01 192.168.0.3:8080 cookie s1 check
    server nginx02 192.168.0.4:8080 cookie s2 check

Se você deseja redirecionar com base na URL, considere usar path_beg na configuração frontend -

frontend http-in 0.0.0.0:80
    acl docs path_beg /docs
    acl phpmyadmin path_beg /phpmyadmin
    
por 24.12.2015 / 12:44
0

Pode valer a pena tentar alterar sua configuração HAProxy para TCP em vez de HTTP. Você perde algumas opções avançadas de balanceamento de carga que o HTTP oferece (configuração de cookies para persistência, etc.), mas não parece que você as esteja usando agora mesmo.

Aqui está um exemplo de configuração que eu uso com o HAProxy para o balanceamento de carga do MySQL:

listen mysql-failover
    bind 10.10.10.210:3306
    mode tcp
    option  tcplog
    option mysql-check user haproxy
    server db1 10.10.10.13:3306 check fall 2 inter 1000
    server backup 10.10.10.11:3306 check

Observe que, se você mudar para TCP, perderá o acesso à página de estatísticas HTTP interna, que pode ser definida em uma instrução listen separada. Por exemplo:

listen stats
    bind 10.10.10.200:80
    mode http
    stats enable
    stats hide-version
    stats uri /
    option httpclose
    stats auth username:password
    
por 02.02.2015 / 17:04
0

Se você quiser ver o erro exato em que o HAproxy é executado, use socat para se conectar ao soquete de administrador. Instale socat via apt-get install socat e execute o seguinte:

echo "show errors" | socat unix-connect:/run/haproxy/admin.sock stdio

Se você executar isso logo após receber um erro de "Pedido incorreto", ele deverá mostrar exatamente o que o HAproxy não gostou sobre a solicitação HTTP feita pelo cliente.

NOTE: The above works only when you have enabled Unix Socket commands for HAProxy. You will have to add a one line configuration under global section to enable this.

global
     stats socket /var/run/haproxy.sock mode 600 level admin

Official documentation

    
por 02.02.2015 / 16:21