HTTPS svuda sa Nginx, Varnish i Apache

Piše: Vanja Cavnic, 30. Sep 2015.

Web se polako pomera ka podrazumevanom korišćenju HTTPS enkripcije. Ovakav način komunikacije dodatno potencira i Google, koji je najavio da će se HTTPS ozbiljno uvrstiti kao faktor prilikom rangiranja u pretrazi. Sve u svemu, prelazak na HTTPS je dobar i iz više drugih razloga. Pretpostavimo da ste se već odlučili za prelazak na HTTPS, pa tako nećemo širiti raspravu o tim razlozima već ćemo vas sprovesti kroz korake ka HTTPS-u, uz priču o prednostima VarnishCache-a.

 

https

Koji problemi postoje sa Varnish-om i HTTPS-om?

Za sve one koji već koriste Varnish i žele da pređu na HTTPS postoji problem: Varnish ne podržava HTTPS. Ukoliko se okrenete SSL-u, obezbeđujući siguran način podrške Apache-a Vašem website-u, gubite prednost u brzini koju vam pruža Varnish.

Postoji relativno jednostavan način da se prevaziđe ovaj problem, a on se nalazi u sloju koji upravlja sigurnom konekcijom i SSL sertifikatima, i koji prosleđuje zahtev do Varnish-a. Da bismo ovo postigli, koristićemo Nginx. Verovatno vam je poznat Nginx kao alternativa Apache-u, što u suštini i jeste. Međutim, on se takođe može koristiti i kao proxy da bi se upravljalo zahtevima ka drugim servisima, što je ono što i mi želimo da postignemo. Drugim rečima, napravićemo web server sendvič, sa Varnish-om kao ukusnim cache-mesom u sredini.

Šta smo mi i šta želimo da budemo?

Pretpostavljam da posedujete server – bilo to virtuelni ili dedicated – sa više web sajtova na njemu. Takođe, verovatno želite da neki web sajtovi koriste HTTPS tehnologiju, a neke ćete za sada ostaviti na HTTP-u.

Vaša trenutna konfiguracija podrazumevaće da svakim zahtevom ka portu 80 upravlja Varnish. Varnish tada odlučuje, u zavisnosti od pravila koja ste postavili u VarnishConfigurationLanguage-u (VCL), da li će dostaviti keširanu kopiju stranice koja je zatražena ili će proslediti zahtev Apache-u koji će izgenerisati novu stranicu.

U tom slučaju, web server će verovatno morati da vuče podatke iz baze podataka ili da procesuira neke druge stvari pre nego što odgovori na zahtev i dostavi stranicu.

Do kraja ovog bloga, želimo da postignemo sledeće:

  • Nginx će se nalaziti na port-u 443 i upravljaće HTTPS zahtevima, dostavljajući rezultat Varnish-u.
  • Varnish će se nalaziti na port-u 80 i upravljaće HTTPS zahtevima, uključujući i one od strane Nginx-a, dostavljajući stranice direktno iz cache-a ili će prosleđivati zahtev do Apache-a.
  • Apache će se nalaziti na port-u 8080 i radiće ono što i inače: dostavljaće Vaš web sajt ili aplikaciju.

U ovom slučaju, Nginx predstavlja proxy. On ne procesuira Vaš web sajt i na njemu se na izvršava PHP niti se konektuje na bazu podataka. Sve što on radi je prihvatanje HTTPS zahteva i slanje istih Varnish-u. Varnish tada odlučuje da li vraća keširanu kopiju stranice ili prosleđuje zahtev Apache-u koji zatim dostavlja “svežu” stranicu, koristeći pravila Varnish-a koja ste već iskonfigurisali.

Primer okruženja

Za sledeći primer korišćen je Vagrant, koristeći UbuntuTrusty. Početno stanje podrazumeva Apache instaliran na portu 8080 i Varnish 4 instaliran na portu 80.

ubuntu1

 

Ukoliko želite da ispratite uputstvo sa istim početnim stanjem, možete preuzeti konfigurisano okruženje sa GitHub-a. Instrukcije za podešavanje nalaze se u readme fajlu.

Za ovaj primer imamo konfigurisana i dva web sajta. Ukoliko bismo posetili ova dva web sajta, Varnish bi upravljao zahtevom kroz port 80 tako što bi nam vratio stranice iz cache-a ili bi naš zahtev porsledio Apache-u.

Sada je korisno izlistati stvari po portovima. Ukucaćemo sledeće:


>vagrantssh

Zatim, pokrenuti netstat:


>sudonetstat –taupen

 

Ovo će vam izlistati portove sa informacijama o procesima koji ih koriste. Trebali biste da imate situaciju da je Varnish pokrenut na portu 80, a Apache na portu 8080.

Takođe, proverite da li se Varnish ponaša očekivano i dostavlja stranice iz cache-a.


>varnishstat

Ukoliko osvežite stranicu u browseru trebali biste da vidite cache pogotke (hits) i promašaje (misses).

