本文梳理了Nginx在做反向代理时常用的核心配置,所有细节可以参考官网Nginx官网 ,我这里主要起到穿针引线的作用。
本文主要涉及了如下模块: ngx_http_core_module ngx_htpp_access_module ngx_http_geo_module ngx_http_map_module ngx_http_index_module ngx_http_log_module ngx_http_perl_module ngx_http_rewrite_module ngx_http_ssi_module ngx_http_ssl_module ngx_http_upstream_module ngx_http_proxy_module ngx_http_limit_conn_module ngx_http_limit_req_module ngx_stream_core_module ngx_stream_proxy_module ngx_upstream_module 第三方模块如下: redis2-nginx-module redis-nginx-module srcache-nginx-module nginx-upsync-module
一、跳转 利用ngx_http_core_module、ngx_http_rewrite_module模块 主要是301跳转 Return写法:域名http请求跳转到对应的https请求
1 2 3 4 5 6 7 8 9 10 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location / { return 301 https://$host$request_uri; } access_log /data/wwwlogs/access_www.test.com.log access; }
Rewrite写法:rewrite写法比较灵活可以调整路径,但没有return高效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location ~* ^/(meinv|huodong|zhuanti)/(.*)$ { rewrite ^/(meinv|huodong|zhuanti)/(.*)$ http://oldwww.test.com/$1/$2 permanent; } location / { proxy_pass http://www_test_com; } access_log /data/wwwlogs/access_www.test.com.log access; } upstream www_test_com { server 192.168.88.188:80; server 192.168.88.189:80; }
二、重写代理 利用ngx_http_proxy_module、ngx_http_upstream_module模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location ~* /api/ { rewrite /api/(.*)$ /api/$1 break; proxy_set_header Host apiwww.test.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X_FORWARDED_FOR $proxy_add_x_forwarded_for; proxy_set_header VIA 111.111.111.111; proxy_pass http://www_test_com_api; } access_log /data/wwwlogs/access_www.test.com.log access; } upstream www_test_com_api { server 192.168.88.188:80; server 192.168.88.189:80; }
三、限速限连接 利用ngx_http_limit_conn_module、ngx_http_limit_req_module模块 首先http区域里面定义好限速限制连接数策略,再在线上具体域名上使用 Http区域配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 map $http_x_forwarded_for $clientRealIpnormal { "" $remote_addr; ~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr; } map $http_http_cdn_src_ip $clientRealIp{ "" $clientRealIpnormal; default $http_http_cdn_src_ip; } geo $clientRealIp $white_ip { default 1; include geo.conf; } map $white_ip $limited { 1 $clientRealIp; 0 ""; } limit_req_status 418; limit_conn_status 418; limit_conn_zone $limited zone=addr:200m; limit_req_zone $limited zone=zero1:20m rate=1r/s; limit_req_zone $limited zone=zero2:20m rate=2r/s; limit_req_zone $limited zone=zero:20m rate=3r/s; limit_req_zone $limited zone=one:20m rate=10r/s; limit_req_zone $limited zone=two:20m rate=20r/s; limit_req_log_level info; limit_conn_log_level info;
线上域名开启配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location / { limit_req zone=two burst=5 nodelay; limit_conn addr 20; proxy_pass http://www_test_com; } access_log /data/wwwlogs/access_www.test.com.log access; } upstream www_test_com { server 192.168.88.188:80; server 192.168.88.189:80; }
四、屏蔽IP 1、方法一 使用ngx_http_access_module模块allow、deny控制,缺点是通过remote_addr来屏蔽IP的,优点是支持CIDR等格式地址
1 2 3 allow 111.111.111.111; allow 192.168.88.0/24; deny all;
2、方法二 用于自定义客户端IP变量$clientRealIp来屏蔽,缺点IP需要写成正则形式的,优点是支持IP穿透,过CDN的域名这种方法才能生效
1 2 3 4 if ($clientRealIp ~ "(183.60.189.195|182.10.18.135)") { return 403; }
3、方法三 自定义屏蔽IP,结合Elasticsearch查询异常IP可自动化屏蔽IP
1 2 3 4 set $clientipfileurl "/usr/local/nginx/html/blockip/$host/$clientRealIp"; if ( -f $clientipfileurl) { return 403 "Your IP address $clientRealIp is too frequent, please try again later or contact the webmaster, thank you!"; }
五、屏蔽URL 1、方法一 自动屏蔽,结合Elasticsearch查询异常URL,可自动化屏蔽URL
1 2 3 4 set $fileurl "/usr/local/nginx/html/blockurl/$host/$uri"; if ( -f $fileurl) { return 403 "This url $host$uri is too frequent, please try again later or contact the webmaster, thank you!"; }
2、方法二 手动屏蔽,当某个目录或者URL影响到全站访问时可以手动屏蔽
1 2 3 location ~* ^/mbw/xoxo/123456789/ { return 403; }
六、SSI包含 利用ngx_http_ssi_module模块 开启ssi后,include与ushtml代理到ssi服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; ssi on; ssi_silent_errors off; ssi_types text/shtml; location ~* ^/(include|ushtml) { proxy_pass http://www_test_com_include; } location / { proxy_pass http://www_test_com; } access_log /data/wwwlogs/access_www.test.com.log access; } upstream www_test_com { server 192.168.88.188:80; server 192.168.88.189:80; } upstream www_test_com_include { server 192.168.88.11:80; server 192.168.88.12:80; }
七、Srcache配置 该架构是给论坛做帖子缓存的,注意只能缓存帖子,目录不能缓存是openresty +srcache+reids2-nginx-module组成:入口是openresty,缓存是codis集群,上游服务器是iis源站 其中http区域配置为删除过期key,更新key的作用,由新第维护lua脚本,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 http { server { listen 80; server_name www.test.com; allow 192.168.88.0/24; allow 192.168.188.0/24; deny all; location ~ /delkey/(.*) { internal; set $redis_key $1; redis2_query del $redis_key; redis2_pass redis_server; } } include proxy.conf; include vhosts_all/*.conf; }
具体源站配置,放在vhost下,目前只有www.test.com域名,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 upstream www_test_com { server 192.168.88.188:80; server 192.168.88.189:80; } server { listen 80; server_name www.test.com; more_clear_headers "X-AspNet-Version"; more_clear_headers "X-Powered-By"; location / { default_type text/html; srcache_methods GET; srcache_response_cache_control on; srcache_store_statuses 200; srcache_store_max_size 1024000; set $key $host$uri; set_escape_uri $escaped_key $key; srcache_fetch GET /redis_get $key; srcache_default_expire 0; srcache_max_expire 1h; srcache_store PUT /redis_set key=$escaped_key&exptime=$srcache_expire; add_header X-Cached-From $srcache_fetch_status; add_header X-Cached-Store $srcache_store_status; add_header X-Key $key; add_header X-Query_String $query_string; add_header X-expire $srcache_expire; access_log /data/wwwlogs/access_www.test.com-redis.log srcache_log; proxy_pass http://www_test_com; } location = /redis_get { internal; set $redis_key $args; redis_pass redis_server; } location = /redis_set { internal; set_unescape_uri $exptime $arg_exptime; set_unescape_uri $key $arg_key; redis2_query set $key $echo_request_body; redis2_query expire $key $exptime; redis2_pass redis_server; } }
八、Upsync配置 该项目是动态上下负载,架构为nginx+nginx-upsync-module+consul,配置文件只需要对具体域名进行修改,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location / { proxy_pass http://www_test_com; } location = /upstream_show { upstream_show; } access_log /data/wwwlogs/access_www.test.com.log access; } upstream www_test_com { upsync 192.168.88.58:8500/v1/kv/upstreams/www.test.com/ upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off; upsync_dump_path /usr/local/nginx/conf/servers/dump_www.test.com.conf; include /usr/local/nginx/conf/servers/include_www.test.com.conf; }
九、Websock配置 Websock协议为ws,如果还需要添加ssl支持,协议为https正常添加证书就行,websock支持长连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 server { listen 80; server_name www.test.com; index index.html index.htm index.shtml; location / { proxy_pass http://www_test_com; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_read_timeout 28800; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream www_test_com { server 192.168.88.188:80; server 192.168.88.189:80; }
十、其他 1、只允许POST请求 1 2 3 4 5 6 7 location ~* /hd/api/prizehandler.ashx { if ($request_method = GET ) { return 403; } proxy_method POST; proxy_pass http://apiwww_test_com; }
2、禁止Agent 1 2 3 4 if ($http_user_agent ~* "(python-requests|Java/1.8.0_40|Java/1.0.0_07|Java/1.7.0_67|Mac OS X 10_7_5|Iceweasel|curl|spider|ChinaCache)") { return 403; }
3、设置过期时间 1 2 3 4 5 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ { expires 30d; proxy_pass http://image_test_com; }
4、设置权限 1 2 3 4 location / { auth_basic "Please input Username and Password"; auth_basic_user_file /usr/local/nginx/conf/.pass_file; }
5、rewrite忽略大小写 1 rewrite (?i)^/newsimg_(\d+)x(\d+)/(.*)$ /videoimgnew.php?w=$1&h=$2&dir=$3 break;
6、404冗余 方法一 通过$request_filename判断
1 2 3 4 if ( !-f $request_filename ){ proxy_pass http://image_test_com; break; }
方法二 if判断效率比较低,可以使用try_files
1 2 3 4 5 6 location / { try_files $uri @backend; } location @backend { proxy_pass http://image_test_com; }
方法三 通过error_page功能
1 2 3 4 5 6 7 location / { error_page 404 500 = @fallback; proxy_pass http://image_test_com; } location @fallback { proxy_pass http://imagebak_test_com; }
7、url大小写转换 http区域配置如下
1 2 3 4 5 6 perl_set $url ' sub { my $r = shift; my $re = lc($r->uri); return $re; } ';
域名server区域配置如下
1 2 3 4 if ($uri ~ [A-Z]) { rewrite ^(.*)$ $url last; }
8、支持跨域 字体支持所有域名跨域调用,某些客户端可能支持的不太友好
1 2 3 4 location ~* /topics/iconfont/ { add_header Access-Control-Allow-Origin *; }
9、SSL支持 该域名配置同时支持http与https,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server { listen 80; listen 443; server_name www.test.com; index index.html index.htm index.shtml; ssl on; ssl_certificate globalsignssl/server.cer; ssl_certificate_key globalsignssl/server.key; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_protocols TLSv1.2 TLSv1.1 TLSv1; ssl_session_cache shared:SSL:10m; ssl_session_timeout 60m; location / { proxy_pass http://www_test_com; } }
10、tcp负载 需要开启stream模块,如果要支持ssl,需要开启stream_ssl模块 http区域配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 user www www; worker_processes auto; worker_cpu_affinity auto; error_log logs/error.log error; pid logs/nginx.pid; worker_rlimit_nofile 409600; events { use epoll; worker_connections 409600; } stream { log_format basic '$remote_addr [$time_local] ' '$protocol $status $bytes_sent $bytes_received ' '$session_time'; log_format proxy '$remote_addr [$time_local] ' '$protocol $status $bytes_sent $bytes_received ' '$session_time "$upstream_addr" ' '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"'; include tcpupstream/*.conf; }
tcp负载配置如下:
1 2 3 4 5 6 7 8 9 10 11 upstream test_12306 { server 192.168.88.21:12306; server 192.168.88.22:12306; } server { listen 12306; proxy_connect_timeout 10s; proxy_timeout 30s; proxy_pass test_12306; access_log /data/wwwlogs/access_test12306.log proxy; }