天天看点

Nginx——访问控制

访问控制

访问控制是网络安全防范和保护的主要策略,其任务是保证网络资源不被非法访问。Nginx作为Web服务器的后起之秀,也提供了访问控制的功能。它可以根据实际需求,对用户可以访问和禁止的目录进行限制。下面将对Nginx提供的权限控制指令以及典型的应用进行详细讲解。

权限控制指令

Nginx中提供了两个用于配置访问权限控制的指令,分别为

allow和deny

。从其名称就可以看出,allow用于设置允许访问的权限deny用于设置禁止访问的权限。在使用时,权限指令后只需跟上允许或禁止的IP、IP段或all即可。其中,all表示所有的。

权限控制指令的使用虽然简单,但是在设置的过程中,还需要特别注意以下几个点。

  • 单个IP指定作用范围最小,all指定作用范围最大。
  • 同一块下,若同时存在多个权限指令(deny、allow),则先出现的访问权限设置生效,并且会对后出现的设置进行覆盖,未覆盖的范围依然生效,否则以先出现的设置用古好为准。
  • 当多个块(如http、server、location)中都出现了权限设置指令,则内层块中的权限级别要比外层块中设置的权限级别高。

1. 禁止所有用户访问:

Nginx——访问控制
Nginx——访问控制

需要注意的是,在server块下设置deny all后,服务器内的客户端软件在访问自己时也会出现403Forbidden。因此,在设置时需要慎重考虑。

2. 只允许指定用户访问:

allow 192.158.78.128
deny all;
           

上述指令表示只允许192.168.78.128客户端访问,其他所有客户端都不能访问。利用之前准备的两个客户端可以进行测试。需要注意的是,若省略此处的denyall,则会允许所有客户端访问;若将deny all 移动到allow 192. 168. 78. 128之后,则会阻止所有客户端.访问。

从上述规律看出,同一个块下的两个权限指令,先出现的设置会覆盖后出现的设置,使得allow 192. 168. 78. 128的配置优先生效;同时deny指令设置的访问范围all 较大,未被allow覆盖的范围配置依然生效,达到除了IP为192. 168. 78. 128的用户外,禁止其他用户对服务器访问的效果。

3. 不同块间的全下指令优先级:

http{
	...
	deny all;
	server{
		listen 80;
		server_name localhost;
		root html;
		index index.tml index.html;
	}
}
           

此时,会禁止所有用户对http块的访问。

在server块中加入

allow all;

http{
	...
	deny all;
	server{
		listen 80;
		server_name localhost;
		root html;
		index index.tml index.html;
		allow all;
	}
}
           

修改后,所有用户都可以访问server块。这是由于Nginx配置文件中的各个块在嵌套的情况下,内层块内的指令比外层块内的指令执行优先级高。因此,当内外层块中同时出现权限指令时,则内层块中的allow all 会覆盖外层块中的deny all 的设置。

访问控制典型应用

在实际应用中,权限控制的需求更加复杂。例如,对于网站下的img目录允许所有用户访问,但对于网站下的admin目录则仅允许管理员身份的用户访问。此时,仅靠deny和allow这两个权限指令不能满足用户的需求,还需要使用location块来完成相关需求的匹配。

在此之前,首先要简单了解一下location 的相关语法及规定,具体如下:

#语法类型1
location [= | ~ | ~ * | ^~] URI {...}

#语法类型2
location @name {...}
           

在上述语法中,

=、~、~ *、^~和@

都是location 用于实现访问控制的前缀,且在使用时只能选择一种,当然也可以不设置前缀。其中,关于location前缀的含义如下图所示。

URI

表示URL地址中从域名到参数之间的部分,

{ ... }

表示指令块,用于满足location 匹配条件后需要执行的指令。

Nginx——访问控制

1. 精准匹配:

所谓精准匹配指的就是用户访问的URI与指定的URI完全一致的情况,才会执行其后的指令块,示例配置如下:

server{
	listen 80;
	server_name localhost;
	root html;
	index index.html index.htm;
	location =/js{     ###6
		allow 192.168.78.128;
	}
	location =/admin/auth {   ###9
		allow 192.168.78.200;
	}
	deny all;
}
           

的上述第

6~8行和第9~11

行配置设置了两个精准匹配,第12行用于禁止所有用户的访问。当上述配置中允许访问的两个客户端,请求网站根目录下不存在的文件或目录时,如果符合匹配规则,网页显示404NotFound,不符合时显示403Forbidden。

假设网站根目录下没有任何文件,下面使用IP为192. 168. 78.128的A用户和IP为192. 168. 78. 200的B用户通过不同的URL进行访问测试,其对应的响应结果如下所示。

Nginx——访问控制

精准匹配是只有用户请求的URI与location中定义的匹配模式完全一致的情况下,才会执行其后的指令块,否则匹配不成功。

2. 正则匹配:

Nginx配置文件中,多个正则location之间按照正则location在配置文件中的书写顺序进行匹配,且只要匹配成功就不会继续匹配后面定义的正则location。下面在IP为192.168.78.3的虚拟机中,设置以下两个正则location访问控制,具体如下:

location ~\.html$ {
	allow all;
}
location ~^/aaa/.*\.html$ {
	deny all;
}
           

在上述配置中,第1行表示匹配网站根目录下以.html结尾的文件,第4行表示匹配网站根目录下aaa目录中以.html结尾的文件。

下面使用IP为192.168.78.128的用户通过不同的URL进行访问测试,其对应的响应结果如下:

Nginx——访问控制

当location中的URI与用户请求中以

.html

为结尾的文件匹配上时,正则location停止了继续匹配,因此显示结果都为404NotFound。

接下来,

调换第1~3行与第4~6行代码的编写顺序

,再次访问http://192.168.78.3/test. html结果依然为404 Not Found,而访问http://192. 168. 78. 3/aaa/test. html的结果为403 Forbidden。

从上述两组测试对比可总结出,

正则location的编写顺序不同,则结果不同,且只有前面定义的正则location匹配不成功的情况下,才会继续匹配后面的正则location

。因此,读者在实际应用中要注意正则location在配置文件中的书写顺序。

3. 最大前缀匹配:

由于location可以同时定义多个,当一个配置文件中同时出现多个location 时,普通location之间遵循“最大前缀匹配"原则。通俗地讲就是,匹配度最高的location将会执行,示例如下:

location /ng.test {
	allow all;
}
location /ng.test/log {
	deny all;
}
           
Nginx——访问控制

注意:

当最大前缀location与正则location同时存在时,如果正则location匹配成功,则不会执行最大前缀location。具体示例如下。

location / {
	deny all;
}
location ~\.html$ {
	allow all;
}
           
Nginx——访问控制

location / {}

location =/ {}

的区别:

location/ {}遵守普通location 的最大前缀匹配,由于任何URI都必然以“/”根开头,所以对于一个URI ,若配置文件中有更合适的匹配则会将其替代,否则返回location/ {}匹配到的结果,它相当于站点默认配置。

而location=/ {}遵守的是精准匹配,也就是只能匹配该站点根目录,同时会禁止继续搜索正则location,效率比location/ {}要高。因此,若在开发中能确定精准匹配的情况,可以采用location =/ {}的方式,提升匹配效率。

4. 禁用正则匹配:

利用=精准匹配或^~非正则匹配可以在正则匹配之前优先匹配,从而禁止执行原有的正则匹配。下面在server块中添加以下几条location匹配规则,具体如下:

location =/aaa/test.html {
	allow all;
}
location ^~/ {
	deny all;
}
location ~\.html$ {
	allow all;
}
           
Nginx——访问控制

在上述配置中,第1行仅用于精准匹配网站根目录下的1aaa/test.html,第4行用于非.正则匹配网站根目录下的文件,第7行用于正则匹配网站根目录下以. html为结尾的文件。

接下来通过不同URL进行访问测试,具体如上表所示。从表中的响应结果可以看出,在使用了“=”或“^~”前缀时,普通location匹配后将不再执行正则location的匹配。

值得一提的是,

前缀“一”和“^~”虽然都能阻止继续搜索正则location,不同的地方是它们遵循的规则不同,“^~”依然遵循最大前缀匹配规则,而=则严格按照精准匹配执行

。亦i因此,当多种类型的location匹配同时出现时,最终执行结果为“=”匹配优先于

“^~”

匹配,

“^~”

匹配优先于正则匹配,正则匹配优先于普通的最大前缀匹配。只要优先的location匹配成功,就不会执行其他的location。

root 与 alias的区别:

在location中指定目录时,除了可以使用root 指令外,还可以使用alias 指令完成。两者在使用时有一定的区别,具体示例如下:

#当收到"/img/ithemima.png"请求时,将请求映射为"/var/www/image/itheima.png"
location /img/ {
	alias /var/www/image/;
}

#当收到"/img/ithemima.png"请求时,将请求映射为"/var/www/image/img/itheima.png"
location /img/ {
	root /var/www/image;
}
           

从上述示例可以看出,alias在映射路径时不会追加location 匹配到的部分,而root 追加了location匹配到的部分。

继续阅读