作者选择开放互联网/言论自由基金接受捐赠,作为Write for DOnations计划的一部分。
介绍
Nginx 的 map 模块允许您在 Nginx 的配置文件中创建变量,其值是有条件的——也就是说,它们依赖于其他变量的值。在本指南中,我们将了解如何使用 Nginx 的地图模块来实现两个示例:设置从旧网站 URL 到新网站的重定向列表,以及创建国家/地区许可名单以控制您网站的流量。
先决条件
要学习本教程,您需要:
-
一台 Ubuntu 20.04 服务器,具有 sudo 权限的普通非 root 用户。您可以按照此初始服务器设置教程学习如何准备您的服务器。
-
按照如何在 Ubuntu 20.04 上安装 Nginx 教程,在您的服务器上安装 Nginx。
步骤 1 — 创建和测试示例网页
首先,我们将创建一个代表新发布网站的测试文件。我们将使用此文件来测试我们的配置。
让我们index.html
在默认的 Nginx 网站目录中创建一个简单的页面。该文件将仅包含描述内容的纯文本:主页:
- sudo sh -c 'echo "Home" > /var/www/html/index.html'
有了这个测试文件,我们将检查它是否正确地使用curl
. 我们不需要index.html
为此命令指定,因为如果没有提供确切的文件名,则默认情况下会提供该文件:
- curl http://localhost/
作为回应,您应该看到一个单词Home,如下所示:
OutputHome
现在让我们尝试访问 中不存在的文件/var/www/html/
,例如old.html
:
- curl -L http://localhost/old.html
响应将是系统错误消息404 Not Found,这意味着该页面不存在:
Output<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
在本教程中我们只是使用了一个虚拟网站,但是如果old.html
真实网站上的一个页面曾经存在并被删除,则返回 404 将意味着指向该页面的所有链接都已损坏。这不太理想,因为这些链接可能已被 Google 编入索引、打印或写下来,或通过任何其他方式共享。
在下一步中,我们将使用地图模块通过自动将查看者重定向到新的替换地址来确保该旧地址再次起作用。
第 2 步 – 配置重定向
对于只有几页的小型网站,if
可以使用简单的条件语句进行重定向和类似的事情。但是,随着条件列表越来越长,这种配置从长远来看并不容易维护或扩展。
map 模块是一个更优雅、更简洁的解决方案。它允许您将 Nginx 变量值与条件列表进行比较,然后根据匹配将新值与变量相关联。在这个例子中,我们将把请求的 URL 与我们想要重定向到新页面的旧页面列表进行比较。对于每个旧地址,我们将关联新地址。
map 模块是 Nginx 的核心模块,这意味着它不需要单独安装。要创建必要的映射和重定向配置,请在nano
您喜欢的文本编辑器中打开默认服务器块 Nginx 配置文件:
- sudo nano /etc/nginx/sites-available/default
找到server
配置块,如下所示:
. . .
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
. . .
我们将添加两个新部分:一个在server
块之前,一个在块内。
server
块之前的部分是一个新map
块,它使用 map 模块定义了旧 URL 和新 URL 之间的映射。server
块内的部分是重定向本身:
. . .
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .
该map $uri $new_uri
指令获取系统$uri
变量的内容,其中包含所请求页面的 URL 地址,然后将其与大括号中的条件列表进行比较。条件列表中的每一项都有两个部分:要匹配的值和要分配给变量(如果匹配)的新值。
块/old.html /index.html
内的行map
表示 if$uri
的值是/old.html
,$new_uri
将更改为/index.html
。如果不匹配,则不会更改。在这里,我们只定义一个条件,但您可以在地图中定义任意数量的条件。
使用块if
内的条件语句server
,我们检查是否设置了$new_uri
变量的值。如果是,则表示满足地图中的条件,我们应该使用该rewrite
命令重定向到新网站。该permanent
关键字确保重定向将是301 Moved Permanently HTTP 重定向,这意味着旧地址不再有效并且不会重新上线。
保存并关闭文件以退出。
要启用新配置,请重新启动 Nginx:
- sudo systemctl restart nginx
要测试新配置,请执行与之前相同的请求:
- curl -L http://localhost/old.html
这次输出中不会有404 Not Found错误。相反,您将看到我们在第 1 步中创建的简单主页:
OutputHome
这意味着地图已被适当配置,您可以使用它通过向地图添加更多条目来重定向 URL。
重定向 URL 是地图模块的一项有用应用。我们将在下一步中探讨的另一个是根据访问者的地理位置过滤流量。
第 3 步 – 限制某些国家/地区的网站访问
有时,服务器可能会收到过多的自动化恶意请求。这可能是 DDoS 攻击、尝试暴力破解网站管理面板的密码,或尝试利用软件中的已知漏洞攻击网站并使用它发送垃圾邮件或修改网站内容。
这种自动攻击可能来自许多不同国家的许多不同的分布式服务器,因此很难阻止。减轻此类攻击影响的一种解决方案是创建可以访问该网站的国家/地区的许可名单。
这不是一个完美的解决方案,但在基于访问者的地理位置限制对网站的访问是一个明智的选择并且不限制网站的受众的情况下,该解决方案具有快速且不易出错的优点。
服务器级别的过滤比网站级别的过滤更快,并且还涵盖所有请求(包括静态文件,如图像)。这种过滤还可以防止请求直接到达网站软件,从而使漏洞更难被利用。
要使用地理过滤,我们必须首先安装 Nginx GeoIP 模块以及包含访问者 IP 地址与其各自国家/地区之间映射的 GeoIP 数据库。为此,让我们执行:
- sudo apt install libnginx-mod-http-geoip geoip-database
现在,让我们首先创建一个新的配置文件:
- sudo nano /etc/nginx/conf.d/geoip.conf
将以下内容粘贴到文件中。这告诉 Nginx 在哪里可以找到 GeoIP 数据库以根据访问者的 IP 地址识别国家:
# GeoIP database path
#
geoip_country /usr/share/GeoIP/GeoIP.dat;
下一步是创建必要的地图和限制配置。打开默认的服务器块 Nginx 配置:
- sudo nano /etc/nginx/sites-available/default
找到server
配置块,在步骤 1 和 2 中修改后,如下所示:
. . .
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .
我们将添加两个新部分:一个在server
块之前,一个在块内。
server
块之前的部分是一个新map
块,它定义了默认操作(不允许访问)以及允许访问网站的国家代码列表。server
如果map
结果如此,则块内的部分拒绝访问该网站:
. . .
# Default server configuration
#
# Allowed countries
#
map $geoip_country_code $allowed_country {
default no;
country_code_1 yes;
country_code_2 yes;
}
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Disallow access based on GeoIP
if ($allowed_country = no) {
return 444;
}
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .
保存并关闭文件以退出。
在这里,我们使用country_code_1
和country_code_2
作为占位符。将这些变量替换为您要允许的国家/地区的两个字符的国家/地区代码。您可以使用ISO 的完整、可搜索的所有国家/地区代码列表进行查找。例如,美国的代码是US
。
与第一个示例不同,在此map
块中,$allowed_country
变量将始终设置为某个值。默认情况下,它设置为no
; 如果$geoip_country_code
变量与块中的国家/地区代码之一匹配,则将其设置为yes
。如果$allowed_country
变量是no
,我们将返回444 Connection Closed without Response而不是为实际网站提供服务。
要启用新配置,请重新启动 Nginx:
- sudo systemctl restart nginx
如果您没有将您所在的国家/地区添加到许可名单中,那么当您尝试访问时,您会看到一条错误消息,如页面无法正常工作或页面未发送任何数据。如果您确实将您的国家/地区添加到许可名单中,您将像以前一样看到主页。http://your_server_ip
结论
map 模块不仅允许简单的比较,而且还支持允许更复杂匹配的正则表达式。如果必须评估多个条件,这是使配置文件更清晰的好方法。
更详细的信息可以在 Nginx 的官方地图模块文档中找到。