Nginx jako reverzní proxy pro Apache

17. 6. 2011
Doba čtení: 6 minut

Sdílet

Webový server Apache už dnes nepatří mezi světovou špičku, ale pořád má vlastnosti, které u jiných webových serverů nenajdeme. Bohužel se na nich staly závislé i některé populární projekty a i přes nebezpečí ho jen tak do kanálu hodit nemůžeme. Tak proč si trochu nepomoci stále populárnějším webovým serverem Nginx.

Není to tak dlouho, co jsme na Rootu psali o lehkém webovém serveru lighttpd. Čtyřdílný seriál, který ukázal, že lighttpd dokáže zastoupit jiná řešení a není to ani moc náročné. Vývoj lighttpd nyní stojí, poslední stabilní verze 1.4.28 byla vydána 22. srpna 2010. Ve své době měl hodně příznivců a třeba servery jako Wikipedia nebo YouTube se svěřily do jeho binárních rukou. Web se „bohužel“ vyvíjí a když nějaký projekt zůstane stát, najde se jiný, který mu ukáže záda. V případě lighttpd by to mohl být Nginx, univerzální, rychlé a bezpečné řešení webového serveru.

K napsání tohoto článku a vůbec nasazení serveru Nginx jako reverzní proxy pro Apache mě inspiroval článek Petra Krčmářeútoku slow loris. Jednoduchý útok, který už v minulosti potrápil mnoho administrátorů webových serverů. Prostředkem jsou vytvořená spojení, kterými se jako plíživé veverky sune několik bytů dat. Webový server s citlivou architekturou pak netrpělivě čeká na dokončení požadavku, ale ten nepřijde a když narazí na limit počtu spojení, tak to s dalšími požadavky dopadne špatně a budou odmítnuty. Takový server nereaguje a v logu není ani zmínka o tom, že je něco špatně.

Apache takovou citlivou architekturou disponuje a i když použijete třeba mod_antiloris nebo si nastavíte dobře firewall, tak to během slow loris útoku stejně nemusí být ono. V praxi se bohužel bez Apache často neobejdeme. Máte-li webový server jen pro sebe, tak není problém vzít Nginx nebo lighttpd, nastartovat PHP přes FastCGI a spojit to všechno dohromady. U jiných jazyků to funguje samozřejmě podobně. V opačném případě, kdy jsou na serveru různé aplikace s různými požadavky a hlavně různých lidí, nemusí být reálné dát Apache pryč. Pořád disponuje vlastnostmi, na kterých jsou některé aplikace závislé. Nejlepším příkladem je v tomhle modrewrite, bez kterého někdy prostě vlak nejede.

A jsme na pomezí dvou světů. Na jedné straně je uživatel, který třeba i platí a na druhé straně je bezpečnost. Pokud se navíc zamyslíte a uděláte pár testů, tak zjistíte, že Apache není nejefektivnější a když před něj strčíte proxy, tak serveru najednou spadne load o pár desetinek dolů. To znamená, že server bude odpovídat rychleji, a také to, že na něj najednou dostanete třeba o polovinu více webů, a to už začíná být zajímavé.

Nginx jako vstupní brána do Apache

Apache někdy zůstat musí, s tím nic neuděláme, ale určitě bychom ho neměli motat tam, kde je jeho přítomnost zbytečná a někdy dokonce i na škodu. Navíc by se mohlo hodit, když ho schováme na lokální adrese a nebudeme ho ukazovat venku. Často se o náhradě Apache mluví při servírování statického obsahu webu, kde může probíhat několik desítek požadavků s každým načteným HTML dokumentem. To je přesně to místo, kde je Apache na škodu, protože Nginx si vede v podobných situacích mnohem lépe. Subjektivně se dá také říct, že se i lépe konfiguruje.

Webový server Nginx najdete snad ve všech hlavních linuxových distribucích, takže ho stačí nainstalovat z balíčkovacího systému. Kompilace ze zdrojových kódů není nějak zvlášť komplikovaná, ale určitě je pracnější.

Nginx proti Apachi dokáže udržet konstantní čas na odpověď. To samozřejmě nemůže být pravda do nekonečna, ale třeba testy na joeandmotorbo­at.com ukazují, že Nginx si tento parametr udržel na více požadavcích než Apache.

Nebudeme dále chodit kolem horké kaše, tady je konfigurační soubor nginx.conf, který najdete většinou v adresáři /etc/nginx/.

user                www-data www-data;
worker_processes    2;

error_log           /var/log/nginx/error.log warn;
pid                 /var/run/nginx.pid;

