43
Nginx Workshop Aftermath Kiev.PM technical meeting, 16th Feb 2012 Denis Zhdanov [email protected]

Nginx Workshop Aftermath

Embed Size (px)

DESCRIPTION

My upcoming presentation for Kiev.PM meeting

Citation preview

Page 1: Nginx Workshop Aftermath

Nginx Workshop Aftermath

Kiev.PM technical meeting, 16th Feb 2012

Denis [email protected]

Page 2: Nginx Workshop Aftermath

Disclaimer

May 29, 2010 - Nginx workshop by Igor Sysoev was organized by SmartMe (http://www.smartme.com.ua/nginx-workshop/)Thanks Igor, thanks SmartMe.Based on workshop, but Nginx was changed, so caching and many other docs are on website now (http://wiki.nginx.org), so I add some things from me. "Scooter is ... ? "

Page 3: Nginx Workshop Aftermath

Nginx / Apache - why we need what ?

1. Static files2. Proxying / Slow client (No dialup but Mobile) Why Apache is bad / Nginx is good - size of worker. Apache is prefork / 1 proc/thread per request - it's too expensive.Nginx - Proc/thread also, but event driven.

Page 4: Nginx Workshop Aftermath

Nginx is fast?

"Nginx is not fast - but scalable", (c) Igor Sysoev.Tens and hundreds of 1000's requests per worker - quite fast, butApache can do this also - but with much more resources. Nginx also has SCALABLE configuration.What is it means?

Page 5: Nginx Workshop Aftermath

How we can configure Apache ?

1. .htaccess / rewrite rules - ugly, but single way on shared hostings ( I hope they all gone now :) ) 2. Virtual hosts - but global (default) server configuration could mess all things. 3. Virtual hosts but default server do nothing (deny all, for example)

Page 6: Nginx Workshop Aftermath

locations

location /images/location = /location ^~ /images/ - plain strings, no order location ~ \.phplocation ~* \.php - regexp rules, ordered location @php - named

Page 7: Nginx Workshop Aftermath

plain vs regexp

location /location /admin/ VS - no difference !location /admin/location / But regexp is ordered, so ...

Page 8: Nginx Workshop Aftermath

location ~* \.(gif|jpe?g|png)$ {root /var/www/images/;

}location ~* \.php$ {

fastcgi_pass ...} location /images/ {

root /var/www/images/;}location /scripts/ {

fastcgi_pass ...}

Page 9: Nginx Workshop Aftermath

Real example

