Konfigurasjon av webservere og applikasjonsservere for lastbalansering

Generelt

Vi anbefaler alltid at trafikk i f?rste rekke h?ndteres av en fullverdig webserver, slik som Apache eller nginx. Selv om det ofte i prinsippet er mulig ? la lastbalanserer snakke direkte med en applikasjonsserver, mister man da mye fleksibilitet og mange muligheter. Hvis man trenger ? h?ndtere sertifikater p? backend er som regel dette ogs? langt enklere ? gj?re i en webserver, og man kan simpelthen f?lge oppskriftene for hhv. Apache eller nginx, som er dokumentert i kokeboken for SSL.

Vi anbefaler videre at webserveren settes til ? lytte p? port 80 og/eller 443 (istedenfor ustandard porter), og begrenses til ? kun tillate trafikk mot disse portene fra UiOs nett. Dette kan man oppn? helst ved ? plassere (eller flytte om n?dvendig) serveren til et VLAN tilh?rende et mer lukket nett, f.eks. kategori 3, eller sekund?rt ved ? begrense innkommende trafikk i lokal firewall n?r dette ikke er mulig. Hovedform?let er alts? ? forhindre at webserver kan ta imot trafikk direkte fra verden, og dermed tvinge innkommende trafikk gjennom lastbalanserer.

Dersom webserver reversproxyer videre til en applikasjonsserver over HTTP, kan denne egentlig benytte hvilken som helst port over 1024. Ofte benyttes port 8080 til dette form?let for lokal ukryptert trafikk. Hvis applikasjonsserver kj?rer p? samme server som webserver - hvilket den som regel gj?r - b?r applikasjonsserveren kun lytte p?/binde mot localhost, og ikke public IP. Webserver b?r da f?lgelig ogs? reversproxye videre til localhost, over valgt port, f.eks. 8080. Hovedform?let med dette er igjen ? forhindre at applikasjonsserver kan ta imot trafikk utenfra - inkludert fra andre servere - og dermed tvinge innkommende trafikk til denne gjennom webserver. Hvis applikasjonsserver kj?rer p? en annen server enn webserver, b?r applikasjonsserver kun tillate trafikk fra IPen(e) til webserver, begrenset med lokal firewall.

Gj?r man alt dette, s?rger man alts? for ? stenge bakd?rer, og at all innkommende web-trafikk vil f?lge ?nsket vei: lastbalanserer -> webserver -> applikasjonsserver.

Applikasjonsservere skal kj?res som en dedikert upersonlig bruker, og aldri som root. Som regel vil en lokal bruker v?re tilstrekkelig. Webservere (og applikasjonsservere der dette er mulig) m? alltid installeres med systempakke fra standard-repo, som da vil benytte dedikert lokal bruker og s?rge for at egnede rettigheter ivaretas.

Gjenopprette korrekt IP

N?r HTTP-trafikk g?r gjennom en reverse proxy, slik den gj?r ved den typen lastbalansering vi gj?r (lastbalansering i HTTP-laget), gj?res det i realiteten to separate foresp?rsler. En fra klient til lastbalanserer, og s? en ny fra lastbalanserer til webserver (backend). Det er dette som gj?r det mulig ? p?virke egenskaper ved foresp?rselen i lastbalanseringslaget, og "fikse" ting der, f?r den g?r videre til webserver. Ettersom disse foresp?rslene er separate, kan de ogs? ha forskjellige egenskaper. Foresp?rselen fra klient til lastbalanserer kan f.eks. g? over IPv6 og HTTP/2, mens foresp?rselen fra lastbalanserer til backend kan g? over IPv4 og HTTP/1.1 - eller andre kombinasjoner av faktorer. Lastbalanserer vil oversette mellom disse, s? s?ml?st som mulig.