events {
    worker_connections  1024;
    use epoll;
}

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

    # Logování
    log_format main '$remote_addr - $remote_user [$time_local] '
            '"$request" $status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" "$http_x_forwarded_for"';

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

    # spool uploads to disk instead of clobbering downstream servers
    client_body_temp_path /var/spool/nginx-client-body 1 2;
    client_max_body_size 32m;
    client_body_buffer_size    128k;

    # Nezveřejňovat verzi serveru na chybových stránkách
    server_tokens       off;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         off;

    keepalive_timeout   5;

    # Komprese
    gzip on;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_min_length  1100;
    gzip_buffers 16 8k;
    gzip_types text/xml text/plain text/css application/x-javascript application/xml application/xml+rss text/javascript;#text/html

    # Vypneme kompresi pokud má uživatel IE6
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_vary on;

    # nastavení proxy
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    # Proměnné v hlavičce, důležité pro logování
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_max_temp_file_size 0;

    # Časové limity
    proxy_connect_timeout      90;
    proxy_send_timeout         90;
    proxy_read_timeout         90;

    proxy_buffer_size          4k;
    proxy_buffers              4 32k;
    proxy_busy_buffers_size    64k;
    proxy_temp_file_write_size 64k;

    include             /etc/nginx/sites-enabled/*;

} 

Konfigurák je možná trochu delší, ale o to bude jednodušší konfigurace jednotlivých virtual hostů. Názvy konfiguračních voleb jsou naštěstí dostatečně výstižné, ale pokud by náhodou nebyly, pomůže přehledně zpracovaná dokumentace.

Důležité parametry pro běh Nginxu máme a můžeme jít k jednotlivým webům. Konfiguraci pro weby si od hlavního konfiguráku oddělíme a umístíme ji do /etc/nginx/sites-enabled/. Zde se musíme rozhodnout, jestli chceme využít jen proxy na všechno a zabránit tak využívání některých bezpečnostních problémů Apache, mezi které se řadí i slow loris a nebo to uděláme „lépe“ a budeme Nginxem servírovat i statická data.

V prvním případě uložíme do souboru /etc/nginx/sites-enabled/defau­lt.conf něco takového.

server {
    listen       80 default_server;
    # Do server name dáme nějaký nesmysl
    server_name  _;

    # Vypneme logování nebo nastavíme správnou cestu
    access_log  off;
    error_log off;

    # Reverzní proxy pro web server běžící na localhostu
    location / {
        proxy_pass         http://127.0.0.1:80/;
    }
} 

V tomto případě bude Nginx všechny požadavky předávat Apachi, který běží na lokální adrese nepřístupné z venku. Tento kousek konfiguráku bude zpracovávat všechny požadavky a bude předávat i řádek s Host v HTTP hlavičce. Tím pokryje všechny domény. Díky tomu, že jsme na začátku nastavily předávání proměnných X-Real-IP a X-Forwarded-For, budeme moci z Apache dostávat i správné logy, ale o tom níže.

Efektivnější je si dát práci s konfiguračním souborem pro každou doménu a servírovat Nginxem i statický obsah.

server {
    listen       80;
    server_name  example.com;

    access_log  off;
    error_log off;

    # Vypneme logování nebo nastavíme správnou cestu
    location / {
        proxy_pass         http://127.0.0.1:80/;
    }

    location /static {
        alias /var/www/static;
    }

    location /static2 {
        alias /var/www/static2;
    }
} 

Proti předchozímu příkladu přibylo sedm řádek na konci, které se postarají o to, aby požadavek na cokoli ve /static a /static2 neprošel do Apache, ale rovnou vrátil potřebný obsah.

Logování v Apachi

S požadavkem od proxy přijdou v hlavičce také proměnné X-Real-IP a X-Forwarded-For. Po nainstalování modulu mod_rpaf, bude Apache dávat pozor, jestli náhodou není X-Forwarded-For v HTTP hlavičce a pokud ano, řekne Apachi, že jde o tuto adresu a ten ji použije při logování. To samozřejmě nebude efektivní, pokud budeme statické soubory řešit na Nginxu. V takovém případě je možná rozumnější vytvářet logy tam.

bitcoin školení listopad 24

Závěr

Nginx je univerzální nástroj, který se umí dobře přizpůsobovat různým situacím. Dobře komunikuje s Pythonem, Ruby, PHP i s jinými webovými servery, jak jste se mohli přesvědčit výše. Zvládá také zabezpečení přes SSL.

Jeho autorem je rus Igor Sysoev a poprvé byl zveřejněn v roce 2004. Momentálně je používán přibližně na 6 % z milionu nejvýznamnějších stránek na světě.

Autor článku

Adam Štrauch je redaktorem serveru Root.cz a svobodný software nasazuje jak na desktopech tak i na routerech a serverech. Ve svém volném čase se stará o komunitní síť, ve které je již přes 100 členů.