2015-11-09 17 views
7

Próbuję skonfigurować proxy_protocol w mojej konfiguracji nginx. Mój serwer siedzi za obciążeniu wyważarki AWS (ELB), i mam włączony protokół proxy, że dla obu portów 80 i 443.Nginx: broken_header z proxy_protocol i ELB

jednak jest to, co mam, kiedy uderzę mojego serwera:

broken header: "��/�� 
                  '���\DW�Vc�A{���� 
                       �@��kj98���=5���[email protected]�</A 
    " while reading PROXY protocol, client: 172.31.12.223, server: 0.0.0.0:443 

To jest bezpośrednia kopia wklejona z dziennika błędów nginx - znaki nieważne i wszystkie.

Oto wycinek z mojego nginx config:

server { 
    listen 80 proxy_protocol; 
    set_real_ip_from 172.31.0.0/20; # Coming from ELB 
    real_ip_header proxy_protocol; 
    return 301 https://$http_host$request_uri; 
} 

server { 
    listen  443 ssl proxy_protocol; 
    server_name *.....com 
    ssl_certificate  /etc/ssl/<....>; 
    ssl_certificate_key /etc/ssl/<....?; 
    ssl_prefer_server_ciphers On; 
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
    ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4; 
    ssl_session_cache shared:SSL:10m; 
    add_header X-Frame-Options DENY; 
    add_header X-Content-Type-Options nosniff; 
    ssl_stapling on; 
    ssl_stapling_verify on; 


    ... 

nie mogę znaleźć żadnej pomocy w Internecie na ten temat. Inne osoby mają problemy z nagłówkiem, ale błąd w przypadku złych nagłówków jest zawsze czytelny - nie wyglądają tak, jakby były zakodowane tak jak dla mnie.

Wszelkie pomysły?

+0

Wygląda na to, że jest na 443. Jak to działa na porcie 80? Czy jest też tryb ELB w trybie HTTPS (nie TCP)? –

+0

Port 80 jest obsługiwany przez pierwszy blok - po prostu przekierowuje do https. Jest w trybie TCP/SSL, więc działają websockets. –

+0

Ten sam problem. Czy używasz Kubernetes przez przypadek? Próbuję to ustawić w klastrze Kubernetes i myślę, że może 'kube-proxy' miał coś z tym wspólnego. – iameli

Odpowiedz

8

dwie sugestie:

  1. Sprawdź, czy ELB słuchacz jest skonfigurowany do korzystania z protokołu TCP jako protokół, a nie http. Mam config LB jak poniżej, który jest routing do Nginx z proxy_protocol skonfigurowane:

    { 
        "LoadBalancerName": "my-lb", 
        "Listeners": [ 
        { 
         "Protocol": "TCP", 
         "LoadBalancerPort": 80, 
         "InstanceProtocol": "TCP", 
         "InstancePort": 80 
        } 
        ], 
        "AvailabilityZones": [ 
        "us-east-1a", 
        "us-east-1b", 
        "us-east-1d", 
        "us-east-1e" 
        ], 
        "SecurityGroups": [ 
        "sg-mysg" 
        ] 
    } 
    
  2. Wspomniałeś, że masz włączony protokół proxy w ELB, więc jestem zakładając, że już po AWS setup steps. Jeśli tak, to ELB powinien tworzyć prawidłowo żądanie HTTP z pierwszą linią jako coś podobnego do PROXY TCP4 198.51.100.22 203.0.113.7 35646 80\r\n. Jeśli jednak żądanie HTTP nie wejdzie do Nginx z linią PROXY ..., może to spowodować problem, który widzisz. Możesz to odtworzyć, jeśli trafisz na nazwę DNS EC2 bezpośrednio w przeglądarce, lub ssh do instancji EC2 i wypróbujesz coś takiego jak curl localhost, wtedy powinieneś zobaczyć podobny uszkodzony błąd nagłówka w dziennikach Nginx.

Aby dowiedzieć się, czy działa prawidłowo uformowane z żądania HTTP można użyć telnet:

$ telnet localhost 80 
    PROXY TCP4 198.51.100.22 203.0.113.7 35646 80 
    GET /index.html HTTP/1.1 
    Host: your-nginx-config-server_name 
    Connection: Keep-Alive 

następnie sprawdzić logi nginx i sprawdzić, czy masz ten sam błąd nagłówka uszkodzony. Jeśli nie, to ELB prawdopodobnie nie wysyła poprawnie sformatowanego żądania PROXY, a proponuję ponowne wykonanie konfiguracji protokołu ELB Proxy Protocol, być może z nowym LB, aby zweryfikować, czy jest poprawnie skonfigurowany.

0

Powyższe rozwiązanie Stephena Kargera jest poprawne, musisz się dostosować, aby skonfigurować serwer ELB do obsługi proxy. Oto dokumentacja AWS do wykonania dokładnie tego: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html. Dokumenty są początkowo nieco zniechęcające, więc jeśli chcesz, możesz po prostu przejść do kroków 3 i 4 w sekcji Enable Proxy Protocol Using the AWS CLI. Są to jedyne niezbędne kroki w celu umożliwienia channelingu proxy. Dodatkowo, jak zasugerował Stephen, musisz upewnić się, że twój ELB używa TCP zamiast http lub https, ponieważ oba te elementy nie będą zachowywały się poprawnie z implementacją proxy ELB. Sugeruję przeniesienie twojego kanału gniazda z popularnych portów, takich jak 80 i 443, tak, aby nadal móc utrzymywać standardowe połączenia z ich domyślnym działaniem. Oczywiście nawiązanie tego połączenia zależy całkowicie od tego, jak wygląda stos aplikacji.

Jeśli to nie pomaga, można użyć pakietu npmwscat debugować połączeń websocket tak:

$ npm install -g wscat 
$ wscat --connect 127.0.0.1 

Jeśli połączenie działa w lokalnej, to jest na pewno wyważarki swój ładunek. Jeśli jednak nie, to prawie na pewno problem z hostem gniazda.

Dodatkowo narzędzie takie jak nmap pomoże Ci odkryć otwarte porty. Miła lista kontrolna do debugowania:

npm install -g wscat 
# can you connect to it from within the server? 
ssh [email protected] 
wscat -c 127.0.0.1:80 
# can you connect to it from outside the server? 
exit 
wscat -c 69.69.69.69:80 
# if not, is your socket port open for business? 
nmap 69.69.69.69:80 

Możesz także użyć nmap z serwera, aby odkryć otwarte porty. zainstalować nmap na ubuntu, po prostu sudo apt-get install nmap. na osx, brew install nmap

Oto działająca konfiguracja, którą mam, mimo że obecnie nie obsługuje ssl. W tej konfiguracji mam port 80 zasilający moją aplikację szynową, port 81 zasilający gniazdo przez mój abel i port 82 otwarty dla wewnętrznych połączeń gniazdowych. Mam nadzieję, że to pomoże komuś !! Każdy, kto używa Railsów, jednorożca i Faye do wdrożenia, powinien uznać to za pomocne. :) szczęśliwy hacking!

