Home | 简体中文 | 繁体中文 | 杂文 | 打赏(Donations) | 云栖社区 | OSChina 博客 | Facebook | Linkedin | 知乎专栏 | Github | Search | About

46.3. nginx.conf 配置文件

worker_processes = CPU 数量

		user www;
		worker_processes 1;

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

46.3.1. http 配置

自定义缓冲区相关设置

			client_body_buffer_size 1K;
			client_header_buffer_size 1k;
			client_max_body_size 1k;
			large_client_header_buffers 2 1k;
		

超时相关设置

			client_body_timeout 10;
			client_header_timeout 10;
			keepalive_timeout 65;
			send_timeout 10;
		

46.3.2. events

			events {
			worker_connections 4096;
			}
		

46.3.3. gzip

			gzip on;
			gzip_min_length 1000;
			gzip_buffers 4 8k;
			gzip_types text/plain text/css application/json application/x-javascript application/xml;


			gzip on;
			gzip_http_version 1.0;
			gzip_disable "MSIE [1-6].";
			gzip_types text/plain application/x-javascript text/css text/javascript;
		

gzip_types 压缩类型

			gzip_types text/plain text/css application/javascript text/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
		

text/html 是 gzip_types 默认值,所以不要将text/html加入到gzip_types

测试,验证 gzip 正常工作

			neo@netkiller:~/workspace$ curl -s -I -H 'Accept-Encoding: gzip,deflate' http://img.netkiller.cn/js/react.js | grep gzip
			Content-Encoding: gzip
		

如果提示 Content-Encoding: gzip 便是配置正确

不仅仅只能压缩html,js,css还能压缩json

			neo@netkiller:~$ curl -s -I -H 'Accept-Encoding: gzip,deflate' http://inf.netkiller.cn/list/json/2.json
			HTTP/1.1 200 OK
			Server: nginx
			Date: Thu, 15 Dec 2016 03:36:31 GMT
			Content-Type: application/json; charset=utf-8
			Connection: keep-alive
			Cache-Control: max-age=60
			Access-Control-Allow-Origin: *
			Access-Control-Allow-Headers: Content-Type,Origin
			Access-Control-Allow-Methods: GET,OPTIONS
			Content-Encoding: gzip
		

46.3.3.1. CDN支持

配置 gzip_proxied any; 后CDN才能识别 gzip

				server_tokens off;
				gzip on;
				gzip_types text/plain text/css application/javascript text/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
				gzip_proxied any;
			

46.3.4. server_tokens

隐藏nginx版本号

			http {
			...
			server_tokens off;
			...
			}
		

46.3.5. ssi

			http {
			ssi on;
			}

			location / {
			ssi on;
			ssi_silent_errors on;
			ssi_types text/shtml;
			}
		
			ssi on;
			ssi_silent_errors on;
			ssi_types text/shtml;
			ssi_value_length 256;
			server_names_hash_bucket_size 128;
			client_header_buffer_size 32k;
			large_client_header_buffers 4 32k;
			client_max_body_size 8m;
		

ssi_silent_errors 默认值是off,开启后在处理SSI文件出错时不输出错误提示:"[an error occurred while processing the directive] "

ssi_types 默认是ssi_types text/html,如果需要shtml支持,则需要设置:ssi_types text/shtml

ssi_value_length 默认值是 256,用于定义SSI参数的长度。

46.3.6. Nginx 变量

可用的全局变量

$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$http_referer
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri
	

46.3.6.1. $host

抽取域名中的域,例如www.netkiller.cn 返回netkiller.cn

if ($host ~* ^www\.(.*)) {       
    set $domain $1;
    rewrite ^(.*) http://user.$domain permanent;
}
		

提取主机

if ($host ~* ^(.+)\.example\.com$) { 
    set $subdomain $1;
    rewrite ^(.*) http://www.example.com/$subdomain permanent;
}		
		

提取 domain 例如 www.netkiller.cn 提取后 netkiller.cn

只处理二级域名 example.com 不处理三级域名

	if ($host ~* ^([^\.]+)\.([^\.]+)$) {
	   set $domain $1.$2;
	}
		

