Nginx 之访问控制详解

1. 访问控制

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

1.1 权限控制指令

  • Nginx 中提供了两个用于配置访问权限控制的指令,分别为 allowdeny。 从其名称就可以看出, allow 用于设置允许访问的权限、 deny 用于设置禁止访问的权限 。 在使用时, 权限指令后只需跟上允许或禁止的 IP、IP 段或 all 即可 。 其中,all 表示所有的 。
  • 权限控制指令的使用虽然简单,但是在设置的过程中,还需要特别注意以下几个点。
  1. 单个 IP 指定作用范围最小, all 指定作用范围最大。
  2. 同一块下,若同时存在多个权限指令(deny、allow) ,则先出现的访问权限设置生效, 并且会对后出现的设置进行破盖,未覆盖的范围依然生效,否则以先出现的设置为准。 ·
  3. 当多个块(如 http、server、 location)中都出现了权限设置指令,则内层块中的权限级别要比外层块中设置的权限级别高 。
  • 为了读者更好地理解权限控制指令,下面对几种常用使用方式分别演示说明 。

1. 准备工作

  • 由于权限的控制测试,需要涉及不同的 IP。 因此,在具体讲解前,准备多台虚拟机, 一 台作为 Nginx 服务器,如 192. 168. 78. 3 。另外几台作为客户端,如 192. 168. 78. 128192. 168. 78. 200 ,通过 curl 访问服务器192. 168. 78. 3),进行测试

2. 默认访问权限

  • 打开 IP 地址为 192. 168. 78. 3 的 Nginx 服务器配置文件,按照如下配置修改 server 块 后,平滑重启 Nginx,使配置生效 。
1	server {
2		listen	80;
3		server_name 1ocalhost;
4		root html;
5		index index.html index.htm;
6		}
  • 为了方便测试,在 html 目录中编写 index. html ,输出一行提示信息,如下所示
<h1>Welcome 192.168. 78.3!</h1> 
  • 接着,利用之前准备的两个客户端(192. 168. 78. 128192. 168. 78. 200),通过 curl 请 求服务器地址 192. 168. 78. 3 ,具体命令如下。
curl http://192 .168.78.3 
  • 执行完上述命令后,若在两个客户端中都能看到如图所示的结果,表明虚拟主机默认未设置访问权限时,允许所有用户的访问,效果相当于为 server 设置 allow all
    在这里插入图片描述

3. 禁止所有用户的访问

  • 在步骤 2 中第 5 行下添加以下指令,用于禁止所有的客户端访问,具体如下。
deny all;
1	server {
2		listen	80;
3		server_name 1ocalhost;
4		root html;
5		index index.html index.htm;
6		deny all;
7		}
  • 接着,再次使用两个客户端进行访问测试,访问结果如图所示。从图中可以看出, 页面显示 403 Forbidden表明禁止访问成功
    在这里插入图片描述

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

4 . 只允许指定用户访问

  • 对于服务器 192. 468. 78. 3 来说,若仅允许客户端 192. 168. 78. 128 访问,则将第 3 步中 的权限设置修改成以下配置即可 。
1	server {
2		listen	80;
3		server_name 1ocalhost;
4		root html;
5		index index.html index.htm;
6		allow 192.168.78.128; 
7		deny all;
8		}
  • 上述指令表示只允许 192. 168. 78. 128 客户端访问,其他所有客户端都不能访问 。 利用之前准备的两个客户端可以进行测试。 需要注意的是,若省略此处的 deny all ,则会允许所有客户端访问;若将 deny all 移动到 allow 192. 168. 78. 128 之后,则会阻止所有客户端 访问 。
  • 从上述规律看出,同一个块下的两个权限指令,先出现的设置会覆盖后出现的设置,使 得 allow 192. 168. 78. 128 的配置优先生效;同时 deny 指令设置的访问范围 all 较大,未被 allow 覆盖的范围配置依然生效,达到除了 IP 为 192. 168. 78. 128 的用户外,禁止其他用户对服务器访问的效果 。

5. 不同块间的权限指令优先级

  • 为了测试不同块间的权限指令优先级,重新配置服务器 192. 168. 78. 3 的权限设置,在 http 块中设置禁止所有用户对 http 块的访问,具体配置如下 。
