如何使用SSL终止设置Nginx负载平衡

来自菜鸟教程
跳转至:导航、​搜索

介绍

本文向您展示了如何使用负载均衡器上的一个 SSL 证书设置带有 SSL 终止的 Nginx 负载均衡。 这将减少您的 SSL 管理开销,因为现在可以从负载均衡器本身管理 OpenSSL 更新以及密钥和证书。

关于 SSL 终止

Nginx 可以配置为负载均衡器,以在多个后端服务器之间分配传入流量。 SSL 终止是发生在负载均衡器上的过程,它处理 SSL 加密/解密,以便负载均衡器和后端服务器之间的流量在 HTTP 中。 必须通过限制对负载均衡器 IP 的访问来保护后端,本文稍后将对此进行解释。

先决条件

在本教程中,命令必须以 root 用户或具有 sudo 权限的用户身份运行。 您可以在 用户教程 中查看如何设置它。

以下指南可作为参考:

LAMP 服务器不是必需的,但我们将在本教程中使用它作为示例。

设置

本教程使用以下 3 个液滴:

液滴 1(前端)

  • 图片:Ubuntu 14.04
  • 主机名:负载均衡器
  • 私有 IP:10.130.227.33

液滴 2(后端)

  • 图片:Ubuntu 14.04
  • 主机名:web1
  • 私有 IP:10.130.227.11

Droplet 3(后端)

  • 图片:Ubuntu 14.04
  • 主机名:web2
  • 私有 IP:10.130.227.22

域名 - example.com

所有这些 Droplet 都必须启用 私有网络

更新和升级所有三台服务器上的软件:

apt-get update && apt-get upgrade -y

重新启动每个服务器以应用升级。 这很重要,因为 OpenSSL 需要使用最新版本才能确保安全。

我们将为域名设置一个新的 Nginx 虚拟主机,其中上游模块负载平衡后端。

在设置 Nginx 负载平衡之前,您应该在您的 VPS 上安装 Nginx。 您可以使用 apt-get 快速安装它:

apt-get install nginx

在两个后端服务器上,更新您的存储库并安装 Apache:

apt-get install apache2

在两个后端服务器上安装 PHP:

apt-get install php5 libapache2-mod-php5 php5-mcrypt

有关详细信息,请参阅这篇文章

生成密钥并创建 SSL 证书

在本节中,您将完成创建 SSL 证书所需的步骤。 这篇文章详细讲解了Nginx上的SSL证书。

创建 SSL 证书目录并切换到它。

mkdir -p /etc/nginx/ssl/example.com
cd /etc/nginx/ssl/example.com

创建私钥:

openssl genrsa -des3 -out server.key 2048

删除其密码:

openssl rsa -in server.key -out server.key

创建 CSR(证书签名请求):

openssl req -new -key server.key -out server.csr

使用此 CSR 从 证书颁发机构 获取有效证书,或使用以下命令生成自签名证书。

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

完成此操作后,此目录将包含以下文件:

  • server.key - 私钥
  • ca-certs.pem - CA 的根证书和中间证书的集合。 仅当您从 CA 获得有效证书时才存在。
  • server.crt - 您的域名的 SSL 证书

虚拟主机文件和上游模块

在 Nginx 目录中创建一个虚拟主机文件

nano /etc/nginx/sites-available/example.com

添加包含后端服务器私有 IP 地址的上游模块

upstream mywebapp1 {
    server 10.130.227.11;
    server 10.130.227.22;
}

这一行之后开始服务器块。 此块包含域名、对上游服务器的引用以及应传递给后端的标头。

server {
    listen 80;
    server_name example.com www.example.com;
    
    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

proxy_set_header 指令用于将有关请求的重要信息传递给上游服务器。

保存此文件并创建指向 sites-enabled 目录的符号链接。

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

执行配置测试以检查错误。

service nginx configtest

如果没有报错,重新加载nginx服务。

service nginx reload

现在已经为 HTTP 配置了负载平衡。

启用 SSL

将以下指令添加到 server {} 块内的虚拟主机文件 (/etc/nginx/sites-available/example.com)。 这些行将在下一个示例的上下文中显示。

listen 443 ssl;
ssl on;
ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;

如果您使用自签名证书,请忽略 ssl_trusted_certificate 指令。 现在 server 块应该如下所示:

server {
    listen 80;
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl on;
    ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
    ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;

    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

检查配置错误并重新加载 Nginx 服务。

service nginx configtest && service nginx reload

保护后端服务器

目前,任何知道其公共 IP 地址的人都可以直接访问托管在后端服务器上的网站。 这可以通过将后端的 Web 服务器配置为仅在私有接口上侦听来防止。 在 Apache 中执行此操作的步骤如下。

编辑 ports.conf 文件。

nano /etc/apache2/ports.conf

找到以下行:

Listen 80

将其替换为 后端服务器的 自己的私有 IP 地址:

Listen 10.130.227.22:80

在所有后端服务器上执行此操作并重新启动 Apache。

service apache2 restart

下一步是限制对 负载平衡器的 私有 IP 的 HTTP 访问。 以下防火墙规则实现了这一点。

iptables -I INPUT -m state --state NEW -p tcp --dport 80 ! -s 10.130.227.33 -j DROP

将示例替换为负载均衡器的私有 IP 地址,并在所有后端服务器上执行此规则。

测试设置

在所有后端服务器(本例中为 web1 和 web2)上创建一个 PHP 文件。 这是为了测试,一旦设置完成就可以删除。

nano /var/www/html/test.php

它应该打印访问的域名,服务器的IP地址,用户的IP地址和访问的端口。

<?php
    header( 'Content-Type: text/plain' );
    echo 'Host: ' . $_SERVER['HTTP_HOST'] . "\n";
    echo 'Remote Address: ' . $_SERVER['REMOTE_ADDR'] . "\n";
    echo 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
    echo 'X-Forwarded-Proto: ' . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "\n";
    echo 'Server Address: ' . $_SERVER['SERVER_ADDR'] . "\n";
    echo 'Server Port: ' . $_SERVER['SERVER_PORT'] . "\n\n";
?>

使用浏览器或使用 curl 多次访问此文件。 在自签名证书设置上使用 curl -k 以使 curl 忽略 SSL 错误。

curl https://example.com/test.php https://example.com/test.php https://example.com/test.php

输出将类似于以下内容。

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.11
   Server Port: 80

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.22
   Server Port: 80

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.11
   Server Port: 80

请注意,Server Address 在每次请求时都会发生变化,表明不同的服务器正在响应每个请求。

强化 SSL 配置

本节说明根据最佳实践配置 SSL 以消除旧密码和协议的漏洞。 本节显示了各个行,本教程的最后一节显示了完整的配置文件。

启用 SSL 会话缓存可提高 HTTPS 网站的性能。 以下指令必须放在 之后 ssl_trusted_certificate。 它们启用大小为 20MB 的共享缓存,缓存寿命为 10 分钟

ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;

指定要在 SSL 连接中使用的协议和密码。 在这里,我们省略了 SSLv2 并禁用了 MD5 和 DSS 等不安全密码。

ssl_prefer_server_ciphers       on;
ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers                     ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

严格传输安全指示所有支持的网络浏览器只使用HTTPS。 使用 add_header 指令启用它。

add_header Strict-Transport-Security "max-age=31536000";

检查配置错误并重新加载 Nginx 服务。

service nginx configtest && service nginx reload

完成配置

配置和加固 SSL 终止后,完整的配置文件将如下所示:

/etc/nginx/sites-available/example.com

upstream mywebapp1 {
    server 10.130.227.11;
    server 10.130.227.22;
}

server {
    listen 80;
    listen 443 ssl;
    server_name example.com www.emxaple.com;

    ssl on;
    ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
    ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
    
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;
    
    ssl_prefer_server_ciphers       on;
    ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                     ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
    
    add_header Strict-Transport-Security "max-age=31536000";

    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

进行 SSL 服务器测试,此设置应获得 A+ 级。 再次运行 curl 测试以检查一切是否正常。

curl https://example.com/test.php https://example.com/test.php https://example.com/test.php

延伸阅读

要了解有关负载平衡算法的更多信息,请阅读 这篇文章