En negativ konsekvens ved dette, er at foresp?rslene fra lastbalanserer til backend ser ut i webserver som de kommer fra IPen som tilh?rer lastbalansereren, istedenfor IPen som tilh?rer klienten. Dette stemmer jo for s? vidt, men man er som regel mer interessert i hvilken klient som faktisk sitter i andre enden. Denne informasjonen (og mer til) eksponerer lastbalanserer gjennom egne HTTP headere, s?rlig headerne X-Forwarded-For og Forwarded. Begge disse gj?r i prinsippet det samme, men X-Forwarded-For er mer utbredt, og ofte enklere ? ta i bruk. Vha. disse headerne kan man i webserver "gjenopprette" den opprinnelige IPen som faktisk tilh?rer klienten, og dermed ogs? eksponere denne videre inn i tjenesten til selve applikasjonen. St?tte for ? gj?re dette er h?yst varierende i ymse applikasjonsservere, og dette er én av grunnene til at vi alltid anbefaler ? ha en skikkelig webserver - med st?tte for dette og langt mer - i forkant. Da vil man ha tilgang til det fulle og rike verkt?yskrinet av muligheter som en webserver tilbyr, og f? logger med korrekt IP fra webserveren.

Det er mange grunner til at det er viktig ? sette opp webserver til ? korrekt rapportere klientens IP-adresse. Uten dette vil det v?re vanskelig (eller s?gar umulig) ? skille forskjellige klienter fra hverandre, b?de i logger og ellers. Logger som rapporteres inn i DataOPS vil v?re langt mindre nyttige eller verdifulle, ettersom de mangler en av de mest vesentlige detaljene. Det vil v?re utfordrende ? debugge problemer med tjenesten, og dersom det skulle oppst? en hendelse vil denne v?re vanskelig for IT-sikkerhet ? kunne analysere. I det store og hele vil man i de fleste sammenhenger v?re mer eller mindre blind mht. hvem som faktisk bruker tjenesten.

OpenShift/OKD

Alle tjenester som kj?rer i OpenShift/OKD m? plasseres bak lastbalanserer - s?rlig om de skal v?re tilgjengelig fra Internet. Her anbefales det f?rst og fremst ? f?lge den generelle OpenShift-dokumentasjonen, med s?rlig fokus p? seksjonene for hhv. Edge og Passthrough.

Merk at de generelle anbefalingene for oppsett bak lastbalansering gjelder ogs? her, og da s?rlig det som gjelder ? ha en webserver foran der dette er mulig, anbefalt oppsett for webservere som nginx og Apache, og h?ndtering av tilgangskontroll.

Det kj?rer en HTTP Echo-tjeneste i OpenShift som vil vise hvilke headere som er tilgjengelig fra innsiden av et cluster, og som man kan benytte seg av. Legg s?rlig merke til headerne Forwarded samt X-Forwarded-* som alle stammer fra lastbalansererne.

Apache

Apache HTTP server er nok den web-serveren vi har mest erfaring med, s?rlig i www-drift. I utgangspunktet trenger man ikke ? gj?re noen endringer i Apache-oppsettet for ? f? dette til ? virke med v?re lastbalanserere, men endringer er n?dvendig for ? gjenopprette opprinnelig klient-IP. For ? gj?re dette i Apache, benytter man modulen mod_remoteip, hvor dette kan l?ses med kun noen f? linjer konfigurasjon.

mod_remoteip

F?rst m? man skru p? modulen mod_remoteip. P? Red Hat er denne allerede inkludert i httpd-pakken, s? man trenger ikke installere noe ekstra for dette. Hvis modulen ikke allerede er lastet inn, kan den enkelt legges inn som en linje der man laster inn andre moduler:

Loadmodule remoteip_module modules/mod_remoteip.so

Videre m? man fortelle Apache hvilken header den skal hente IP fra, samt hvilke lastbalanserere man har i forkant.

RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy w3prod-lb-uio01.uio.no
RemoteIPTrustedProxy w3prod-lb-uio02.uio.no

Noen vil kanskje foretrekke ? heller bruke IPv4- og IPv6-adressene. Da m? man i s? fall huske ? legge inn begge, alts? b?de IPv4 og IPv6 for begge lastbalansererne, siden trafikk kan komme fra begge lastbalanserere og begge IP-versjoner.

I eksempelet over sier man alts? at klientens IP-adresse skal hentes fra HTTP-headeren X-Forwarded-For, og at denne informasjonen kun skal stoles p? dersom den stammer fra lastbalansererne w3prod-lb-uio01.uio.no eller w3prod-lb-uio02.uio.no.

