# Nginx配置

使用服务器配置nginx肯定是在所难免,下面是nginx配置的入门

# 基本配置

参考资料:

Nginx的配置文件是由全局块+events块+http块组成。

# 全局块

从配置文件开始到events之间的内容,主要会设置一些影响Nginx服务器整体运行的配置指令,主要包括配置运行Nginx服务器的用户(组)、允许生成的worker process数,进程pid存放路径、日志存放路径和类型以及配置文件的引入等。

worker_processes是Nginx服务器并发处理服务的关键配置,该值越大,支持的并发处理量越多,但是会受到硬件软件等设备的制约。

# events块

events块设计的指令主要影响Nginx服务器与用户的网络连接,常用的设置包括是否开启对多work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个work process可以同时支持的最大连接数等。下面的例子表示每个work process支持的最大连接数为1024。这部分配置对Nginx的性能影响较大,在实际中应该灵活配置。比如:

events {
   worker_connections 1024;
}
1
2
3

# http块

Nginx服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里,http块又包括:

  • http全局块:http全局块配置的指令包括文件引入、MIME-TYPE定义、日志自定义、连接超时时间、单链接请求数上限等。
  • server块:这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机。每个server块也可以分为全局server块,以及可以同时包含多个location块。
    • 全局server块:最常见的配置是本虚拟主机的监听配置和本虚拟主机的名称或IP配置。
    • location块:一个server块可以配置多个location块。这块的主要作用是基于Nginx服务器接收到的请求字符串(例如server_name/uri-string),对虚拟主机名称(也可以是IP别名)之外的字符串(例如前面的/uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

# location配置

location的基本用法如下:

location [=|~|~*|^~] /uri/ {}
1
2
3

匹配模式分为两种:

  • 普通字符串匹配:以=开头或开头无引导字符(~)的规则
  • 正则匹配:以~或~*开头表示正则匹配

前面中括号中的符号含义为:

  • = :严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。
  • ^~:开头以某个常规字符匹配字符串,匹配后不再进行正则匹配,比=优先级低。
  • ~ :区分大小写匹配
  • !~:区分大小写不匹配
  • ~*:不区分大小写匹配
  • !~*:不区分大小写不匹配

他们的优先级如下:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

下面是它的一些案例:

location = / {
 # 只匹配 / 查询。
}
location / {
 # 匹配任何查询,因为所有请求都以 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配。
}
location ^~ /images/ {
 # 匹配任何以 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
}
location ~*.(gif|jpg|jpeg)$ {
 # 匹配任何以 gif、jpg 或 jpeg 结尾的请求。
}
location ~* ^.+\.(jpg|jpeg|gif|png|bmp|css|js|swf|txt|html)$ {
   root /home/public/; 
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# php相关

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    fastcgi_pass php-fpm:9000;
    fastcgi_index  index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /home/WebRoot/phpFrame/controller/$fastcgi_script_name;
    fastcgi_param  PATH_INFO       $fastcgi_path_info;
    #fastcgi_param TOKENID $http_tokenid;
    #fastcgi_pass unix:/var/run/php5-fpm.sock;
    #try_files $uri =404;
}  
1
2
3
4
5
6
7
8
9
10
11
  1. fastcgi_split_path_info有三种写法:

    # 第一种,非贪婪匹配,比如fagh.php.php/test只会匹配到fagh.php
    fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
    
    # 第二种,非贪婪匹配
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    
    # 第三种,贪婪匹配
    fastcgi_split_path_info  ^(.+\.php)(/.*)$;
    
    1
    2
    3
    4
    5
    6
    7
    8

    这两个匹配的组,第一个组匹配的值会给$fastcgi_script_name变量,第二组匹配的值会给$fastcgi_path_info变量。

  2. fastcgi配置

    # 配置fastcgi服务器的地址
    fastcgi_pass php-fpm:9000;
    # 配置默认主页,当找不到url时就使用该主页。
    fastcgi_index  index.php;
    
    1
    2
    3
    4
  3. fastcgi_param配置

    fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
    
    # SCRIPT_FILENAME变量是php-fpm可识别的脚本名称,后面的路径则定义了对应脚本的路径
    fastcgi_param SCRIPT_FILENAME /home/WebRoot/phpFrame/controller/$fastcgi_script_name;
    
    # 需要将cgi.fix_pathinfo设置为0
    fastcgi_param  PATH_INFO       $fastcgi_path_info;
    
    1
    2
    3
    4
    5
    6
    7

    上面是使用fastcgi_split_path_info,对uri进行处理,分析出真实脚本文件和PATH_INFO,并设置两个重要变量$fastcgi_script_name和$fastcgi_path_info,下面的方法,会出现安全隐患,不推荐使用:

    # 需要把cgi.fix_pathinfo设置为1
    fastcgi_param PATH_INFO $fastcgi_script_name;
    
    1
    2

# 小场景

# 防盗链

HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是用它能够限制大部分的盗链。

valid_referers的语法如下:

valid_referers [none|blocked|server_names] ...

该指令会根据Referer Header头的内容分配一个值为0或1给变量$invalid_referer。如果Referer Header头不符合valid_referers指令设置的有效Referer,变量$invalid_referer将被设置为1。也就是给Referer Header设置白名单。

该指令的参数如下:

  • none:表示无Referer值的情况。
  • blocked:表示Referer值被防火墙或者是代理给去除了。
  • server_names:表示一个或多个主机名称。从Nginx 0.5.33版本开始,server_names中可以使用通配符"*"号。
location ~*.(gif|jpg|swf)$ {
  valid_referers none blocked start.igrow.cn sta.igrow.cn;
  if ($invalid_referer) {
    #防盗链
    rewrite ^/ http://$host/logo.png;
  }
}
1
2
3
4
5
6
7

# nginx只允许域名访问

一般是用于反向代理隐藏一些东西,有两种方法:

  • 判断源域名:

    server {
       listen 8081;
       server_name  www.test.com;
       if ( $host != 'www.test.com' ){
          return 403;
       }
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 配置默认域名:

    server {
       listen 8081;
       server_name  www.test.com;
    }
    server {
       listen 8081 default_server;
       server_name  _;
       return 403;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 正则表达式

nginx的规则离不开正则表达式,而正则表示式是由普通字符和元字符(metacharacters)组成。普通字符则是字母和数字,元字符则是用一些特殊字符来代表不同含义。

# 元字符

元字符 描述
\ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^ 匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$ 匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。
+ 匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
.点 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
(pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(
(?=pattern) 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95
(?!pattern) 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95
(?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95
(?<!patte_n) 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95
x|y 匹配x或y。例如,“z
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d 匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
\D 匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。
\num 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml 如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。
<和> 匹配词(word)的开始(<)和结束(>)。例如正则表达式<the>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
( ) 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
| 将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him

# 特殊元字符

注意,还有一个特殊的是 \p{P},前面小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。此语法部分语言不支持比如javascript。中括号内的“P”表示Unicode 字符集七个字符属性之一:标点字符。其他六个属性:

  • L:字母;
  • M:标记符号(一般不会单独出现)
  • Z:分隔符(比如空格、换行等)
  • S:符号(比如数学符号、货币符号等)
  • N:数字(比如阿拉伯数字、罗马数字等)
  • C:其他字符。