作为 Write for DOnations 计划的一部分,作者选择了 Open Internet/Free Speech Fund 来接受捐赠。
介绍
Nginx 的 map 模块允许您在 Nginx 的配置文件中创建变量,其值是有条件的——也就是说,它们依赖于其他变量的值。 在本指南中,我们将了解如何使用 Nginx 的地图模块来实现两个示例:设置从旧网站 URL 到新 URL 的重定向列表以及创建国家许可列表以控制您网站的流量。
先决条件
要遵循本教程,您将需要:
- 一个 Ubuntu 20.04 服务器,带有一个具有 sudo 权限的常规非 root 用户。 您可以按照初始服务器设置教程学习如何准备服务器。
- 按照 如何在 Ubuntu 20.04 上安装 Nginx 教程 在您的服务器上安装 Nginx。
第 1 步 - 创建和测试示例网页
首先,我们将创建一个代表新发布网站的测试文件。 我们将使用这个文件来测试我们的配置。
让我们在默认的 Nginx 网站目录中创建一个简单的页面 index.html
。 该文件将仅包含描述内部内容的纯文本:主页:
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
配置块,如下所示:
/etc/nginx/sites-available/default
. . . # Default server configuration # server { listen 80 default_server; listen [::]:80 default_server; . . .
我们将添加两个新部分:一个在 server
块之前,一个在它里面。
server
块之前的部分是一个新的 map
块,它使用 map 模块定义旧 URL 和新 URL 之间的映射。 server
块内的部分是重定向本身:
/etc/nginx/sites-available/default
. . . # 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 地址,然后将其与大括号中的条件列表进行比较。 条件列表中的每个项目都有两个部分:要匹配的值和匹配时分配给变量的新值。
map
块内的 /old.html /index.html
行表示如果 $uri
的值为 /old.html
,则 $new_uri
将更改为 /index.html
。 如果不匹配,则不会更改。 在这里,我们只定义一个条件,但您可以在地图中定义任意数量的条件。
使用 server
块内的条件 if
语句,我们检查是否设置了 $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 是 map 模块的一个有用的应用。 我们将在下一步中探讨的另一个是根据访问者的地理位置过滤流量。
第 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 地址识别国家:
/etc/nginx/conf.d/geoip.conf
# GeoIP database path # geoip_country /usr/share/GeoIP/GeoIP.dat;
下一步是创建必要的地图和限制配置。 打开默认服务器块 Nginx 配置:
sudo nano /etc/nginx/sites-available/default
找到 server
配置块,在步骤 1 和 2 中修改后,如下所示:
/etc/nginx/sites-available/default
. . . # 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
块,它定义了默认操作(不允许访问)以及允许访问网站的国家代码列表。 如果 map
结果显示如下,则 server
块内的部分拒绝访问该网站:
修改 /etc/nginx/sites-available/default
. . . # 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
时,您会看到类似 The page is not working 或 The page没有发送任何数据。 如果您确实将您的国家/地区添加到了许可名单,您会像以前一样看到 Home。
结论
map 模块不仅允许简单的比较,还支持允许更复杂匹配的正则表达式。 如果必须评估多个条件,这是使配置文件更清晰的好方法。
更详细的信息可以在 Nginx 的官方地图模块文档中找到。