I noen tilfeller vil tjenesten settes opp p? andre lastbalanserere enn de i eksempelet, f.eks. dersom tjenesten er en test-instans, eller dersom den kj?rer i et annet milj? (OpenShift, Educloud eller annet). Det ligger en full liste over alle lastbalanserere i git, men er du usikker p? dette s? sp?r oss gjerne. Det er ogs? mulig ? si at man stoler p? hele UiOs nett, men man er da n?dt til ? ta h?yde for b?de IPv4 og IPv6. Dette er i utgangspunktet noe mindre sikkert, og gj?res i s? fall p? eget ansvar.

Loggformat

Loggformatet m? s? oppdateres til ? benytte verdien fra "X-Forwarded-For". Man kan benytte hvilket loggformat man m?tte ?nske, men vi vil foresl? flg., ettersom dette enkelt vil kunne parses av DataOPS uten behov for videre tilpasninger:

LogFormat "%a %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined

Det siste ordet i linjen er navnet p? loggformatet man har definert, som man s? m? s?rge for ? gjenbruke der man definerer logger. I dette eksempelet defineres alts? et loggformat kalt "combined". Dette er et navn som er ofte brukt i Apache, og gjerne vil v?re definert fra f?r av, men da med et annet format enn det vi her foresl?r.

Det enkleste vil da v?re ? finne linjene som starter p? CustomLog, og se p? slutten av linjen for ? finne ut navnet p? loggformatet man allerede bruker, f.eks. "combined" eller "common". Man kan s? finne den eksisterende LogFormat-linjen som slutter p? dette navnet, og bytte denne ut med linjen over, med samme navn p? slutten som det man alt bruker i CustomLog-linjer. Da holder det ? oppdatere denne ene linjen (som starter p? LogFormat), og man trenger ikke ? endre noen linjer som definerer logger (de som starter p? CustomLog).

Alternativt kan man legge til en ny loggformat-definisjon lik den over, og istedenfor "combined" kalle den f.eks. "uio" eller hva som helst. Da kan man spesifisere at logger istedet skal bruke dette nye formatet kalt "uio". Et eksempel p? sistnevnte kunne sett slik ut:

CustomLog /var/log/httpd/foo.uio.no/access_log uio

Om man ikke ?nsker ? bruke det foresl?tte loggformatet, kan man gj?re en mindre endring i det loggformatet man selv foretrekker, og simpelthen bytte fra "%h" til "%a". Dette er i seg selv tilstrekkelig for ? f? riktig kilde-IP i logger.

HTTP/2

Man b?r ogs? s?rge for ? skru p? st?tte for HTTP/2, ettersom denne har langt bedre ytelse enn den eldre (og n? ganske gamle) HTTP/1.1. I webservere - ogs? Apache - m? dette vanligvis aktivt skrus p? for ? brukes.

Dette gj?r man ved ? f?rst installere pakken mod_http2 med flg. systemkommando:

sudo yum install -y mod_http2

S? laste modulen i Apache-config, samme sted hvor man laster andre moduler:

LoadModule http2_module modules/mod_http2.so

Og til sist aktivere protokollen i Apache-config:

Protocols h2 h2c http/1.1

Denne siste linjen kan erstatte evt. tidligere Protocols-linje(r) man m?tte ha fra f?r. Hvis man ikke har en slik fra f?r av, kan denne puttes enten (helst) i generell server config, eller (evt.) inni en VirtualHost-blokk.

N?r trafikk fra lastbalanserer til backend (alts? Apache) g?r over HTTPS (port 443), vil da oppgradering til HTTP/2 skje automatisk, og man trenger ikke foreta seg noe mer.

Hvis den derimot g?r over HTTP (port 80), vil ikke oppgradering til HTTP/2 skje av seg selv, og lastbalanserer m? eksplisitt fortelles at den skal bruke dette. Dette gj?r man ved ? be www-drift om ? legge dette til. Konfigurasjonen man skal be om er dette:

backend_http_version: proto h2

nginx

I utgangspunktet trenger man ikke ? gj?re noen endringer i nginx-oppsettet for ? f? dette til ? virke med v?re lastbalanserere, men endringer er n?dvendig for ? gjenopprette opprinnelig klient-IP. For ? gj?re dette i nginx, benytter man modulen real_ip, hvor dette kan l?ses med kun noen f? linjer konfigurasjon. P? Red Hat er denne allerede inkludert i nginx-pakken, s? man trenger ikke installere noe ekstra for dette.