# sets up deployed ruby on rails server 
upstream unicorn { 
    server unix:/path/to/unicorn/unicorn.sock fail_timeout=0; 
} 

# sets up Faye socket 
upstream rack_upstream { 
    server 127.0.0.1:9292; 
} 

# sets port 80 to proxy to rails app 
server { 
    listen 80 default_server; 
    keepalive_timeout 300; 
    client_max_body_size 4G; 
    root /path/to/rails/public; 
    try_files $uri/index.html $uri.html $uri @unicorn; 

    location @unicorn { 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header Host $http_host; 
    proxy_set_header X-Forwarded_Proto $scheme; 
    proxy_redirect off; 
    proxy_pass http://unicorn; 
    proxy_read_timeout 300s; 
    proxy_send_timeout 300s; 
    } 

    error_page 500 502 503 504 /500.html; 
    location = /500.html { 
    root /path/to/rails/public; 
    } 
} 

# open 81 to load balancers (external socket connection) 
server { 
    listen 81 proxy_protocol; 
    server_name _; 
    charset UTF-8; 
    location/{ 
    proxy_pass http://rack_upstream; 
    proxy_redirect off; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    } 
} 

# open 82 to internal network (internal socket connections) 
server { 
    listen 82; 
    server_name _; 
    charset UTF-8; 
    location/{ 
    proxy_pass http://rack_upstream; 
    proxy_redirect off; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    } 
} 
0

miałem ten błąd i natknąłem się na ten bilet:

które ostatecznie doprowadziły mnie do zastanawianie się, że miałem niepotrzebne oświadczenie w moim pliku nginx.confproxy_protocol. Usunąłem to i wszystko znowu działało.

Co dziwne, wszystko działało dobrze z wersją nginx 1.8.0, ale po aktualizacji do wersji nginx 1.8.1 jest, gdy zacząłem widzieć błąd.