location / { if ($uri ~ ^/login\.php$) { ...} if ($uri ~ ^/admin/) {...}

Page 10: Nginx Workshop Aftermath

Nested locations

location /images/ {root /var/www/images;

}location /admin/ {

location ^/admin*.\.php$ {fastcgi_pass....

}}...

Page 11: Nginx Workshop Aftermath

Directives: declarative vs runtime

Declarative - no ordering, inheritance

proxy_connect_timeout 25s;server {

location / { }location = / {}location = /x {

proxy_pass http://backend;}root /var/www/;

}

Page 12: Nginx Workshop Aftermath

Runtime directives

Runs every time, no inheritance ! if (....) {

set ...rewrite ...break

return ....}

Page 13: Nginx Workshop Aftermath

Bad examples

location /images/ {root /var/www/images/;

break; # <---- WHY???} if (-e $request_filename) {

expire 1y; break; # totally wrong !!}

Page 14: Nginx Workshop Aftermath

Igor says: Do not use rewrites! :)

if (...) {return 403; # good usage

} location ~ ^/images/(.+)$ {

root /var/www/img/$1; # bad} Why ?

Page 15: Nginx Workshop Aftermath

Root semantic VS alias semanticGET /images/test/one.jpg location /images/ {

root /var/www/;# path - /var/www/images/test/one.jpg

} location /images/ {

alias /var/www/img/;# path - /var/www/img/test/one.jpg

}

Page 16: Nginx Workshop Aftermath

Alias instead of root

location /images/ {alias /var/www/images/;

} location /images/ {

root /var/www;}

Page 17: Nginx Workshop Aftermath

Alias and root with variablesGET /images/one.jpg location /images/ {

root /var/www/$host;} # real path - /var/www/SITE/images/one.jpg location ~ ^/images/(.)(.+)$ {

alias /var/www/img/$1/$1$2;} # real path - /var/www/img/o/one.jpg Alias make complete path, no replacementMUST use $1/$2 if location contains captures

Page 18: Nginx Workshop Aftermath

proxy_pass semantic

GET /images/test/one.jpg location /images/ {

proxy_path http://backend; # <-- no URI} # Root semantic -GET http://backend/images/test/one.jpg location /images/ {

proxy_path http://backend/img/;} # Alias semanticGhttp://backend/img/test/one.jpg

Page 19: Nginx Workshop Aftermath

proxy_pass with variables

GET /images/one.jpg location ^/images/(.)(.+)$ {

proxy_pass http://backend/$1/$1$2;} # --> http://backend/o/one.jpg# Alias semantic, but path is replaced location ^/images/(.).+$ {

proxy_pass $1; # not part of URI} # --> http://o/images/one.jpg# Root semantic

Page 20: Nginx Workshop Aftermath

location handlers

proxy_pass, fastcgi_pass, memcached_pass, empty_gif, flv, stub_status, perl trailing slash - random index / index / auto index no trailing slash -gzip static / static

Page 21: Nginx Workshop Aftermath

Why "if" is bad - it's "location" too

gzip on;keepalive on;if ($no_gzip) {

gzip off; # gzip off}if ($no_keepalive) { keepalive off; # gzip on, keepalive off}# gzip on, keepalive on

Page 22: Nginx Workshop Aftermath

Fix - but it's not recommended

gzip on;keepalive on;if ($no_gzip) {

gzip off; break;}if ($no_keepalive) { keepalive off; break;}

Page 23: Nginx Workshop Aftermath

Caching

Page 24: Nginx Workshop Aftermath

Couple of caveatsfrom my Apache to Nginx migration

Page 25: Nginx Workshop Aftermath

Migration from Apache to Nginx Apache:RewriteCond %{HTTP_HOST} ^site\.com$ [NC]RewriteRule ^(.*)$ http://www.site.com/$1 [R=301,L]# www redirect, common stuff out there Nginx: if ($host = 'site.com') {

rewrite ^(.*)$ http://www.site.com/$1 permanent; # MY EYES!!!}

Page 26: Nginx Workshop Aftermath

Apache:RewriteCond %{HTTP_HOST} ^site\.com$ [NC]RewriteRule ^(.*)$ http://www.site.com/$1 [R=301,L]# www redirect, common stuff out there Nginx:server {

server_name site.com;rewrite ^ http://www.site.com/$request_uri? permanent;# NOT BAD

}

Right way to do it

Page 27: Nginx Workshop Aftermath

Another common thing

RewriteCond %{REQUEST_FILENAME} -dRewriteCond %{REQUEST_FILENAME} -fRewriteRule .* index.php # right waylocation / {

try files $uri $uri index.php$is_args$args;}

Page 28: Nginx Workshop Aftermath

FCGI security caveat

location ~* \.php$ {fastcgi_pass 127.0.0.1:9000;

fastcgi_param SCRIPT_FILENAME $script;fastcgi_param PATH_INFO $path_info;

....}This PHP app supports upload of files...Do you mention possible security breach? :)

Page 29: Nginx Workshop Aftermath

PATHINFO links

GET /index.php/article/0001 => SCRIPT_NAME = 0001PATH_INFO = /index.php/article/ - WRONG Fix pathinfo magic - SCRIPT_NAME = index.phpPATH_INFO = /article/0001

Page 30: Nginx Workshop Aftermath

GET /upload/evil.jpg/notexist.php

SCRIPT_NAME = notexist.phpPATH_INFO = /upload/evil.jpg/ cgi.fix_pathinfo = 1 (yep, it's default) - if SCRIPT_NAME not found - let's "FIX" it - SCRIPT_NAME = evil.jpgPATH_INFO = /notexist.phpLet's RUN evil.jpg ! :)

Page 31: Nginx Workshop Aftermath

Solutionlocation ~* \.php$ {

try_files $uri = 404;fastcgi_pass 127.0.0.1:9000;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_scriptname;fastcgi_param PATH_INFO $fastcgi_pathinfo;

....}

- if you do not need PATHINFO links OR

Page 32: Nginx Workshop Aftermath

Use fastcgi_split_path_info location ~* ^(.+\.php)(.*)$ { fastcgi_split_path_info ^(.+\.php)(.*)$;

fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_scriptname;

fastcgi_param PATH_INFO $fastcgi_pathinfo;}

GET /index.php/article/0001 =>SCRIPT_FILENAME = index.php, PATH_INFO = /article/0001

Page 33: Nginx Workshop Aftermath

Please check

http://wiki.nginx.org/Pitfalls - lot of stuff there

Page 34: Nginx Workshop Aftermath

Just couple of words

Nginx optimization

Page 35: Nginx Workshop Aftermath

Case 1. Big static files

What is BIG file? Size is >2Mb (mp3, zip, iso etc)a)RAID - use big stripe size (>128K)b) output_buffers 1 1m; # need to tunec) AIO:Freebsd:sendfile on;aio sendfile;Linuxaio on;directio on; # required but drops sendfile()

Page 36: Nginx Workshop Aftermath

Case 2. Lot of small files

a). There is NO MAGICHot files must reside in RAM cache or else... it will be slow. b) Tune open_file_cache Freebsd: see dirhash, vfs.ufs.dirhash_maxmem