real_ip

For ? ta i bruk real_ip, legger man til f?lgende i "http"-seksjonen av konfigurasjon, der "..." b?de f?r og etter er resten av den eksisterende konfigurasjonen. Den relevante koden m? legges til f?r "log_format" defineres:

http {
...
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    set_real_ip_from 129.240.118.24;
    set_real_ip_from 129.240.118.31;
    set_real_ip_from 2001:700:100:8040::24;
    set_real_ip_from 2001:700:100:8040::31;
...

}

I eksempelet over sier man alts? at klientens IP-adresse ("Real IP") skal hentes fra HTTP-headeren X-Forwarded-For, og at denne informasjonen kun skal stoles p? dersom den stammer fra lastbalansererne w3prod-lb-uio01.uio.no eller w3prod-lb-uio02.uio.no, som samsvarer med IP-adressene vi her har oppgitt.

I noen tilfeller vil tjenesten settes opp p? andre lastbalanserere enn de i eksempelet, f.eks. dersom tjenesten er en test-instans, eller dersom den kj?rer i et annet milj? (OpenShift, Educloud eller annet). Det ligger en full liste over alle lastbalanserere i git, men er du usikker p? dette s? sp?r oss gjerne. Det er ogs? mulig ? si at man stoler p? hele UiOs nett, men man er da n?dt til ? ta h?yde for b?de IPv4 og IPv6. Dette er i utgangspunktet noe mindre sikkert, og gj?res i s? fall p? eget ansvar.

Loggformat

N?r man bruker real_ip-modulen i nginx, vil denne s?rge for ? benytte korrekt IP ogs? i logger. Det er dermed ikke n?dvendig ? gj?re noen ytterligere justeringer i nginx for ? f? riktige logger.

HTTP/2

I tillegg anbefaler vi at man tillater trafikk over HTTP/2, ettersom denne har langt bedre ytelse enn den eldre (og n? ganske gamle) HTTP/1.1. I webservere - ogs? nginx - m? dette vanligvis aktivt skrus p? for ? brukes. For ? f? til dette er det to ting man m? ta stilling til.

Den f?rste er hvilken versjon av nginx som brukes. Dette finner man ut med flg. kommando:

nginx -v

Det vesentlige her er hvorvidt denne er h?yere eller lavere enn 1.25.1, ettersom konfigurasjonssyntaks endret seg i denne versjonen. Hvis man bruker nginx p? Red Hat vil den v?re lavere, ettersom ingen Red Hat-versjoner forel?pig inneholder nyere versjoner enn dette. Men hvis man f.eks. kj?rer nginx i en container, eksempelvis p? OpenShift, kan det v?re man har en h?yere versjon.

Dersom man har en lavere versjon enn 1.25.1, finner man linjene som starter med listen, og legger til http2 p? slutten av disse.

Alts? hvis man har en linje som f.eks. ser slik ut:

listen 443 ssl;

Endrer man denne til ? se slik ut:

listen 443 ssl http2;

Hvis port 80 er i bruk b?r man gj?re tilsvarende endring for tilh?rende listen-linje der ogs?, men s?rg for ? lese neste punkt f?rst.

Hvis man derimot har en h?yere versjon enn 1.25.1, legger man istedet til denne linjen:

http2 on;

Denne plasseres da under listen-linjen beskrevet i forrige eksempel.

Det neste man m? ta stilling til er om trafikk fra lastbalanserer til backend (alts? nginx) g?r over HTTP (port 80) eller HTTPS (port 443). Dersom den g?r over HTTPS, vil HTTP/2 bli brukt automatisk (s? lenge man har gjort endringen beskrevet over), og man trenger ikke foreta seg noe mer. Hvis man bruker nginx i OpenShift i Passthrough-modus vil HTTPS alltid bli brukt, men man m? likevel s?rge for ? gj?re endringen beskrevet over for at det skal virke.

Hvis den derimot g?r over HTTP (port 80), vil ikke oppgradering til HTTP/2 skje av seg selv, og lastbalanserer m? eksplisitt fortelles at den skal bruke dette. Dette gj?r man ved ? be www-drift om ? legge dette til. Konfigurasjonen man skal be om er dette:

backend_http_version: proto h2

Merk at hvis man bruker nginx i OpenShift i Edge-modus trenger man per i dag ikke ? gj?re dette, ettersom det forel?pig ikke st?ttes i mellomliggende lag (OpenShifts interne router/ingress-punkt).

IIS

Ogs? Microsoft Internet Information Services (IIS) har st?tte for X-Forwarded-For, selv om denne er noe mer begrenset enn i Apache og nginx. I Apache og nginx vil relevante interne variabler i webserver endre seg slik at klientens IP (hentet fra X-Forwarded-For) i prinsippet erstatter lastbalansererens IP, men i IIS er ikke dette tilfelle. Man vil likevel kunne f? riktig IP i logger, samt ha mulighet til ? benytte benytte ACLer der dette er relevant.

Vi har dessverre forel?pig ikke dokumentasjon for hvordan dette settes opp i IIS, men vi vet at seksjon for datainnsamling og automasjon (DIA) jobber med ? f? p? plass en felles l?sning som skal gj?re det enkelt og automatisk ? f? IIS til ? generere logger i ?nsket format for DataOps, med korrekt klient-IP. Inntil videre kan man ta kontakt med DIA for ? f? hjelp til ? sette dette opp riktig.

Applikasjonsservere

Les aller f?rst avsnittet Generelt, som inneholder viktig generell informasjon om hvordan applikasjonsservere b?r settes opp. Med applikasjonsserver mener vi i hovedsak egne dedikerte prosesser som server en webapplikasjon, som regel over HTTP. Det finnes mange gode artikler som nok definerer dette bedre enn vi klarer.

Ofte betjenes en tjeneste av en applikasjonsserver. Disse finnes det utallige varianter av, med varierende st?tte for slike ting som en webserver kan tilby, som beskrevet i Generelt-avsnittet. Vi anbefaler derfor alltid at en webserver plasseres foran en evt. applikasjonsserver. F?lger man instruksjonene p? denne siden, vil man f? riktig IP i webserver, b?de i logger og ?vrig milj?. I mange tilfeller vil dette v?re tilstrekkelig.

N?r en applikasjonsserver er i bruk, bak en webserver, kan det dog hende man ogs? her ?nsker ? f? tilgang til faktisk klient-IP. Dette kan f.eks. v?re tilfelle dersom man trenger ? generere logger som inneholder brukernavn (sammen med (korrekt) IP), eller andre detaljer som en webserver ikke vil vite om n?r den kun reversproxyer foresp?rsler videre. Det kan ogs? v?re at brukers IP skal benyttes i selve tjenesten p? noe vis. Hvordan dette kan l?ses vil avhenge av hvilken applikasjonsserver man bruker, og hvilke muligheter denne gir.

Applikasjonsservere kan i denne sammenhengen litt forenklet deles opp i to kategorier:

Direkte integrert og andre protokoller

Dette gjelder f.eks.:

I disse tilfellene vil som regel milj? fra webserver arves direkte, slik at variabler vil f?lge det som er satt i webserver, inkludert kilde-IP. Har man konfigurert ting riktig i webserver skal med andre ord vanligvis dette fungere "out of the box".

Merk at av disse alternativene, er det egentlig kun FastCGI/SCGI og (u)WSGI/ASGI vi normalt ville anbefalt i dag. De andre er n? i realiteten utdaterte, og b?r som regel byttes ut med mer moderne og fremtidsrettede l?sninger.

For moduler som kj?rer direkte i webserver (mod_php, mod_perl m.fl.), samt CGI, vil mye av det som st?r skrevet om applikasjonsservere dessuten ikke v?re relevant, ettersom disse ikke kj?rer som egne prosesser uavhengig av webserver, men istedet spawnes av (eller kj?rer som del av) webserverens egen prosess. Dermed vil de s?nn sett ikke egentlig regnes som applikasjonsservere - i hvert fall ikke med definisjonen vi bruker her.

Integrert over HTTP