处理三级域名

		
	set $domain $host;
	if ($host ~* ^([^\.]+)\.([^\.]+)\.([^\.]+)$) {
	    set $domain $2.$3;
	}
		
		

46.3.6.2. http_user_agent

## Block http user agent - wget ##
if ($http_user_agent ~* (Wget|Curl) ) {
   return 403;
}

## Block Software download user agents ##
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
       return 403;
}

if ($http_user_agent ~ (msnbot|scrapbot) ) {
    return 403;
}


if ($http_user_agent ~ (Spider|Robot) ) {
    return 403;
}

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}
		
46.3.6.2.1. 禁止非浏览器访问

禁止非浏览器访问

if ($http_user_agent ~ ^$) {
	return 412;
}
			

测试是否生效

tail -f /var/log/nginx/www.mydomain.com.access.log
			
telnet 192.168.2.10 80
GET /index.html HTTP/1.0
Host: www.mydomain.com
			
46.3.6.2.2. http_user_agent 没有设置不允许访问
	if ($http_user_agent = "") { return 403; }
			

验证测试,首先使用curl -A 指定一个 空的User Agent,应该返回 403.

			
curl -A ""  http://www.example.com/xml/data.json

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
			
			

46.3.6.3. http_referer

if ($http_referer ~* "PHP/5.2.14"){return 403;}
		
46.3.6.3.1. valid_referers/invalid_referer
valid_referers none blocked *.example.com example.com;
if ($invalid_referer) {
	#rewrite ^(.*)$  http://www.example.com/cn/$1;
	return 403;
}
			

46.3.6.4. request_filename

    location / {
        root   /www/mydomain.com/info.mydomain.com;
        index  index.html;

		rewrite ^/$  http://www.mydomain.com/;

		valid_referers none blocked *.mydomain.com;
		if ($invalid_referer) {
			return 403;
		}

        proxy_intercept_errors  on;
	    proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  Host            $host;


        if (!-f $request_filename) {
          proxy_pass http://old.mydomain.com;
          break;
        }
    }
		

46.3.6.5. request_uri

server {
    listen       80;
    server_name  quote.mydomain.com;

    charset utf-8;
    access_log  /var/log/nginx/quote.mydomain.com.access.log  main;

    location / {
        root   /www/mydomain.com/info.mydomain.com;
        index  index.html ;

		rewrite ^/$  http://www.mydomain.com/;

		valid_referers none blocked *.mydomain.com;
		if ($invalid_referer) {
			#rewrite ^(.*)$  http://www.mydomain.com/cn/$1;
			return 403;
		}

        proxy_intercept_errors  on;
	    proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  Host            $host;

		if ( $request_uri ~ "^/xml/(sge|cgse|futures|stock|bonds)\.xml$") {
              proxy_pass http://21.16.22.12/$request_uri;
		break;
        }

        if (!-f $request_filename) {
	          proxy_pass http://cms.mydomain.com;
	          break;
        }

    }

    location ~ \.xml$ {
        proxy_pass http://21.16.22.12/public/datas$request_uri;
        break;
    }

    location ~* ^/public/datas/\w+\.xml$ {
        proxy_pass http://21.16.22.12/$request_uri;
        break;
    }
}
		
#add for yiiframework
        if (!-e $request_filename){
                   rewrite (.*) /index.php break;
        }

        location ~ .*\.php?$
        {
                  #fastcgi_pass  unix:/tmp/php-cgi.sock;
                  include fcgi.conf;
                  fastcgi_pass  127.0.0.1:10080;
                  fastcgi_index index.php;

                  set $path_info $request_uri;

                  if ($request_uri ~ "^(.*)(\?.*)$") {
                        set $path_info $1;
                  }
                  fastcgi_param PATH_INFO $path_info;
        }
#end for yiiframework
		

46.3.6.6. remote_addr

location /name/(match) {
    if ($remote_addr !~ ^10.10.20) {
        limit_rate 10k;
    }

    proxy_buffering off;
    proxy_pass http://10.10.20.1/${1}.html;
}

if ($remote_addr ~* "192.168.0.50|192.168.0.51|192.168.0.56") {
	proxy_pass http://www.netkiller.cn/error;
}
		
location ~ /(\d+) {
    if ($remote_addr ~ (\d+)\.\d+\.) {

    }

    echo $1;
}
		
$ curl 127.0.0.1/134
127

$ curl 192.168.0.1/134
192
		

46.3.6.7. http_cookie

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}
		

46.3.6.8. request_method

location ~* /restful {
	if ($request_method = PUT ) {
	return 403;
	}
	if ($request_method = DELETE ) {
	return 403;
	}
	if ($request_method = POST ) {
	return 403;
	}
	proxy_method GET;
	proxy_pass http://backend;
}		
		
if ($request_method = POST) {
    return 405;
}
		
if ($request_method !~ ^(GET|HEAD|POST)$) {
	return 403;
}
		

46.3.6.9. limit_except

limit_except GET {
	allow 192.168.1.1;
	deny all;
}
		

46.3.6.10. invalid_referer

if ($invalid_referer) {
    return 403;
}
		

46.3.6.11. $request_body - HTTP POST 数据

46.3.6.11.1. 用户日志

将 POST 数据记录到日志中

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" - "$request_body"';
			

注意:用户登录通常使用POST方式,所以记录POST数据到日志会带来安全问题,例如用户密码泄露。

46.3.6.11.2. $request_body 用于缓存

因为nginx 使用 url 作为缓存的key ( Nginx 将url地址 md5后作为缓存的 key ),所以默认情况下 Nginx 只能处理 HTTP GET 缓存。

对于 HTTP POST 请求,提交数据放在HTTP Head 头部提交到服务器的, 提交前后URL始终不变,Nginx 无法区分相同网址两次请求的内容有变化。

但是我们可以自定义 缓存 key 例如: "$request_uri|$request_body" 我们将请求地址加上post内容作为缓存的key,这样nginx 便可以区分每次提交后的页面变化。

 proxy_cache_path /tmp/cache levels=1:2 keys_zone=netkiller:128m inactive=1m;
 
 server {
  listen 8080;
  server_name localhost;

  location / {
   try_files $uri @backend;
  }
 
  location @backend {
   proxy_pass http://node1.netkiller.cn:8080;
   proxy_cache netkiller;
   proxy_cache_methods POST;
   proxy_cache_key "$request_uri|$request_body";
   proxy_buffers 8 32k;
   proxy_buffer_size 64k;
   proxy_cache_valid 5s;
   proxy_cache_use_stale updating;
   add_header X-Cached $upstream_cache_status;
  }
 }
			

46.3.6.12. 自定义变量

if ( $host ~* (.*)\.(.*)\.(.*)) {
	set $subdomain $1;
}
location / {
    root  /www/$subdomain;
    index index.html index.php;
}
		
if ( $host ~* (\b(?!www\b)\w+)\.\w+\.\w+ ) {
    set $subdomain /$1;
}

location / {
    root /www/public_html$subdomain;
    index index.html index.php;
}
		

46.3.6.13. if 条件判断

判断相等

if ($query_string = "") {
   	set $args "";
}
		

正则匹配

if ( $host ~* (.*)\.(.*)\.(.*)) {
	set $subdomain $1;
}
location / {
    root /var/www/$subdomain;
    index index.html index.php;
}
		
		
if ($remote_addr ~ "^(172.16|192.168)" && $http_user_agent ~* "spider") {
    return 403;
}

set $flag 0;
if ($remote_addr ~ "^(172.16|192.168)") {
    set $flag "1";
}
if ($http_user_agent ~* "spider") {
    set $flag "1";
}
if ($flag = "1") {
    return 403;
}
		
		
		
if ($request_method = POST ) {
	return 405;
}
if ($args ~ post=140){
	rewrite ^ http://example.com/ permanent;
}		
		
		
		
location /only-one-if {
    set $true 1;

    if ($true) {
        add_header X-First 1;
    }

    if ($true) {
        add_header X-Second 2;
    }

    return 204;
}