2016-07-14 81 views
7

Sono sfortunatamente non molto un amministratore di sistema e mi sono imbattuto in un problema che mi ha sbattuto la testa contro il muro.Il proxy inverso Nginx per Heroku non funziona con l'handshake SSL

Il breve è che sto eseguendo Nginx su EC2 (Ubuntu 14.04.4 LTS) per (a) ospitare il sito di marketing della mia azienda (https://example.com, che incidentalmente è Wordpress) e (b) serve come proxy inverso per la nostra app Rails in esecuzione su Heroku (https: // app.example.com), per determinati percorsi. Utilizziamo lo stesso certificato SSL per example.com e app.example.com. Tutto ciò ha funzionato benissimo per 8-10 mesi, ma di recente sono passato dall'aggiunta SSL a pagamento di Heroku alla nuova offerta SSL gratuita, e ora il nostro proxy inverso non funziona.

Nel controllare i log degli errori Nginx, compaiono i seguenti:

SSL_do_handshake() failed (SSL: error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: ipaddress1, server: example.com, request: "GET /proxiedpath/proxiedpage HTTP/1.1", upstream: "https:// ipaddress2:443/proxiedpath/proxiedpage", host: "example.com"

Ho provato a cercare in giro per un po 'ulteriori indicazioni - ho aggiornato Nginx (1.10.1) e OpenSSL (1.0. 2h) senza fortuna. Sospettavo che il problema potesse essere dovuto all'utilizzo di SNI da parte di Heroku nella nuova funzionalità SSL gratuita (https://devcenter.heroku.com/articles/ssl-beta), ma non sono stato in grado di determinare perché questo potrebbe essere un problema.

Alcuni punti aggiuntivi sulla mia esplorazione a questo punto:

  • Quando sono passato alla nuova libera Heroku SSL, ho cambiato il nostro record DNS app.example.com per puntare a app.example.com .herokudns.com, come indicato dai documenti. L'applicazione è accessibile normalmente tramite app.example.com e quando eseguo un nslookup su app.example.com e app.example.com.herokudns.com, ottengo lo stesso indirizzo IP. Tuttavia ...

  • Non riesco ad accedere all'applicazione tramite l'indirizzo IP restituito da nslookup o app.example.com.herokudns.com. Sospetto che sia normale e atteso, ma non ne so abbastanza per dire esattamente perché è così. E ...

  • L'indirizzo IP restituito da nslookup NON è lo stesso dell'indirizzo IP a cui si fa riferimento nel messaggio di errore del registro sopra ("ipaddress2"). In effetti, "ipaddress2" non è coerente in tutti i log: sembra che cambi regolarmente. Ancora non ne so abbastanza per sapere cosa non so ... bilanciare il carico dalla parte di Heroku?

E, infine, il mio Nginx reverse proxy è configurato come segue in nginx.conf:

http { 

    client_max_body_size 500M; 

    sendfile on; 
    tcp_nopush on; 
    tcp_nodelay on; 
    keepalive_timeout 65; 
    types_hash_max_size 2048; 

    server_names_hash_bucket_size 64; 

    include /etc/nginx/mime.types; 
    default_type application/octet-stream; 

    access_log /var/log/nginx/access.log; 
    error_log /var/log/nginx/error.log; 

    gzip on; 
    gzip_disable "msie6"; 

    server { 

     listen 443 default_server; 
     server_name example.com; 

     root /usr/share/nginx/html; 
     index index.php index.html index.htm; 

     ssl on; 
     ssl_certificate mycompanycert.crt; 
     ssl_certificate_key mycompanykey.key; 

     ssl_session_timeout 5m; 

     ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
     ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; 
     ssl_prefer_server_ciphers on; 

     error_page 404 /404.html; 
     error_page 500 502 503 504 /50x.html; 

     location/{ 
      try_files $uri $uri/ /index.php?q=$uri&$args; 
     } 

     location ^~ /proxiedpath/ { 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_set_header X-Forwarded-Proto https; 
      proxy_pass https://app.example.com/proxiedpath/; 
     } 

    } 

} 

Qualsiasi aiuto è molto apprezzato - grazie mille!

+0

sono i tuoi 2 siti ospitati sullo stesso server? Puoi mostrarci la configurazione di 'app.mycompany.com'? Perché se si trovano sullo stesso server, è possibile restituire 301 https: //app.mycompany.com/proxiedpath/; 'e fare in modo che nginx gestisca la richiesta utilizzando il nome del server' app.mycompany.com' con lo stesso certificato. –

+0

Sfortunatamente sono completamente separati - il server proxy è configurato su AWS (dove ho il pieno controllo della configurazione) e il server delle applicazioni è ospitato su Heroku (dove ho un controllo relativamente piccolo o addirittura un approfondimento sulla configurazione). Ha funzionato prima di questo cambiamento, quindi so che deve essere una cosa abbastanza piccola. – Bart

+0

Inoltre, volevo aggiungere: per noi è importante per i motivi SEO che queste pagine vengano visualizzate su mycompany.com anziché su app.mycompany.com, da dove vengono effettivamente servite. – Bart

risposta

10

Oggi sono riuscito a risolvere questo problema e ho voluto postare la soluzione nel caso in cui altri si trovassero nello stesso problema.

Si scopre che il problema era collegato a SNI dopo tutto. Ho trovato questo biglietto sulla nginx.org:

https://trac.nginx.org/nginx/ticket/229

che mi ha portato alla direttiva proxy_ssl_server_name:

http://nginx.org/r/proxy_ssl_server_name

Impostando su "on" nella configurazione, sarete in grado per eseguire il proxy agli host upstream utilizzando SNI.

Grazie a tutti coloro che hanno commentato con suggerimenti!

+0

È uguale a http://stackoverflow.com/questions/25329941/nginx-caching-proxy-fails-with-ssl23-get-server-hellosslv3-alert -handshake-fail/25330027 # 25330027 L'unica cosa è che si dovrebbe anche applicare TLS1.0 o superiore, altrimenti SNI non verrà utilizzato. – gubble

+0

Grazie per questa risposta. Pensavo che trovare questa risposta sarebbe stato facile, ma Google non la pensava così –

0

Come nota per gli altri una condizione correlata che Heroku impone è che il campo HOST deve corrispondere al nome di dominio personalizzato.

Quindi, oltre a proxy_ssl_server_name si consiglia inoltre di impostare una linea come:

proxy_set_header Host mycustomdomain.com; 

Naturalmente questo vale solo se il campo host in arrivo nel sever è diverso dal dominio che il server risiede in.

l'errore specifico che si ottiene è:

SSL certificate error

There is conflicting information between the SSL connection, its certificate and/or the included HTTP requests.

Problemi correlati