Dette gjelder tilfeller der webserver snakker med applikasjonsserver kun over HTTP, og dermed fungerer som en ren reversproxy. Dersom tjenesten i prinsippet kan fungere uten behov for en webserver foran, er det trolig dette dere bruker. Merk at vi anbefaler likevel at man setter en webserver mellom lastbalanserer og applikasjonsserver. Se avsnittene Generelt, samt Gjenopprette korrekt IP, for en forklaring av hvorfor dette er anbefalt.

For at en applikasjonsserver skal se korrekt IP i slike tilfeller, m? (ogs?) applikasjonsserver kunne konfigureres til ? benytte HTTP-headeren X-Forwarded-For (eller Forwarded) og beslektede headere. I hvilken grad dette er st?ttet, og hvordan st?tten er implementert, vil variere stort mellom forskjellige applikasjonsservere, og det finnes altfor mange av disse til at vi kan dekke alle her. Dersom du setter deg fast, kan du gjerne ta kontakt, s? skal vi gj?re v?rt beste for ? hjelpe.

Av headere som kan v?re nyttige finner man bl.a. X-Forwarded-By som angir hvilken lastbalanserer X-Forwarded-For ble satt av (kan benyttes til ? spesifisere hvilke lastbalanserere man vil stole p?), X-Forwarded-Proto som angir hvilken protokoll innkommende foresp?rsel benyttet (kan f.eks. benyttes til ? forhindre redirect loop til HTTPS n?r applikasjonen tror den mottar foresp?rsler over HTTP) m.fl.

PROXY protocol

Det finnes ogs? en annen m?te for lastbalanserer ? videreformidle klientens IP p?, kalt PROXY protocol, men til forskjell fra X-Forwarded-For opererer denne i TCP-laget. Dette forutsetter at backend st?tter denne protokollen (hvilket b?de Apache og nginx gj?r), samt at st?tte for den aktiveres for tjenesten i lastbalanserer. Vi bruker ikke PROXY protocol noe s?rlig per i dag, men den kan v?re grei ? vite om. Den er ogs? beste l?sning der andre protokoller enn HTTP skal lastbalanseres, men dette gj?res kun unntaksvis.

Tilgangskontroll

Noen ganger har man behov for ? begrense tilgang basert p? IP, enten til spesifikke nett (subnett/CIDR) eller til enkelt(e) IP-adresse(r). Et vanlig bruksomr?de er ? begrense tilgang til klienter p? UiO-nett. Vi anbefaler at dette gj?res i webserver, som beskrevet i Generelt-avsnittet. Ved ? f?lge eksemplene over, "gjenopprettes" kilde-IP av webserver, slik ting fungerer p? samme m?te som n?r det ikke er et revers-proxy-lag med lastbalansering imellom. Dermed vil man kunne benytte vanlig ACL-funksjonalitet i webserver, akkurat som vanlig.

N?r man setter opp IP-basert tilgangskontroll, anbefaler vi at det benyttes en egen feilmeldingsside til dette. Denne kan gjerne forklare at tilgang nektes fordi man ikke kommer fra riktig nett eller IP, slik at bruker f?r en indikasjon p? hva som kan eller m? gj?res for ? f? tilgang til tjenesten (selvsagt uten ? avsl?re potensielt sensitive detaljer). P? denne siden kan det gjerne ogs? linkes til andre sider med mer informasjon om dette, der dette finnes. Se et godt eksempel p? hvordan dette kan se ut p? siden Brukerinfo har opprettet til dette form?let.

Det er ogs? mulig ? legge inn IP-basert tilgangskontroll for en tjeneste direkte i lastbalanserer, men dette frar?der vi. Dette er mer komplisert ? vedlikeholde, da alle endringer n?dvendigvis m? involvere www-drift som drifter lastbalanseringsl?sningen, til forskjell fra i webserver hvor man styrer dette helt selv. Det vil dessuten resultere i en mindre brukervennlig og hjelpsom feilmeldingsside, da denne vil v?re en generisk type som ikke gir noen indikasjon p? hvorfor tilgang nektes, og kan forveksles med feilmeldinger man mottar n?r manglende tilgang skyldes helt andre ?rsaker. Dette kan igjen medf?re un?dvendig ?kt trykk p? IT-hjelp, som da kan motta saker fra brukere som ikke skj?nner hvorfor de ikke f?r tilgang.

Publisert 12. nov. 2024 14:12 - Sist endret 20. jan. 2025 13:14