Ukoliko koristite VCL sa GitHub-a, on je podešen da šalje HIT i MISS browseru. To znači da možete u zaglavlju zahteva u browseru pronaći X-Cache: HIT, ukoliko je stranica vraćena iz Varnish-a, odnosno X-Cache: MISS ukoliko je vraćena direktno iz Apache-a.

 

Postavljanje – instalacija Nginx

Sada možemo instalirati Nginx. Na Ubuntu sistemu to ide prilično jednostano kucanje sledeće komande:


>sudoapt-getinstallnginx

Nginx dokumentacija sadrži informacije kako instalirati Nginx na različitim operativnim sistemima. Zapamtite, mi koristimo Nginx samo kao proxy, zatim nemojte brinuti o podešavanjima podrške za PHP ili MySQL. Nginx se neće pokrenuti nakon instalacije, a trenutno i nije u mogućnosti, jer je port 80 zauzet od strane Varnish-a. Ukoliko ovo pokušavate na svom live serveru, slobodno možete uraditi ovaj korak, jer neće uticati na vaše web sajtove.

Kreiranje ili instalacija SSL sertifikata

sertifikat

Sledeći korak je postavljanje SSL sertifikata. Obzirom da radimo lokalno, možemo jednostavno kreirati “self-signed” sertifikat da bismo testirali SSL konekciju.

Da bismo to uradili, prvo ćemo izabrati direktorijum gde ćemo ga smestiti. Kreiraćemo nginx direktorijum i /etc/ssl. Zatim ćemo pokrenuti sledeću komandu da bismo generisali ključ i sertifikat.

>sudoopensslreq -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.key -out /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.crt

Nakon pokretanja ove komande biće Vam postavljana neka pitanja. Možete upisati bilo šta, međutim kada naiđete na “CommonName” upišite URL koji ste koristili kada ste pristupali Vagrantu. U slučaju primera koristili smo: smashing_ssl_one.tutorials.eoms

Ukoliko pogledate sada u folder koji ste kreirali, trebali biste da vidite dva fajla, jedan sa .key ekstenzijom i jedan sa .crt ekstenzijom.

Na svom live serveru izvršićete kupovinu sertifikata i tada dobiti ključ i sam sertifikat. Oba ćete postaviti na svoj server pre nego što pređete na sledeći korak.

Podešavanje SSL web sajtova u Nginx-u

Sa svojim “self-signed” ili kupljenim sertifikatom, možemo podesiti web sajt u Nginx-u.

Prvo, potrebno je da uklonimo podrazumevanu konfiguraciju iz /etc/nginx/sites-enabled. Možete ukloniti default fajl ili ga pomeriti na drugu lokaciju.

Konfigurisaćemo samo web sajtove koji će biti dostavljani preko SSL-a, ostali web sajtovi biće dostavljani direktno iz Varnish-a sa kroz port 80. U našem primeru, podešavamo smashing_ssl_one.tutorials.eoms. Gde god naiđete na ovaj domen u sledećim koracima, zamenite ga svojim domenom, ukoliko ne koristite ovaj primer.

nginx

U  /etc/nginx/sites-available/ kreirajte konfiguracioni fajl kao your_domain.com.conf.

U taj fajl upišite sledeće:

server {

listen *:443 ssl;

server_namesmashing_ssl_one.tutorials.eoms;

 

ssl on;

ssl_certificate /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.crt;

ssl_certificate_key /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.key;

 

location / {

 

proxy_pass            http://127.0.0.1:80;

proxy_read_timeout    90;

proxy_connect_timeout 90;

proxy_redirectoff;

 

proxy_set_header      X-Real-IP $remote_addr;

proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header      X-Forwarded-Proto https;

proxy_set_header      X-Forwarded-Port 443;

proxy_set_header      Host $host;

}

}

Prva linija upućuje server na port 443. Ovo je podrazumevani port za HTTPS konekcije, kao što je port 80 za HTTP. Zatim upisujemo ime servera.

Postavljamo SSL u aktivan status, a nakon toga dodajemo sertifikat i ključ koji smo kreirali ili instalirali, koristeći punu putanju.

Kod lokacije, koristimo proxy_pass da bismo prosledili zahtev nazad na port 80, gde ga Varnish čeka. Zatim dodajemo određene header-e, koje ćemo takođe proslediti.

Nakon dodavanja ovog fajla, uradićemo symlink fajla u sites-available na sites-enabled. Ukoliko ikada budete želeli da isključite web sajt, jednostavno obrišite symlink. Sledeća komanda kreiraće željeni symlink:

 
>ln -s /etc/nginx/sites-available/smashing_ssl_one.tutorials.eoms.conf /etc/nginx/sites-enabled/smashing_ssl_one.tutorials.eoms.conf

Zatim ponovo pokrenite Nginx:

 
>sudoservicenginx restart

Ukoliko nakon poruke restartingnginxnginxvidite [fail], najverovatnije imate grešku u kucanju u Vašem konfiguracionom fajlu. Preporuka je da pogledate da li nakon svakog reda imate karakter ;

Ukoliko Nginx ne uspe da se pokrene, proverite log na putanji  /var/log/nginx/error.log. Većina grešaka veoma dobro opisuje problem.

