Nginx ako reverzny proxy server

Nginx je webový server, ktorý je možne nastaviť okrem iného aj ako reverzný proxy server. V tomto blogu ukážem ako som nastavoval reverzný proxy server a vysvetlím prečo takýto server potrebujeme. Ja som na to mal špecificky dôvod, kde som potreboval 2 webové servery na rôznych lokálnych IP adresách, sprístupniť na verejnej sieti (internet).

Ako je na tom nginx

Nginx je veľmi populárny open source webový server. Podľa meraní w3techs veľmi rýchlo dobehuje aj legendárny Apache. Aby to bolo porovnanie objektívnejšie, tak okrem Apache a Nginx je do meraní pridany aj ISS od MicroSoftu. Tvorcom nginxu je náš priateľ z bývalého Sovietskeho zväzu Igor Sysoev, ktorý už ale stihol nginx predať Američanom za 670 000 000 $. Od zákulisných problémov sa radšej presunieme do reálu.

Percentuálne porovnanie najznámejších webových serverov

Nastolenie problému

Môj problém vznikol takto: V linuxovom kontajnery s OS Debian 9 prevádzkujem klasický LAMP s niekoľko virtualhostami. V súčasnej dobe by som chcel prejsť na Debian 10. Nerád by som však robil dist-upgrad na Debian 10, ale radšej by som išiel od nuly. Linuxový kontajner mám pripravený. Stačilo by doinštalovať LAMP, synchronizovať webové adresáre, presunúť databázy a mountnuť file systém. Na starom servery mi okrem iného beží NextCloud a na nový server by som chcel nasadiť NextCloud Hub. Do nového cloudu chcem integrovať aj OnlyOffice a to my zrejme zabere nejaký čas. Starý NextCloud nechcem odstavovať, pokiaľ nebude nový plne funkčný. Takáto situácia si vyžaduje 2 servery, pochopiteľne s dvoma lokálnymi IP adresami. Vystaviť 2 a viac serverov do internetu na štandardných portoch za jednou verejnou IP adresou je dosť problém. Riešením je reverzný proxy server.

Čiže ako som už spomínal mám LXC Debian 9 s LAMP. Ďalší LXC s LAMP v ktorom budem testovať je potrebné nainštalovať. A nakoniec posledný LXC bude slúžiť ako reverzný proxy.

OSIP adresaServerNasadený akoTyp serveraStav
Debian 10192.168.1.10Nginxfrontendreverzný proxynový
Debian 10192.168.1.11Apachebackendwebový servernový
Debian 9192.168.1.12Apachebackendwebový serverstarý

Rozdiel medzi proxy a reverzným proxy

Ešte by som chcel vysvetliť čo je to vlastne proxy server. Majme nejakú spoločnosť (firmu), kde je veľká počítačová sieť a na tej sieti strašne veľa počítačov, ktoré pristupujú na internet. Niekde pred firewallom sa postavi proxy server a keď klient odošle požiadavku na internet, tak najprv sa skontroluje, či odpoveď nie je v cache na proxy. Ak nie, tak proxy preposiela požiadavku na internet. Odpoveď z internetu smeruje znova na proxy a proxy ju preposiela klientovi. Takéto proxy servery majú obrovské cache disky a klient kvázi nekomunikuje priamo z internetom, ale len z proxy serverom. Zo strany firmy to má určite výhody, ale zo strany zamestnanca to mohlo byť obmedzujúce.

Reverzný proxy server vykonáva to isté, ale trocha obrátene. Reverzné proxy servery (frontendy) sú umiestnené pred webovými servermi (backendami) a očakávajú požiadavky od klientov. Ak request od klientov nevyžaduje nejakú operáciu od backendov, tak frontend odpovedá rovno klietom. A keďže nginx je oproti apache serveru oveľa rýchlejší, tak sa veľmi hodí ako reverzný proxy.

Vzťah medzi proxy serverom a reverzným proxy severom

Výhody nginx servera

Spomeniem aspoň niektoré výhody nginix reverzných proxy:

  • Cache pre statický obsah (nezaťaží backend)
  • LoadBalancig (vyrovnávanie záťaže)
  • Klient nemá priamy prístup na webový server
  • Premapovanie portov rôznych aplikácii
  • Vyriešenie šifrovania SSL/TLS
  • Možná kompresia dát
  • Šetrenie verejných IPv4 adries

Princíp reverzného proxy