Page 37: Nginx Workshop Aftermath

Common highload advices

a) tune hardware and OS - disks, NICs, OS limitations (open files, limits, network stack etc.)worker_rlmit_nofile + kern.maxfiles/maxfilesperproc (FreeBSD) + fs.filemax (Linux)

b) tune workers (number / threads). Start from CPU or disks numbers.c) sendfile, tcp_nopush, tcp_nodelay - ?d) timeouts, keepalive, reset_timedout_connection on - checkhttp://calomel.org/nginx.html

Page 38: Nginx Workshop Aftermath

Case 3. Light DDOS fighting

What is "light" DDOS ?1) 1000 - 5000 - 7000 bots max.2) HTTP GET/HEAD/POST, e.g. GET /script.php?<random>

3) "slowpoke" - time of attack vector changing is big.4) "dumb" - dumb behaviour can be detected - no/bad referrers, no redirects, bad/same or missing HTTP headers etc.REMOVE NGINX FROM AUTOSTART !!!!

Page 39: Nginx Workshop Aftermath

a) "Heavy" (e.g. search) scripts flood

http {...limit_req_zone $binary_remote_addr zone=SLOW:10m rate=1r/s;# 64byte per record, 16000 record per MB, 503 error if overflow!... location =/search.php {

limit_req SLOW burst=2;proxy_pass ....

}

Page 40: Nginx Workshop Aftermath

b) "flooders" detection

error_log /var/log/nginx/error.log;limit_conn_zone $binary_remote_addr zone=CONN:10m;...location =/attacked_url {

limit_conn CONN 4; #4-8, but beware of proixes!....

} grep "limiting connections by zone" | grep "/attacked_url" | awk .. - get list of them and add it to firewall (ipset)Beware - you can easily "shoot yourself in the foot"!

Page 41: Nginx Workshop Aftermath

c) Geo limitingCompile geoip module with --with-http_geoip_module first.http {

geo_country /usr/local/nginx/etc/GeoIP.dat;map $geoip_country_code $bad_country {

default 0;include /usr/local/nginx/etc/bad_countries; #

}server {....if ($bad_country) { return 403; }

bad_countries:CN 1;TZ 1;...

Page 42: Nginx Workshop Aftermath

d) Aggresive caching

"Slow is better than dead"location=/ { rewrite ^ main.html last; }# main.html - temporary static page with link to real homelocation=/main.html {

internal;root /var/nginx/cache/;error_page 404 = /cached$uri;

}location /cached/ {

internal;alias /var/nginx/cache/;proxy_pass http://backend;proxy_store_on; proxy_store_temp_path /var/nginx/tmp/;

}

Page 43: Nginx Workshop Aftermath

The ENDPlease check http://wiki.nginx.org - many

nice hings there. :)Questions ?