Videćete OK ukoliko se Nginx pokrene bez problema. Sada, ukoliko proverite koji servisi su pokrenuti na kojem portu, videćete da je Nginx na portu 443, Varnish je i dalje na portu 80 a Apache na 8080.

>sudonetstat–taupen

Najbolji test je svakako da posetite svoj web sajt koristeći https://. Ukoliko koristite “self-signed” sertifikat, ignorišite poruku upozorenja na Vašem browseru koji Vas upozorava da je sertifikat izdat od strane nepoznatog izvora.

Ukoliko vidite da Vam je web sajt prikazan sa katancem pored URL-a, to znači da Vam je dostavljen preko HTTPS-a kroz Nginx. Ukoliko pogledate HIT ili MISSheader-e, videćete da je stranica dostavljena kroz Varnish ne koristeći Apache svaki put.

 

Preusmeravanje na SSL koristeći Varnish

Ukoliko vam se web sajt dostavlja preko HTTP, a želite da ga dostavljate preko HTTPS-a, onda je potrebno da preusmerite sve HTTP zahteve. Ovo možete učiniti koristeći Varnish. Varnish je na portu 80, upravaljajući svim non-SSl zahtevima. Ono što moramo tražiti od Varnish-a je da identifikuje zahteve za Vaš sajt i prosledi ih na HTTPS.

U VCL fajlu u /etc/varnish/default.vcldodajte:

# handlesredirecting from http to https

subvcl_synth {

if (resp.status == 750) {

set resp.status = 301;

set resp.http.Location = req.http.x-redir;

return(deliver);

}

}

Zatim u subvcl_recvbloku dodajte sledeće:

if ( (req.http.host ~ "^(?i)smashing_ssl_one.tutorials.eoms") &&req.http.X-Forwarded-Proto !~ "(?i)https") {

set req.http.x-redir = "https://" + req.http.host + req.url;

return (synth(750, ""));

}

Možete pregledati kompletnu VCL konfiguraciju, uključujući i ovaj kod, na GitHub-u.

Sada, sve bi trebalo da je preusmereno na SSL. Restartujte Varnish i pokušajte da otvorite svoj web sajt koristeći HTTP i proverite da li vas preusmerava na HTTPS.

Još jedan način da proverite ovo jeste korišćenje cURL komande. Sledeća komanda vratiće samo header Vašeg zahteva. Trebali biste da dobijete poruku 301 prilikom testiranja HTTP URL-a.


>curl -I http://smashing_ssl_one.tutorials.eoms

Ocenite SSL

good vs bad

Kada preusmerite sve svoje sajtove tako da koriste SSL, dobar način da proverite svoju SSL konfiguraiju je SSL Server Test od Qualys SSL Labs. Upišite svoj domen i sačekajte da se test obavi.

Sa sličnom konfiguracijom iz primera: Vagrant instalacija – UbuntuTrusty, Nginx, Varnish i Apache, dobićete B ocenu, s obzirom da će server biti ranjiv po pitanju Logjam napada. Način da ispravite ovo možete naći u članku: “Weak Diffie – Hellman and the Log jam Attack.”

Vratite se na server, ukucajte cd komandu do direktorijuma gde Vam se nalazi SSL sertifikat i pokrenite sledeće:

>openssldhparam -outdhparams.pem 2048

Ovo će kreirati fajl po imenu dhparams.pem.

Zatim, dodajte u Nginx konfiguraciju kod koji je opisan pod “Nginx” sa sajta“Weak Diffie – Hellman and the Log jam Attack”.

server {

listen *:443 ssl;

server_namesmashing_ssl_one.tutorials.eoms;

 

ssl on;

ssl_certificate /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.crt;

ssl_certificate_key /etc/ssl/nginx/smashing_ssl_one.tutorials.eoms.key;

ssl_dhparam /etc/ssl/nginx/dhparams.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

 

ssl_prefer_server_ciphers on;

 

location / {

 

proxy_pass            http://127.0.0.1:80;

proxy_read_timeout    90;

proxy_connect_timeout 90;

proxy_redirect        off;

 

proxy_set_header      X-Real-IP $remote_addr;

proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header      X-Forwarded-Proto https;

proxy_set_header      X-Forwarded-Port 443;

proxy_set_header      Host $host;

 

}

}

08-ssl-test-opt-small

Uradite Reload Nginx i ponovo testirajte svoj web sajt. Kada dostignete ocenu A, možete periodično vršiti proveru, odnosno ocenu sajta da biste se uverili da i dalje imate ocenu A.

Proverite upozorenja o različitom sadržaju

Vaš web sajt može da sadrži resurse koji su učitani sa drugih domena koji nisu HTTPS – ovo će prikazivati upozorenje na vašem web sajtu. U većini slučajeva, izvor tih resursa ima i HTTPS verziju koju možete da koristite. U nekim slučajevima bićete primorani da uklonite te resurse, jer su dostavljane samo u HTTP verziji.

 

Blog post preuzet i preveden u slobodnoj formi sa Smashing magazine