Dajme tomu, že máme zákazníka, ktorý si bude chcieť riešiť vlastný webový server a bude žiadať o poskytnutie IaaS. V praxi sa to zrejme nestáva často, pretože väčšinou, poskytovatelia takýchto služieb ku každému virtuálnemu stroju, alebo kontajneru poskytujú aj verejnú Ipv4 a IPv6 adresu. Avšak keď chce poskytovateľ ušetriť verejné IPv4 adresy, môže byť reverzný proxy jedným z riešení. Moja situácia je nasledovná

Ak chceme aby sa ku klientovi dostal webový obsah zo správneho servera a disponujeme jednou verejnou IPv4 adresou, tak reverzný proxy postavíme v roli frontendu pred apache, ktoré budu v roli backendov.

Najprv si všetko vyskúšame na lokálnej (LAN) sieti. Ako som už uviedol, tak máme 3 servery (viď obrázok, alebo tabuľku vyššie). Každý server má nastavenú statickú IP adresu. Či sú servery postavené na fyzickom železe, VM, alebo kontajnery nie je podstatné (ja to testujem v kontajneroch).

Inštalácia Apache2 servera

Cieľom tohto článku nie je návod ako nainštalovať a nakonfigurovať webové servery, ale aspoň v stručnosti to popíšem aby sme vedeli ktorý server nám bude odpovedať. Servery budú postavené na Debiane 10 (9). Inštalácia Apache servera spočíva v zadaní jediného príkazu

sudo apt update && sudo apt upgrade
sudo apt install apache2 -y

Na manipuláciu so serverom použijeme klasické príkazy na zistenie stavu, vypnutie, zapnutie a reštart

sudo systemctl status|stop|start|restart apache2
sudo systemctl enable apache2

Ihneď po nainštalovaní by mal webový server bežať pod IP adresou servera. Čiže keď do webového prehliadača zadáme 192.168.1.11, tak by sme mali vidieť toto

Ak vytvárame zároveň aj druhý testovací server na IP adrese 192.168.1.12, tak na obidvoch IP adresách uvidíme to isté. Servery si musíme preto rozlíšiť a to spravíme následovne. Najprv si pripravíme koreňový adresár pre webové súbory, zmeníme vlastníka a vytvoríme indexoví súbor

sudo mkdir -p /var/www/html/www.first-domain.com/
sudo chown -R www-data:www-data /var/www/html/www.first-domain.com/
sudo nano /var/www/html/www.first-domain.com/index.html
<html>
    <head>
        <title>Welcome to first-domain.com</title>
    </head>
    <body>
        <h1>It's virtualhost for first-domain.com</h1>
    </body>
</html>

Vytvoríme konfiguračný súbor pre apache

sudo nano /etc/apache2/sites-available/www.first-domain.com.conf

Do konfiguračného súboru vložíme

&lt;VirtualHost *:80>
    ServerAdmin admin@first-domain.com
    ServerName first-domain.com
    ServerAlias www.first-domain.com
    DocumentRoot /var/www/html/www.first-domain.com/
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
&lt;/VirtualHost>
sudo a2ensite www.first-domain.com.conf
sudo a2dissite 000-default.conf
sudo systemctl restart apache2

Keď zadáme do webového prehliadača IP adresu 192.168.1.11 teraz, tak uvidíme čistú web stránku, kde bude napísane It’s virtualhost for first-domain.com.

Toto isté spravíme aj na druhom webovom servery s IP adresou 192.168.1.12 s tým rozdielom, že nahradíme sekvenciu first-domain.com inou sekvenciou, napr. second-domain.com. Následne vo web prehliadači zadáme 192.168.1.12 a uvidíme text It’s virtualhost for second-domain.com. Teraz vieme, že obidva servery sú v poriadku a fungujú správne.

Statické DNS záznamy

V závislosti od toho aký používame router si najprv nastavíme statické DNS „A“ záznamy. DNS záznam typu „A“ slúži pre nastavanie IP adresy, z ktorej sa má načítavať obsah pre danú doménu. Nie som si istý či majú možnosť vytvárať „A“ záznamy aj lacnejšie sieťové zariadenia (routery), ale na pfsense, openwrt, mikrotik, to určite funguje. Takže si môžeme nastaviť na routery A záznamy takto, aby sa doménové meno preložilo na IP adresu konkrétneho servera.

first-domain.com   --->  192.168.1.11
second-domain.com  --->  192.168.1.12

