介绍
为网站配置服务器时,您可能需要实施一些常见的条件操作。例如,也许某些文件应该被用户的浏览器缓存的时间比其他文件长,或者网站的某些部分应该只允许通过安全连接(例如需要用户密码的任何内容),而网站的其他部分则不吨。
另一个简单、常见的例子是确保当一个新网页代替旧网页发布时,所有旧地址都将重定向到正确的位置。这很有用,因为这意味着旧链接和书签不会停止工作,并且还保留了 Google 的缓存。
Nginx 的 map 模块允许您在 Nginx 的配置文件中创建变量,其值是有条件的——也就是说,它们依赖于其他变量的值。在本指南中,我们将了解如何使用 Nginx 的地图模块实现两个示例:如何设置从旧网站 URL 到新网站的重定向列表以及如何创建国家/地区许可名单以控制您网站的流量。
先决条件
要学习本教程,您需要:
-
使用此初始服务器设置教程设置的一台 Ubuntu 16.04 服务器,包括 sudo 非 root 用户。
-
按照如何在 Ubuntu 16.04 上安装 Nginx 教程,在您的服务器上安装 Nginx。
步骤 1 — 创建和测试示例网页
首先,我们将创建一个代表新发布网站的测试文件。我们将使用此文件来测试我们的配置。
让我们index.html
在默认的 Nginx 网站目录中创建一个简单的页面。这个文件只有纯文本描述里面的内容:Home。
- sudo sh -c 'echo "Home" > /var/www/html/index.html'
有了这个测试文件,接下来我们将检查它是否正确地使用curl
. 我们不需要index.html
为此命令指定,因为如果没有提供确切的文件名,则默认情况下会提供该文件。
- curl http://localhost/
作为回应,您应该看到一个单词Home,如下所示:
Home
现在让我们尝试访问一个不存在的文件/var/www/html/
,比如old.html
.
- curl -L http://localhost/old.html
响应将是系统错误消息404 Not Found,这意味着该页面不存在。
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.10.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 步中创建的简单主页。
Home
这意味着地图已正确配置,您可以使用它通过向地图添加更多条目来重定向 URL。
重定向 URL 是地图模块的一项有用应用。我们将在下一步中探讨的另一个是根据访问者的地理位置过滤流量。
第 3 步 – 限制某些国家/地区的网站访问
有时,服务器可能会收到过多的自动化恶意请求。这可能是 DDoS 攻击、尝试暴力破解网站管理面板的密码,或尝试利用软件中的已知漏洞攻击网站并使用它发送垃圾邮件或修改网站内容。
这种自动攻击可能来自许多不同国家的许多不同的分布式服务器,因此很难阻止。减轻此类攻击影响的一种解决方案是创建可以访问该网站的国家/地区的许可名单。
这不是一个完美的解决方案,但在基于访问者的地理位置限制对网站的访问是一个明智的选择并且不限制网站的受众的情况下,此解决方案具有快速且不易出错的优点。
服务器级别的过滤比网站级别的过滤更快,并且还涵盖所有请求(包括静态文件,如图像)。这种过滤还完全阻止了请求到达网站软件,这使得漏洞更难被利用。
为了使用地理过滤,让我们首先创建一个新的配置文件。
- sudo nano /etc/nginx/conf.d/geoip.conf
将以下内容粘贴到文件中。这告诉 Nginx 在哪里可以找到包含访问者 IP 地址与其各自国家/地区之间映射的 GeoIP 数据库。该数据库预装了 Ubuntu 16.04。
. . .
# 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 模块的非常简单的示例,但它展示了可以以许多其他不同方式使用的机制。map 模块不仅允许简单的比较,还支持允许更复杂匹配的正则表达式。如果必须评估多个条件,这是使配置文件更清晰的好方法。
地图模块的另一个非常流行的用例是在其他非 SSL 环境中对网站的安全部分进行条件重定向。仅为需要输入密码的表单设置强制 SSL 连接是一个很好的示例,说明如何在现实世界场景中应用地图模块,我鼓励尝试这种设置。
更详细的信息可以在 Nginx 的官方地图模块文档中找到。