經(jīng)常需要配置Nginx ,其中有許多以 $ 開頭的變量,經(jīng)常需要查閱nginx 所支持的變量。
可能是對(duì) Ngixn資源不熟悉,干脆就直接讀源碼,分析出支持的變量。
Nginx支持的http變量實(shí)現(xiàn)在 ngx_http_variables.c 的 ngx_http_core_variables存儲(chǔ)實(shí)現(xiàn):
ngx_http_core_variables
1 static ngx_http_variable_t ngx_http_core_variables[] = {
2 3 { ngx_string("http_host"), NULL, ngx_http_variable_header, 4 offsetof(ngx_http_request_t, headers_in.host), 0, 0 }, 5 6 { ngx_string("http_user_agent"), NULL, ngx_http_variable_header, 7 offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 }, 8 9 { ngx_string("http_referer"), NULL, ngx_http_variable_header, 10 offsetof(ngx_http_request_t, headers_in.referer), 0, 0 }, 11 12 #if (NGX_HTTP_GZIP) 13 { ngx_string("http_via"), NULL, ngx_http_variable_header, 14 offsetof(ngx_http_request_t, headers_in.via), 0, 0 }, 15 #endif 16 17 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP) 18 { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header, 19 offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 }, 20 #endif 21 22 { ngx_string("http_cookie"), NULL, ngx_http_variable_headers, 23 offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 }, 24 25 { ngx_string("content_length"), NULL, ngx_http_variable_header, 26 offsetof(ngx_http_request_t, headers_in.content_length), 0, 0 }, 27 28 { ngx_string("content_type"), NULL, ngx_http_variable_header, 29 offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 }, 30 31 { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 }, 32 33 { ngx_string("binary_remote_addr"), NULL, 34 ngx_http_variable_binary_remote_addr, 0, 0, 0 }, 35 36 { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 }, 37 38 { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 }, 39 40 { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, 41 42 { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, 43 44 { ngx_string("server_protocol"), NULL, ngx_http_variable_request, 45 offsetof(ngx_http_request_t, http_protocol), 0, 0 }, 46 47 { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 }, 48 49 { ngx_string("request_uri"), NULL, ngx_http_variable_request, 50 offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, 51 52 { ngx_string("uri"), NULL, ngx_http_variable_request, 53 offsetof(ngx_http_request_t, uri), 54 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 55 56 { ngx_string("document_uri"), NULL, ngx_http_variable_request, 57 offsetof(ngx_http_request_t, uri), 58 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 59 60 { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 }, 61 62 { ngx_string("document_root"), NULL, 63 ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, 64 65 { ngx_string("realpath_root"), NULL, 66 ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, 67 68 { ngx_string("query_string"), NULL, ngx_http_variable_request, 69 offsetof(ngx_http_request_t, args), 70 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 71 72 { ngx_string("args"), 73 ngx_http_variable_request_set, 74 ngx_http_variable_request, 75 offsetof(ngx_http_request_t, args), 76 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, 77 78 { ngx_string("is_args"), NULL, ngx_http_variable_is_args, 79 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, 80 81 { ngx_string("request_filename"), NULL, 82 ngx_http_variable_request_filename, 0, 83 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 84 85 { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 }, 86 87 { ngx_string("request_method"), NULL, 88 ngx_http_variable_request_method, 0, 89 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 90 91 { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 }, 92 93 { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent, 94 0, 0, 0 }, 95 96 { ngx_string("request_completion"), NULL, 97 ngx_http_variable_request_completion, 98 0, 0, 0 }, 99 100 { ngx_string("request_body"), NULL, 101 ngx_http_variable_request_body, 102 0, 0, 0 }, 103 104 { ngx_string("request_body_file"), NULL, 105 ngx_http_variable_request_body_file, 106 0, 0, 0 }, 107 108 { ngx_string("sent_http_content_type"), NULL, 109 ngx_http_variable_sent_content_type, 0, 0, 0 }, 110 111 { ngx_string("sent_http_content_length"), NULL, 112 ngx_http_variable_sent_content_length, 0, 0, 0 }, 113 114 { ngx_string("sent_http_location"), NULL, 115 ngx_http_variable_sent_location, 0, 0, 0 }, 116 117 { ngx_string("sent_http_last_modified"), NULL, 118 ngx_http_variable_sent_last_modified, 0, 0, 0 }, 119 120 { ngx_string("sent_http_connection"), NULL, 121 ngx_http_variable_sent_connection, 0, 0, 0 }, 122 123 { ngx_string("sent_http_keep_alive"), NULL, 124 ngx_http_variable_sent_keep_alive, 0, 0, 0 }, 125 126 { ngx_string("sent_http_transfer_encoding"), NULL, 127 ngx_http_variable_sent_transfer_encoding, 0, 0, 0 }, 128 129 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers, 130 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 }, 131 132 { ngx_string("limit_rate"), ngx_http_variable_request_set_size, 133 ngx_http_variable_request_get_size, 134 offsetof(ngx_http_request_t, limit_rate), 135 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, 136 137 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 138 0, 0, 0 }, 139 140 { ngx_string("hostname"), NULL, ngx_http_variable_hostname, 141 0, 0, 0 }, 142 143 { ngx_string("pid"), NULL, ngx_http_variable_pid, 144 0, 0, 0 }, 145 146 { ngx_null_string, NULL, NULL, 0, 0, 0 } 147 };
把這些變量提取下,總結(jié)如下:
nginx防DDOS攻擊的簡單配置
nginx本身就有防DDOS攻擊這方面的模塊ngx_http_limit_req_module和ngx_http_limit_conn_module。
一、基本介紹
1.ngx_http_limit_req_module
配置格式及說明:
設(shè)置一個(gè)緩存區(qū)保存不同key的狀態(tài),這里的狀態(tài)是指當(dāng)前的過量請(qǐng)求數(shù)。而key是由variable指定的,是一個(gè)非空的變量,我們這里使用$binary_remote_addr,表示源IP為key值。
limit_req_zone $variable zone=name:size rate=rate;
指定要進(jìn)行限制的緩存區(qū)和最大的請(qǐng)求到達(dá)后有多少個(gè)請(qǐng)求放入延遲隊(duì)列(其它的直接丟棄)。如果不希望請(qǐng)求數(shù)達(dá)到上限而被延遲,就需要使用nodelay。
limit_req zone=name [burst=number] [nodelay];
例子:
緩存區(qū)為10M,請(qǐng)求限制為每秒1次,延遲隊(duì)列為5
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; ... server { ... location /search/ { limit_req zone=one burst=5; } }
2.ngx_http_limit_conn_module
配置格式及說明:
設(shè)置一個(gè)緩存區(qū)保存不同key的狀態(tài)。我們這里使用源IP來作為key,以此限制每個(gè)源IP的鏈接數(shù)
limit_conn_zone $binary_remote_addr zone=addr:10m;
指定限制的緩存區(qū),并指定每個(gè)key的鏈接個(gè)數(shù)
limit_conn zone number;
例子:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m; ... server { ... location /download/ { limit_conn addr 1; } }
二、實(shí)際應(yīng)用
如果作為代理服務(wù)器,我們需要限制每個(gè)用戶的請(qǐng)求速度和鏈接數(shù)量,但是,由于一個(gè)頁面有多個(gè)子資源,如果毫無選擇的都進(jìn)行限制,那就會(huì)出現(xiàn)很多不必要的麻煩,如:一個(gè)頁面有40個(gè)子資源,那么如果想讓一個(gè)頁面完整的顯示,就需要將請(qǐng)求速度和連接數(shù)都調(diào)整到40,以此達(dá)到不阻塞用戶正常請(qǐng)求,而這個(gè)限制,對(duì)服務(wù)器性能影響很大,幾百用戶就能把一臺(tái)nginx的處理性能拉下來。
所以我們需要制定哪些請(qǐng)求是需要進(jìn)行限制的,如html頁面;哪些是不需要限制的,如css、js、圖片等,這樣就需要通過配置對(duì)應(yīng)的location進(jìn)一步細(xì)化。
我們不對(duì)css、js、gif、png,jpg等進(jìn)行連接限制,而對(duì)除此之外的鏈接進(jìn)行限制
http {
limit_conn_zone $binary_remote_addr zone=addr:10m; limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; ... server { ... location ~ .*\.(gif|png|css|js|icon)$ { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* .*\.(jpeg|jpg|JPG)$ { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # image_filter resize 480 -; # image_filter_jpeg_quality 50; # image_filter_sharpen 10; # image_filter_buffer 4M; } location / { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #limit limit_conn addr 3; limit_req zone=one burst=5; } }
Location配置簡單介紹:
語法規(guī)則: location [=|~|~*|^~] /uri/ { … }
= 開頭表示精確匹配
^~ 開頭表示uri以某個(gè)常規(guī)字符串開頭,理解為匹配 url路徑即可。nginx不對(duì)url做編碼,因此請(qǐng)求為/static/20%/aa,可以被規(guī)則^~ /static/ /aa匹配到(注意是空格)。
~ 開頭表示區(qū)分大小寫的正則匹配
~* 開頭表示不區(qū)分大小寫的正則匹配
!~和!~*分別為區(qū)分大小寫不匹配及不區(qū)分大小寫不匹配 的正則
/ 通用匹配,任何請(qǐng)求都會(huì)匹配到。
多個(gè)location配置的情況下匹配順序?yàn)椋▍⒖假Y料而來,還未實(shí)際驗(yàn)證,試試就知道了,不必拘泥,僅供參考):
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最后是交給 / 通用匹配。當(dāng)有匹配成功時(shí)候,停止匹配,按當(dāng)前匹配規(guī)則處理請(qǐng)求。
例子,有如下匹配規(guī)則:
location = / {
#規(guī)則A
}
location = /login {
#規(guī)則B
}
location ^~ /static/ {
#規(guī)則C
}
location ~ \.(gif|jpg|png|js|css)$ {
#規(guī)則D
}
location ~* \.png$ {
#規(guī)則E
}
location !~ \.xhtml$ {
#規(guī)則F
}
location !~* \.xhtml$ {
#規(guī)則G
}
location / {
#規(guī)則H
}
那么產(chǎn)生的效果如下:
訪問根目錄/, 比如http://localhost/ 將匹配規(guī)則A
訪問 http://localhost/login 將匹配規(guī)則B,http://localhost/register 則匹配規(guī)則H
訪問 http://localhost/static/a.html 將匹配規(guī)則C
訪問 http://localhost/a.gif, http://localhost/b.jpg 將匹配規(guī)則D和規(guī)則E,但是規(guī)則D順序優(yōu)先,規(guī)則E不起作用, 而 http://localhost/static/c.png 則優(yōu)先匹配到 規(guī)則C
訪問 http://localhost/a.PNG 則匹配規(guī)則E, 而不會(huì)匹配規(guī)則D,因?yàn)橐?guī)則E不區(qū)分大小寫。
訪問 http://localhost/a.xhtml 不會(huì)匹配規(guī)則F和規(guī)則G,http://localhost/a.XHTML不會(huì)匹配規(guī)則G,因?yàn)椴粎^(qū)分大小寫。規(guī)則F,規(guī)則G屬于排除法,符合匹配規(guī)則但是不會(huì)匹配到,所以想想看實(shí)際應(yīng)用中哪里會(huì)用到。
訪問 http://localhost/category/id/1111 則最終匹配到規(guī)則H,因?yàn)橐陨弦?guī)則都不匹配,這個(gè)時(shí)候應(yīng)該是nginx轉(zhuǎn)發(fā)請(qǐng)求給后端應(yīng)用服務(wù)器,比如FastCGI(php),tomcat(jsp),nginx作為方向代理服務(wù)器存在。
補(bǔ)nginx內(nèi)置變量.xls:http://pan.baidu.com/share/link?shareid=476245&uk=85241834