即使使用默认设置,Nginx也是一个非常安全可靠的Web服务器。但是,有很多方法可以进一步保护Nginx。
在本文中,我们将专门使用开源软件,同时尝试遵循一些流行的Web服务器强化方法和安全标准。也就是说,我们将讨论防止信息泄露,实施加密,执行审计和限制访问。
准备
在学习本教程之前,请确保完成以下内容:
- Ubuntu 14.04 CVM,没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。
- 安装和配置Nginx Web服务器。
- 已注册的域或子域指向CVM的IP。您将需要它来测试SSL设置。
- 如果你有域名,保护你网站的最简单方法是使用腾讯云SSL证书服务,它提供免费的可信证书。腾讯云SSL证书安装操作指南进行设置。
- 如果你没有域名,建议您先去这里注册一个域名,如果你只是使用此配置进行测试或个人使用,则可以使用自签名证书,不需要购买域名。自签名证书提供了相同类型的加密,但没有域名验证公告。关于自签名证书,你可以参考为Apache创建自签名SSL证书和如何为Nginx创建自签名SSL证书这两篇文章。
- 具有
sudo
命令权限的非root用户(有关详细信息,请查看Linux系统下给非root用户添加sudo权限)
除非另有说明,否则本教程中需要root权限的所有命令都应作为具有sudo权限的非root用户运行。
第一步 - 更新所有软件
将软件更新到最新版本是保护整个系统的第一步,而不仅仅是Nginx。
警告:在更新系统上的所有软件包之前,请务必确定这是否会导致除Nginx之外的系统上运行的任何问题。在执行一次影响这么多包的操作之前,最好先备份整个系统。如果在更新所有软件包后出现问题,您可以恢复备份。要更新存储库软件包列表,然后用apt-get
更新在Ubuntu服务器上管理的所有当前安装的软件包,请运行以下命令:
sudo apt-get update && sudo apt-get upgrade
或者,您可以将Nginx升级到Ubuntu存储库中的最新版本。这将升级Nginx包和任何必要的依赖项:
代码语言:javascript复制sudo apt-get upgrade nginx
第二步 - 防止信息泄露
要开始强化您的Nginx Web服务器,我们首先要限制它公开的信息。从HTTP服务器标头到应用程序错误报告的每个级别都泄露了有价值的信息。
所以让我们从HTTP标头开始。默认情况下,Nginx在HTTP标头中显示其名称和版本。你可以这样检查这些信息curl
:
curl -I http://localhost
输出应如下所示:
代码语言:javascript复制HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
...
如您所见,在上面的输出中可以看到Nginx的版本和操作系统的名称。这不一定是一个严重的问题,而是攻击者试图解决以破坏您的Nginx服务器的难题的一部分。这就是为什么我们通过像这样用nano 打开Nginx的主配置文件/etc/nginx/nginx.conf
来隐藏这些信息的原因:
sudo nano /etc/nginx/nginx.conf
然后,在http
配置部分内添加server_tokens off;
行:
http {
##
# Basic Settings
##
server_tokens off;
...
之后,保存并退出该文件,然后重新加载Nginx以使更改生效:
代码语言:javascript复制sudo service nginx reload
现在,如果再次尝试相同的curl命令:
代码语言:javascript复制curl -I http://localhost
您将看到更少的信息:
代码语言:javascript复制HTTP/1.1 200 OK
Server: nginx
...
以上输出仅公开了这是Nginx服务器的事实。你可能想知道你是否也可以删除它。不幸的是,这并不容易实现,因为它没有配置选项。相反,你将不得不从源代码重新编译Nginx,这是值得的。
除了Server
标题之外,还有另一个包含敏感信息的标题 - X-Powered-By
。此标头通常显示PHP,Tomcat或Nginx背后的任何服务器端引擎的版本。如果你用PHP运行Nginx,输出curl
将如下所示:
HTTP/1.1 200 OK
Server: nginx
...
X-Powered-By: PHP/5.5.9-1ubuntu4.14
...
上面的X-Powered-By
标题显示服务器是运行PHP版本5.5.9的Ubuntu 14。从X-Powered-By
标题中隐藏此信息非常重要。你不能在Nginx中这样做,但你应该在后端引擎中找到相应的选项。例如,对于PHP的情况,您必须在主php.ini
配置文件中设置该expose_php = Off
选项。默认情况下,此选项设置为On
。
接下来要做的是更改4xx(客户端)错误页面,攻击者可以使用这些错误页面。通常,这些是Unauthorized 401
和Forbidden 403
错误页面。除非您正在调试问题,否则通常不需要向常规访问者显示这些错误。如果您需要了解这些错误,您仍然可以在Nginx错误日志(/var/log/nginx/error.log
)中找到它们。
要更改这两个错误页面,请打开服务器块的配置文件,例如默认值:
代码语言:javascript复制sudo nano /etc/nginx/sites-enabled/default
在主服务器server
配置部分内指定:
server {
...
error_page 401 403 404 /404.html;
...
将更改保存到文件后,请确保重新加载Nginx,以使其对命令生效:
代码语言:javascript复制sudo service nginx reload
以上提示为您提供了防止信息泄露的想法 - 尽可能少地显示非必要的Web内容。您不仅应该在Nginx中隐藏服务和调试信息,还应该在后端引擎(PHP,Tomcat等)中隐藏服务和调试信息,当然还应该隐藏在Web应用程序中。
第二步 - 配置SSL
在Nginx上运行带有SSL的安全HTTPS协议是处理敏感信息(如用户凭据,私人数据等)的任何站点必须的。SSL是确保无论您的站点用户位于何处以及Internet连接的唯一方法,他们使用,他们收到和发送的信息将受到保护。
虽然本文是一个良好的开端,但它无法有效保护您的数据。如今,默认的SSL设置和算法不够强大,无法阻止攻击者解密您的流量。
这就是为什么我们将使用更强大的加密算法和设置为Nginx配置SSL证书。这将确保为您的数据提供更高级别的保护,您的HTTPS服务将符合最高安全标准和实践。
让我们从使用以下命令为SSL证书创建目录开始:
代码语言:javascript复制sudo mkdir /etc/nginx/ssl/
对于我们的SSL,我们需要一个带有强签名算法SHA256的证书。出于测试目的或非生产环境,您可以使用自签名证书并忽略SSL警告。让我们用命令创建一个:
代码语言:javascript复制sudo openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
此命令将向您询问有关您的站点和业务详细信息的一些简单问题。之后,它将在/etc/nginx/ssl/nginx.key
文件中创建一个2048位RSA加密密钥,并在该/etc/nginx/ssl/nginx.crt
文件中创建一个SHA256证书。
接下来,您将必须生成更强,4096位长的DH参数。准备好等待一段时间,取决于你的CVM,它可能需要长达30分钟。运行命令:
代码语言:javascript复制sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
现在,您可以配置服务器块的SSL部分。例如,让我们配置默认服务器块。使用nano进行编辑配置文件:
代码语言:javascript复制sudo nano /etc/nginx/sites-enabled/default
在此文件中,编辑服务器配置部分,在server_name
指令之后添加SSL部分,如下所示:
server {
...
server_name localhost;
### SSL Part
listen 443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
...
以下是我们使用上述指令指定的指令:
listen
- 在端口443上启用SSL侦听器,即HTTPS端口。ssl_protocols
- 仅启用这三个被认为是当前安全的协议 -TLSv1 TLSv1.1 TLSv1.2
。ssl_ciphers
- 仅启用这些安全SSL密码:EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH
ssl_prefer_server_ciphers
- 确保客户端尊重服务器的密码首选项。ssl_dhparam
- 使用我们之前生成的自定义强DH参数。ssl_certificate
- 使用我们的自签名SSL证书。如果您使用其他证书,请务必更改它。ssl_certificate_key
- 使用我们之前生成的SSL私钥。
要使上述设置生效,您必须使用以下命令重新加载nginx:
代码语言:javascript复制sudo service nginx reload
要测试新的SSL配置,最好使用外部工具,例如SSL Labs提供的工具。在那里你应该忽略SSL不受信任的警告。这很自然,因为它是一个自签名证书。请注意,此站点仅测试具有注册域名的站点。您无法仅使用CVM的IP地址测试SSL连接。
整体结果应该是“T”,就像“测试”一样,但基本上它是A(最高可能),它应该这样说"If trust issues are ignored: A"
:
稍后,您可能希望删除SSL警告并使SSL测试成为“A”。一种选择是使用** Let's Encrypt **,如在Ubuntu 14.04上如何使用Let's Encrypt来保护Nginx一文中所述。它是免费的,允许您指定最多4096的RSA密钥大小,并且不会发出有关自签名的警告。否则,您可以选择任何商业SSL提供商。当您选择一个时,请确保您选择SHA256证书。
第三步 - 通过IP限制访问
密码身份验证并不总是足以确保站点敏感区域的安全性,例如站点控制面板,phpmyadmin等。有时,攻击者利用这些区域中的弱密码或软件漏洞来获取未经授权的访问。这就是为什么强烈建议您添加额外的IP限制,前提是您可以确定合法用户的IP。
例如,如果您有一个WordPress站点并且其管理区域位于/wp-admin/
,则应将其访问权限仅限于您的IP或所有管理员的IP。为此,打开相应的服务器块 - Nginx的默认服务器块是/etc/nginx/sites-enabled/default
:
sudo nano /etc/nginx/sites-enabled/default
在server
配置部分内添加:
server {
...
location /wp-admin/ {
allow 192.168.1.1/24;
allow 10.0.0.1/24;
deny all;
}
...
...
在上面请确保更换192.168.1.1
和10.0.0.1
您的IP。同样,您可以通过更改网络掩码(/24
)来允许访问其他IP甚至网络。
要使这些设置生效,您必须使用以下命令重新加载Nginx:
代码语言:javascript复制sudo service nginx reload
现在,如果您尝试使用/wp-admin/
允许的IP地址范围之外的浏览器访问站点的某个部分,则会出现错误。此错误将为403 禁止页(除非您已将此错误更改为404未找到,如前所述)。同时,您将使用以下命令在错误日志中看到真正的错误代码:
sudo tail /var/log/nginx/error.log
该access forbidden
错误将表明这样的:
...
2016/01/02 04:16:12 [error] 4767#0: *13 access forbidden by rule, client: X.X.X.X, server: localhost, request: "GET /wp-admin/ HTTP/1.1", host: "Y.Y.Y.Y"
...
应用多种安全方法(例如更改错误页面和限制IP访问)的组合显示了强化Nginx的累积效果。根据示例,攻击者和他们使用的自动化工具将会看到404找不到的页面,而不是通常的WordPress管理页面。这很令人困惑,可能会阻止他们尝试其他方法来破坏你的WordPress。
第四步 - 执行安全审计
独立于您自己的意见进行安全检查始终是个好主意。为此,您可以使用安全审核工具来扫描Web漏洞。有许多这样的工具,包括商业工具,一开始你可以使用免费和开源的wapiti。Wapiti可能缺乏更高级工具的一些功能,但它会让您了解安全审核的内容。
你可以通过apt在Ubuntu上安装wapiti:
代码语言:javascript复制sudo apt-get install wapiti
然后使用以下命令开始使用wapiti扫描您的站点:
代码语言:javascript复制wapiti http://example.org -n 10 -b folder
请务必替换example.org
为您网站的名称。我们给了命令两个额外的参数。第一个-n 10
将具有相同模式的URL数限制为10,以防止无限循环。第二个参数-b folder
仅将扫描范围设置为给定域。
扫描完成后,您将在您运行扫描的目录中调用的目录中generated_report
结果。要获得最佳查看效果,请将此目录下载到本地计算机,然后使用Web浏览器打开该index.html
文件。
在报告中,您将看到以10个不同类别排序的漏洞:SQL注入,盲SQL注入,文件处理,跨站点脚本,CRLF,命令执行,资源消耗,Htaccess绕过,备份文件和潜在危险文件。
理想情况下,您的报告应该如下所示,没有发现漏洞:
如果存在漏洞,则可以展开扫描的相应部分以获取更多信息。
确保经常使用不同的工具运行此类扫描,以确保对您的Nginx和网站进行最全面和最彻底的审核。
第五步 - 采取额外的安全措施
有关Nginx安全性的一些主题未在本文中介绍,因为已有关于它们的优秀文章。请熟悉以下内容:
- 如何在Ubuntu 14.04上安装和配置Naxsi
Naxsi是Nginx的Web应用程序防火墙。它通过使用恶意签名的汇编来保护您免受已知和未知的Web漏洞的攻击。
您应该知道Naxsi是一个复杂的软件,它的调整需要一些时间和精力。幸运的是,大多数流行的Web应用程序都有现成的配置,您可以根据需要进一步自定义。
Fail2ban是一个很好的工具,可以将Web安全性提升到一个新的水平,并主动保护您的nginx服务器。到目前为止,我们限制用户查找某些信息并访问我们网站的部分内容。使用fail2ban,当您检测到攻击者正在执行恶意活动时,您可以进一步阻止攻击者。
监控对于安全至关重要,Monit是一个很好的工具,可以为Nginx提供良好的支持。Web日志不仅显示恶意活动的痕迹,而且还显示CPU负载和内存使用量的峰值。
在本文中,要特别注意第五步 - 监视错误和关键字的日志。在那里,您可以配置自定义警报,以便在安全事件发送时发送,例如当有人访问或尝试访问您站点的敏感部分时。
- 如何在Ubuntu 14.04上使用Iptables设置防火墙
拥有防火墙对于nginx和整个CVM的安全性非常重要。确保将https(tcp 443)端口添加到标准http(tcp 80)端口之外的允许传入连接。
上面的文章有点过时,不是专门为Ubuntu编写的。但是,您应该能够轻松地对其进行调整并将其应用于Ubuntu 14.04。配置AIDE或其他类似工具时,请确保排除Web日志和临时文件(如Web缓存)的监视。
结论
阅读本文后,您应该对Nginx安全性更有信心。只需确保在功能和安全性之间寻求平衡,这样您就可以放心,您的Web环境按设计运行且安全可靠。另外,请记住,保护Nginx是一项持续性任务,需要定期更新,重新配置,扫描等。
想要了解更多关于Ubuntu的开源信息教程,请前往腾讯云 社区学习更多知识。
参考文献:《How To Secure Nginx on Ubuntu 14.04》