Keď do web prehliadača zadáme first-domain.com tak sa nám zobrazí nápis It’s virtualhost for first-domain.com a keď zadáme second-domain.com, tak sa nám zobrazí It’s virtualhost for second-domain.com. Super! apache fungujú aj z lokálnymi doménami. Ak by sme zo servermi operovali len na lokálnej sieti, tak žiadny reverzný proxy nepotrebujeme, pretože každý server má lokálnu IP adresu a funguje na štandardnom http (80) porte. V lokálnej sieti sa na server dostane každý klient, pokiaľ to neobmedzíme pravidlami firewallu.

Overenie funkčnosti oboch webových serverov

Inštalácia a nastavenie nginx servera

Teraz môžeme pristúpiť k tomu o čom je tento blog a to je reverzný proxy server. Ako už bolo spomenuté, reverzný proxy server postavíme v linuxovým kontajnerom na IP adrese 192.168.1.10. Prihlásime sa na LXC cez ssh a nainštalujeme nginx

ssh name@192.168.1.10
sudo apt update && sudo apt upgrade
sudo apt install nginx -y

Na zistenie stavu (resp. stop, štart, reload) použijeme podobné príkazy ako pri apache (reload načíta konfiguračný súbor bez reštartu služby).

systemctl status|stop|start|reload nginx

Bežiaci nginx vyzerá následovne

* nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-04-07 14:32:54 UTC; 20h ago
     Docs: man:nginx(8)
  Process: 515 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 516 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 517 (nginx)
    Tasks: 2 (limit: 4915)
   Memory: 3.1M
   CGroup: /system.slice/nginx.service
           |-517 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           `-518 nginx: worker process

Ak zadáme IP adresu 192.168.1.10 do web prehliadača, tak uvidíme

Môžeme sa prihlásiť ako root, alebo môžeme pracovať pod užívateľom sudo. Najprv vymažeme obsah adresára (default konfiguračný súbor si môžeme zálohovať) a potom si nastavíme vlastný konfigurák

rm -rf /etc/nginx/sites-enabled/*
nano /etc/nginx/sites-available/000-default

V konfiguračnom súbore nastavíme aby boli požiadavky prichádzajúce na reverzný proxy forwardované na konkrétne IP adresy backendových serverov. Najdôležitejšou direktívou pri konfigurácii je proxy_pass. Tam bude nginx smerovať prevádzku.

server {
    listen 80;
    server_name first-domain.com www.first-domain.com;

    location / {
        proxy_pass http://192.168.1.11;
        proxy_set_header Host $host;
        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 $scheme;
    }
}

server {
    listen 80;
    server_name second-domain.com www.second-domain.com;

    location / {
        proxy_pass http://192.168.1.12;
        proxy_set_header Host $host;
        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 $scheme;
    }
}

Skontrolujeme či je konfiguračný súbor po syntaktickej stránke v poriadku (riadok 2 a 3 hovoria, že všetko je OK a test skončil úspešne) a vytvoríme symlink do etc/nginx/sites-enabled/

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
ln -s /etc/nginx/sites-available/000-default /etc/nginx/sites-enabled/000-default
systemctl reload nginx

A najdôležitejšou úlohou je aby sme nezabudli zmeniť na lokálnom DNS servery „A“ záznamy, ktoré majú smerovať na reverzný proxy server.

first-domain.com   --->  192.168.1.10
second-domain.com  --->  192.168.1.10

V tomto momente by nám mali fungovať obidva servery cez reverzný proxy server nginx, ktorý preposiela požiadavky na apache servery. Ako som už viac krát v blogu spomínal, webové servey potrebujeme mať prístupne z vonkajšej strany (z internetu). Bola by tu možnosť mať prístupne weby z internetu aj bez reverzného proxy servera, ale museli by sme mapovať IP adresu na rôznych portoch. Potom by naše url adresy vyzerali veľmi nepekne.

first-domain.com:8081
second-domain.com:8082

Založime si verejnu doménú

Keď chceme aby boli naše servery dostupné z internetu musíme mať platné doménové meno. Doménu si môžeme založiť na niektorom free dns servery. Takýchto serverov je množstvo a väčšinou ponúkajú domény tretieho radu zdarma. Existujú však dns servery, ktoré ponúkajú doménu druhého radu zdarma, napr. freenom. Ja mám založené radovo jednotky domén na freenom, changeip a noip. Ak máme vytvorené domény, tak skontrolujeme, či sa „A“ záznam zhoduje s našou verejnou IPv4 adresou. Predpokladajme, že naše verejné domény budú

first-domain.ddns.net
second-domain.ddns.net

Nastavujeme NAT na pfsense

Poslednou našou úlohou je spraviť NAT na našom routery/firewalle. Ako je známe, ja som prešiel v roku 2020 z ROS mikrotik na firewall pfsense. Takže NAT spravím na pfsense. Prihlásime sa do pfsense webového rozhrania a prejdeme do

Firewall ---> NAT  ---> Port Forward ---> Add

Pravidlo nastavíme podľa obrázku

Forward portu 80

Ešte si môžeme preveriť, či port 80, je skutočne na našej verejnej IPv4 adrese otvorený. Ak je port zavretý, tak je niekde chyba a nebude to fungovať.

Prístup na servery a fungovanie DNS

Veľmi v skratke vysvetlím ako to bude fungovať. Klient sa môže nachádzať kdekoľvek na svete (samozrejme musí mať prístup na internet). Zadaním doménového mena napr. first-domain.ddns.net (upozorňujem že mená sú vymyslené) do web prehliadača, dáva klient info knižničnej funkcii stub resolver aby sa opýtal najbližšieho rekurzivného resolvera, či vie niečo o first-domain.ddns.net. Najbližší resolver je zvyčajne cache a súbor /etc/hosts v PC. Ak sa táto doména nachádza v cache, alebo /etc/hosts, tak klientovi okamžite vráti odpoveď a tým pádom mame vyriešený problém. Ak sa v cache daný záznam nenachádza, tak sa kontaktuje nadradený resolver a ten je vo väčšine prípadov na lokálnom smerovači v LAN. Znova sa prehľadá cache, príp. statické DNS záznamy a v prípade neúspechu sa kontaktuje ďalší nadradený resolver a to je väčšinou DNS rekurzívny resolver ISP. proces vyhľadávania záznamu v cache sa znova opakuje a v prípade neúspechu resolver kontaktuje niektorý z 13 koreňových DNS serverov (spravovaných IANAou). Koreňový DNS tak isto netuší, kde sa nachádza first-domain.ddns.net. Keďže DNS fungujú hierarchicky, tak tuší, kde sa nachádza generická TLD (Top Level Domain) net. Resolveru odošle ďalšie DNS servery, ktoré spravujú TLD net. Na základe toho resolver kontaktuje ďalší DNS server, ktorý tak isto nič netuší o first-domain.ddns.net, ale vie na ktorých autoritatívnych DNS serveroch sa nachádza ddns.net. Tento DNS server odošle resolveru adresy Name Serverov, ktoré spravuje ddns.net. Ten si vo svojej tabuľke vyhľadá first-domain.ddns.net a aj „A“ záznam (čo je naša verejná IPv4 adresa) a posiela resolveru odpoveď, že k doméne first-domain.ddns.net prislúcha IP adresa xx.xx.xx.xx. Resolver si tieto údaje uloží do cache a klientovi už odosiela IP adresu, ktorú má kontaktovať. Paket od klienta bude teraz nasmerovaný na správnu IP adresu. V hlavičke IP paketu je zadaná cieľová a zdrojová IP, cieľový a zdrojový port. NAT spraví preklad adries a paket presmeruje na IP adresu v lokálnej sieti 192.168.1.10. Potom preberá úlohu už reverzný proxy server a smeruje paket na správny server, príp. virtualhost. Ten spracuje požiadavku od klienta a posiela paket skrz reverzný proxy na najbližší uzol v sieti čo je naša brána (GW). Znova dôjde k preloženiu IP adresy a modifikácii paketu, kde sa v hlavičke menia cieľové a zdrojové údaje a paket smeruje k odosielateľovi požiadavky a na koniec dostáva klient o to čo žiadal.

Záver

Dnes sme sa dozvedeli niečo o reverznom proxy servery nginx. Povedali sme si ako funguje a na aké účely sa dá použiť. V našom prípade sme ho využili ako reverzný proxy z viacerými webovými servermi za jednou verejnou IP adresou. Musím však spomenúť, že dosť dlho som sa rozhodoval, či postavím reverzný proxy server na platforme pfsense s balíkom haproxy, alebo na LXC s nginx. Aj keď som haproxy testoval a fungovalo to, tak nakoniec som sa rozhodol pre nginx. Ak mi to čas dovolí, tak ďalšia vec, ktorú by som chcel uskutočniť je SSL/TLS šifrovanie za pomoci certbot s CA od Let’s Encrypt, ktorá bude spravovaná na reverznom proxy. Celkom nakoniec spomeniem, že tento návod nerieši žiadnu bezpečnosť. Čo sa týka pravidiel firewallu, tak je potrebne použiť UFW, alebo si nastaviť iptables.

Leave a Reply

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *