如何在Ubuntu14.04上使用Let'sEncrypt保护HAProxy
介绍
Let's Encrypt 是一个新的证书颁发机构 (CA),它提供了一种简单的方法来获取和安装免费的 TLS/SSL 证书,从而在 Web 服务器上启用加密的 HTTPS。 它通过提供一个软件客户端 Certbot 来简化流程,该客户端尝试自动化大多数必需的步骤。 目前,获取和安装证书的整个过程仅在 Apache Web 服务器上是完全自动化的。 但是,Certbot 可用于轻松获得免费的 SSL 证书,无论您选择何种 Web 服务器软件,都可以手动安装该证书。
在本教程中,我们将向您展示如何使用 Certbot 获取免费的 SSL 证书并将其与 Ubuntu 14.04 上的 HAProxy 一起使用。 我们还将向您展示如何自动更新您的 SSL 证书。
先决条件
在学习本教程之前,您需要做一些事情。
您应该拥有一个 Ubuntu 14.04 服务器,并且该服务器具有具有 sudo
权限的非 root 用户。 您可以按照我们为 Ubuntu 14.04 的 初始服务器设置中的步骤 1-3 学习如何设置此类用户帐户。
您必须拥有或控制您希望使用证书的注册域名。 如果您还没有注册域名,您可以在众多域名注册商之一注册一个(例如 Namecheap、GoDaddy 等)。
如果您还没有,请务必创建一个 A 记录,将您的域指向您服务器的公共 IP 地址。 这是必需的,因为 Let's Encrypt 如何验证您是否拥有它为其颁发证书的域。 例如,如果您想获得 example.com
的证书,则该域必须解析到您的服务器,验证过程才能正常工作。 我们的设置将使用 example.com
和 www.example.com
作为域名,因此需要 两个 DNS 记录。
完成所有先决条件后,让我们继续安装 Let's Encrypt 客户端软件 certbot
。
第 1 步 — 安装 Let's Encrypt 客户端
使用 Let's Encrypt 获取 SSL 证书的第一步是在您的服务器上安装 certbot
软件。 Certbot 开发人员提供了一个包含最新版本软件的存储库。 现在让我们将该存储库添加到我们的包管理器中:
sudo add-apt-repository ppa:certbot/certbot
系统将提示您确认添加。 按 ENTER
继续。 然后更新包缓存以获取新的包列表:
sudo apt-get update
最后,安装 certbot
包:
sudo apt-get install certbot
现在我们已经安装了 certbot
,我们准备好获取我们的 SSL 证书。
第 2 步 — 获得证书
Let's Encrypt 通过各种插件提供了多种获取 SSL 证书的方式。 与 另一个教程 中介绍的 Apache 插件不同,大多数插件只会帮助您获得必须手动配置 Web 服务器才能使用的证书。 只获取证书而不安装它们的插件被称为“身份验证器”,因为它们用于验证是否应该向服务器颁发证书。
我们将向您展示如何使用 Standalone 插件来获取 SSL 证书。
验证端口 80 是否打开
Standalone 插件提供了一种非常简单的方式来获取 SSL 证书。 它通过在您的服务器上临时运行一个小型 Web 服务器(默认在端口 80
上)来工作,Let's Encrypt CA 可以连接到该服务器并在颁发证书之前验证您的服务器的身份。 因此,此方法要求端口 80
未使用。 也就是说,如果它使用端口 80
(即 http
),在尝试使用此插件之前。
例如,如果您使用的是 HAProxy,则可以通过运行以下命令来停止它:
sudo service haproxy stop
如果您不确定端口 80
是否正在使用,您可以运行以下命令:
netstat -na | grep ':80.*LISTEN'
如果运行此命令时没有输出,则可以使用 Standalone 插件。
运行 Certbot
现在通过运行以下命令来使用独立插件:
sudo certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d example.com -d www.example.com
系统将提示您输入您的电子邮件地址并同意 Let's Encrypt 服务条款。 之后,将运行 http
挑战。 如果一切成功,certbot
将打印如下输出消息:
Output:IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire on 2017-09-06. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
您需要注意证书的路径和到期日期,这在上面的示例输出中突出显示。
注意: 如果您的域通过 CloudFlare 等 DNS 服务进行路由,您需要暂时禁用它,直到您获得证书。
证书文件
获得证书后,您将拥有以下 PEM 编码文件:
- cert.pem: 你的域名证书
- chain.pem: Let's Encrypt 链证书
- 全链.pem:
cert.pem
andchain.pem
combined - privkey.pem: 你证书的私钥
了解刚刚创建的证书文件的位置很重要,因此您可以在 Web 服务器配置中使用它们。 文件本身放置在 /etc/letsencrypt/archive
的子目录中。 但是,Certbot 会在 /etc/letsencrypt/live/your_domain_name
目录中创建指向最新证书文件的符号链接。
您可以通过运行以下命令检查文件是否存在(替换为您的域名):
sudo ls /etc/letsencrypt/live/your_domain_name
输出应该是前面提到的四个证书文件。
结合 fullchain.pem 和 privkey.pem
当配置 HAProxy 执行 SSL 终止时,它会加密自己和最终用户之间的流量,您必须将 fullchain.pem
和 privkey.pem
组合到一个文件中。
首先,创建将放置组合文件的目录,/etc/haproxy/certs
:
sudo mkdir -p /etc/haproxy/certs
接下来,使用此 cat
命令创建组合文件(将突出显示的 example.com
替换为您的域名):
DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'
使用以下命令安全访问包含私钥的组合文件:
sudo chmod -R go-rwx /etc/haproxy/certs
现在我们已准备好将 SSL 证书和私钥与 HAProxy 一起使用。
第 3 步 — 安装 HAProxy
此步骤涵盖 HAProxy 的安装。 如果它已经安装在您的服务器上,请跳过此步骤。
我们将安装 HAProxy 1.6,它不在默认的 Ubuntu 存储库中。 但是,如果我们使用 PPA,我们仍然可以使用包管理器安装 HAProxy 1.6,使用以下命令:
sudo add-apt-repository ppa:vbernat/haproxy-1.6
更新负载均衡器上的本地包索引并通过键入以下命令安装 HAProxy:
sudo apt-get update sudo apt-get install haproxy
HAProxy 现在已安装,但需要进行配置。
第 4 步 — 配置 HAProxy
本节将向您展示如何使用 SSL 设置配置基本 HAProxy。 它还介绍了如何配置 HAProxy 以允许我们自动更新 Let's Encrypt 证书。
在文本编辑器中打开 haproxy.cfg
:
sudo nano /etc/haproxy/haproxy.cfg
在接下来的几个部分中编辑它时,保持这个文件打开。
全局部分
让我们在 global
部分下添加一些基本设置。
您要做的第一件事是将 maxconn 设置为合理的数字。 这会影响 HAProxy 允许的并发连接数,这会影响 QoS 并防止您的 Web 服务器因尝试服务过多请求而崩溃。 您将需要使用它来找到适合您环境的方法。 将以下行(使用您认为合理的值)添加到 global 部分:
haproxy.cfg — 1 的 7
maxconn 2048
接下来,添加此行,以配置生成的临时 DHE 密钥的最大大小:
haproxy.cfg — 2 个,共 7 个
tune.ssl.default-dh-param 2048
默认部分
在 defaults 部分下添加以下行:
haproxy.cfg — 3 个,共 7 个
option forwardfor option http-server-close
forwardfor 选项将 HAProxy 设置为向每个请求添加 X-Forwarded-For
标头,而 http-server-close
选项通过关闭连接但保持保持活动状态来减少 HAProxy 与用户之间的延迟。
前端部分
现在我们准备好定义我们的 frontend
部分。
我们要添加的第一件事是处理传入 HTTP 连接的前端,并将它们发送到默认后端(我们将在稍后定义)。 在文件的最后,让我们添加一个名为 www-http 的前端。 请务必将 haproxy_public_IP
替换为您的 HAProxy 服务器的公共 IP 地址:
haproxy.cfg — 4 个,共 7 个
frontend www-http bind haproxy_www_public_IP:80 reqadd X-Forwarded-Proto:\ http default_backend www-backend
接下来,我们将添加一个前端来处理传入的 HTTPS 连接。 在文件末尾,添加一个名为 www-https 的前端。 请务必将 haproxy_www_public_IP
替换为您的 HAProxy 服务器的公共 IP。 此外,您需要将 example.com
替换为您的域名(应该对应于您之前创建的证书文件):
haproxy.cfg — 5 个,共 7 个
frontend www-https bind haproxy_www_public_IP:443 ssl crt /etc/haproxy/certs/example.com.pem reqadd X-Forwarded-Proto:\ https acl letsencrypt-acl path_beg /.well-known/acme-challenge/ use_backend letsencrypt-backend if letsencrypt-acl default_backend www-backend
此前端使用 ACL (letsencrypt-acl
) 将 Let's Encrypt 验证请求(针对 /.well-known/acme-challenge
)发送到 letsencrypt-backend
后端,这将使我们能够在不停止 HAProxy 的情况下更新证书服务。 所有其他请求将被转发到 www-backend
,它是为我们的 Web 应用程序或站点提供服务的后端。
后端部分
完成前端配置后,通过添加以下行来添加 www-backend
后端。 请务必将突出显示的单词替换为您的 Web 服务器的相应私有 IP 地址(调整 server
行的数量以匹配您拥有的后端服务器数量):
haproxy.cfg — 6 个,共 7 个
backend www-backend redirect scheme https if !{ ssl_fc } server www-1 www_1_private_IP:80 check server www-2 www_2_private_IP:80 check
此后端接收的任何流量都将通过 HTTP(端口 80)在其 server
条目之间进行平衡。
最后,通过添加这些行来添加 letsencrypt-backend
后端
haproxy.cfg — 7 个,共 7 个
backend letsencrypt-backend server letsencrypt 127.0.0.1:54321
此后端仅处理用于证书请求和续订的 Let's Encrypt ACME 质询,将流量发送到端口 54321
上的 localhost。 当我们更新 Let's Encrypt SSL 证书时,我们将使用此端口而不是 80
和 443
。
现在我们准备启动 HAProxy:
sudo service haproxy restart
注意: 如果您在使用 haproxy.cfg
配置文件时遇到问题,请查看 这个 GitHub Gist 示例。
Let's Encrypt TLS/SSL 证书现已到位,我们已准备好设置自动续订脚本。 此时,您应该通过在 Web 浏览器中访问您的域来测试 TLS/SSL 证书是否有效。
第 5 步 — 设置自动续订
Let's Encrypt 证书的有效期仅为 90 天,因此自动续订过程非常重要。
确保您的证书不会过时的一种实用方法是创建一个 cron 作业,该作业将自动为您处理续订过程。 cronjob 将每天运行 certbot
并在证书到期后三十天内更新证书。 certbot
也将在任何成功续订后运行一个特殊的 renew-hook
脚本。 我们将使用这个更新脚本来更新我们组合的 .pem
文件并重新加载 haproxy。
现在让我们创建该脚本,然后对其进行测试。
创建续订脚本
在 /usr/local/bin
中以 root 的身份打开一个新文件:
sudo nano /usr/local/bin/renew.sh
这将是一个新的空白文本文件。 粘贴以下简短脚本,确保使用您自己的更新突出显示的域名:
#!/bin/sh SITE=example.com # move to the correct let's encrypt directory cd /etc/letsencrypt/live/$SITE # cat files to make combined .pem for haproxy cat fullchain.pem privkey.pem > /etc/haproxy/certs/$SITE.pem # reload haproxy service haproxy reload
保存并关闭文件。 此脚本移动到正确的 Let's Encrypt 目录,运行 cat
命令将两个 .pem
文件合并为一个,然后重新加载 haproxy。
接下来,使脚本可执行:
sudo chmod u+x /usr/local/bin/renew.sh
然后运行脚本:
sudo /usr/local/bin/renew.sh
它应该运行没有错误。 你会看到一些关于重新加载 haproxy 的输出。 接下来,我们将更新 Certbot 并将其配置为运行此更新脚本。
更新 certbot 配置
我们将用于更新证书的 certbot renew
命令读取我们第一次运行 certbot
时创建的配置文件。 我们需要打开这个文件并更新 certbot
用来运行其独立 http 服务器的端口,这样它就不会与 haproxy 冲突(它已经在监听端口 80 和 443)。 在文本编辑器中打开配置文件:
sudo nano /etc/letsencrypt/renewal/example.com.conf
我们需要更改 http01_port
行,所以它看起来像这样:
example.com.conf
http01_port = 54321
保存并关闭文件。 现在测试更新过程,指定 --dry-run
所以我们实际上不更新任何东西:
sudo certbot renew --dry-run
Certbot 将在端口 54321 上侦听更新挑战,haproxy 将代理从端口 80 到 54321 的请求。
创建一个 Cron 作业
接下来,我们将编辑 crontab 以创建一个新作业,该作业将每天运行 certbot renew
命令。 要为 root 用户编辑 crontab,请运行:
sudo crontab -e
将以下内容添加到文件底部:
crontab 条目
30 2 * * * /usr/bin/certbot renew --renew-hook "/usr/local/bin/renew.sh" >> /var/log/le-renewal.log
保存并退出。 这将创建一个新的 cron 作业,该作业将在每天凌晨 2:30 执行 certbot renew
命令。 该命令产生的输出将通过管道传送到位于 /var/log/le-renewal.log
的日志文件。 如果证书实际更新,--renew-hook
脚本将运行以创建组合 PEM 文件并重新加载 haproxy
。
结论
就是这样! HAProxy 现在使用免费的 Let's Encrypt TLS/SSL 证书来安全地提供 HTTPS 流量。