1	http {
2		...
3		deny all;
4		server {
5			1isten	80;
6			server_name		localhost;
7 			root	html;
8			index 	index.html index.htm;
10		}
11	}
  • 接着 ,使用之前准备的两个客户端访问测试,可以看到如上图 4-12 所示的访问失败结果 。 然后,在第 8 行指令的配置后添加以下配置。
allow all; 
  • 修改完成后,使用两个客户端访问,可以看到如图 4-11 所示的访问成功结果。 这是由于 Nginx 配置文件中的各个块在嵌套的情况下,内层块内的指令比外层块内的指令执行优先级高 。 因此,当内外层块中同时出现权限指令时,则内层块中的 allow all 会覆盖外层块 中的 deny all 的设置。

1.2 访问控制典型应用

  • 在实际应用中,权限控制的需求更加复杂。例如,对于网站下的 img 目录允许所有用户访问,但对于网站下的 admin 目录则仅允许管理员身份的用户访问。此时,仅靠 deny 和 allow 这两个权限指令不能满足用户的需求,还需要使用 location 块来完成相关需求的匹配。
  • 在此之前,首先要简单了解一下 location 的相关语法及规定,具体如下。
location	[ = I ~ | ~ * | ^ ~ ]	URI 	{ ... }		#语法类型1
location @name		{ ... }								#语法类型2
  • 在上述语法中, ~ *^~都是 location 用于实现访问控制的前缀,且在使用时只能选择一种,当然也可以不设置前缀。其中,关于 location 前缀的含义如表 4-3 所示。 URI 表示 URL 地址中从域名到参数之间的部分 , { … }表示指令块 ,用于满足 location 匹配条件后需要执行的指令。
    在这里插入图片描述
  • 根据表 4-3 的描述,可将 location 根据不同前缀的使用方式,大致分为普通 location正则 locationo 其中,~和~*属于正则 location其余的前缀和没有前缀的情况都属于普 通 location。
  • 接下来,通过 location 块和权限控制指令,逐一演示访问控制的几种典型使用方式。

1. 精准匹配

  • 所谓精准匹配指的就是用户访问的 URI 与指定的 URI 完全一致的情况,才会执行其后的指令块,示例配置如下 。
1	server {
2	listen	80;
3	server_name localhost;
4	root html;
5	index index.html index.htm;
6	location = /js {
7		allow 192.168.78.128;
8	}
9	location = /admin/auth{
10			allow 192.168.78.200;
11 		}
12		deny all;
13	}
  • 上述第 6~8 行和第 9~11 行配置设置了两个精准匹配,第 12 行用于禁止所有用户的访问 。当上述配置中允许访问的两个客户端,请求网站根目录下不存在的文件或目录时,如果符合匹配规则,网页显示 404 Not Found,不符合时显示 403 Forbidden

  • 假设网站根目录下没有任何文件,下面使用 IP 为 192. 168. 78. 128 的 A 用户和 IP 为 192. 168. 78. 200 的 B 用户通过不同的 URL 进行访问测试,其对应的响应结果如表 4-4 所示。
    在这里插入图片描述

  • 从表 4-4 可以看出,精准匹配是只有用户请求的 URIlocation 中定义的匹配模式完 全一致的情况下,才会执行其后的指令块,否则匹配不成功。

2. 正则匹配

  • Nginx 配置文件中,多个正则 location 之间按照正则 location 在配置文件中的书写顺序进行匹配,且只要匹配成功就不会继续匹配后面定义的正则 location. 下面在 IP 为 192. 168. 78. 3 的虚拟机中,设置以下两个正则 location 访问控制,具体如下 。
1	location ~ \.html$ {
2		allow all;
3	}
4	location ~ ^/aaa/.* \.html$ {
5		deny all;
6 	}
  • 在上述配置中,第 1 行表示匹配网站根目录下以.html 结尾的文件,第 4 行表示匹配网站根目录下 aaa 目录中以. html 结尾的文件。

  • 下面使用 IP 为 192. 168. 78. 128 的用户通过不同的 URL 进行访问测试,其对应的响应 结果如表 4-5 所示 。
    在这里插入图片描述

  • 从表 4-5 可以看出,当 location 中的 URI 与用户请求中以 .html 为结尾的文件匹配上时,正则 location 停止了继续匹配,因此显示结果都为 404 Not Found

  • 接下来,调换第 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 将会执行,示例如下 。
1	location /ng.test {
2		allow all;
3	}
4	location /ng.test/log {
5		deny all;
6	}
  • 为了方便对比学习 ,下面利用不同的 URL 进行访问测试,对应的响应结果如表 4-6 所示。
    在这里插入图片描述

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

1	location / {
2		deny all;
3	}
4	location ~\.html$ {
5		allow all;
6	}
  • 上述配置中,第 1~3 行定义的是最大前缀 location,用于匹配当前网站根目录下的所有文件,第 4~6 行用于正则匹配所有以.html 结尾的 URI。 不同 URL 及其对应的响应结果如表 4-7 所示。
    在这里插入图片描述
  • 从表 4-7 中可以看出,当用户访问 http : //192. 168. 78. 3 时,完成第 1 行的匹配;而在用户访问 http: //192. 168. 78. 3/ notfound. htmlhttp : //192. 168. 78. 3/ index.php 时,前者符合正则 location,结果为 404 Not Found ,而后者不符合正则 location ,显示了最大前缀匹 配的结果 403 Forbidden

location / {} 与location =/ {} 的区别

  • location / {}遵守普通 location 的最大前缀匹配,由于任何 URI 都必然以“ / ” 根开头, 所以对于一个 URI ,若配直文件中有更合适的匹配则会将其替代,否则返回 location /{} 匹配到的结果,它相当于站点默认配直 。
  • location= / {}遵 守的是精准匹配,也就是只能匹配该站点根目录,同时会禁止继续搜索正则 location ,效率比 location / {}妥高 。 因此,若在开发中能确定精准匹配的情况,可以采用 location =/{} 的方式,提升匹配效率 。

4. 禁用正则匹配

  • 利用 精准匹配或 ^~非正则匹配可以在正则匹配之前优先匹配,从而禁止执行原有的正则匹配 。 下面在 server 块中添加以下几条 location 匹配规则,具体如下 。
1	location = /aaa/test.html {
2		allow all;
3	}
4	location ^~ {
5		deny all;
6	}
7 	location ~\.html$ (
8		allow all;
9	}
  • 在上述配置中,第 1 行仅用于精准匹配网站根目录下的aaa/ test.html ,第 4 行用于非 正则匹配网站根目录下的文件,第 7 行用于正则匹配网站根目录下以.html 为结尾的文件。
  • 接下来通过不同 URL 进行访问测试,具体如表 4-8 所示。从表中的响应结果可以看 出,在使用了“=”“^~”前缀时,普通 location 匹配后将不再执行正则 location 的匹配 。
  • 值得一提的是,前缀“=”“^~”虽然都能阻止继续搜索正则 location ,不同的地方是它们遵循的规则不同,叫“^~”依然遵循最大前缀匹配规则,而则严格按照精准匹配执行。
  • 因此,当多种类型的 location 匹配同时出现时,最终执行结果为“ = ”匹配优先于“^~” 匹配,“^~”匹配优先于正则匹配,正则匹配优先于普通的最大前缀匹配。 只要优先的 location 匹配成功,就不会执行其他的 location
    在这里插入图片描述

root 与 alias 的时区别

  • location 中指定目录时,除了可以使用 root 指令外,还可以使用 alias 指令完成 。 两者在使用时有一定的区别,具体示例如下 。
#当收到"/img/a.png"请求时,将请求映射为"/var/www/image/a.png"
location /img/ {
	alias /var/www/image/;
}
#当收到"/img/b.png"请求时,将请求映射为"/var/www/image/img/b.png"
location /img/ {
	root /var/www/image;
}
  • 从上述示例可以看 出 ,alias 在映射路径时不会追加 location 匹 配到的 部分,而 root 追加了 location 匹配到的部分。
posted @ 2020-12-06 17:19  兮动人  阅读(391)  评论(1编辑  收藏  举报