使用 Let's Encrypt 和 Nginx 从同一服务器托管多个 HTTPS 域名
2017-02-17 09:15
309 查看
现在网站越来越需要 HTTPS,而这正是顺应了发展趋势。Chrome 现已将带有密码或信用卡字段的 HTTP 网站明确标记为“不安全的”。在过去的一年里,我一直在将我的客户端网站切换到 HTTPS 上。事实证明,作为系统管理员的工作总是这样做,也存在与此相关的隐藏的挑战。
在我们深入下面的细节之前,我们先弄清写这篇文章的目的。
从同一服务器上托管多个 HTTPS 网站的问题与 HTTPS 连接的建立方式有关。安全的(读取:不是pwned)HTTPS 是在 TLS 上运行。当 TLS 连接建立时,我们倾向于认为它是与网站构建的。在技术上这是不正确的。 TLS 连接是连接到特定的 IP 地址。一旦你连接到那个 IP,服务器会假定这就是你想访问的网站。这意味着您不能在同一 IP 地址的主机上托管的多个 HTTPS 网站。
SNI(服务器名称标识)是一项在 21 世纪初期就被引入的协议,引入的目的就是为了解决这个问题。它是一种用于在浏览器设置一个 TLS 连接时向网页服务器发送一个域名的方法。通过在初次握手阶段传入域名,网页服务器就可以知道你想要访问的是哪一个域,从而让其为正确的那一个提供服务。
不过尽管其已经得到了广泛的支持,但也有不被支持的情况。我自己就曾在处理对 SNI 的依赖时掉进了移动端浏览器的坑。从另外一方面来看,IP 地址是廉价的,好像是 1 $/月,或者还要更便宜。因此你索性可以为你的 HTTPS 站点单独弄一个 IP,这样做所避免掉的一些在终端/浏览器组合上遇到的头疼事儿,花费的代价可能百倍不止。
对于初学者而言,首先需要给每一个你准备从同一台服务器上托管在 HTTPS 上的域名获取一个 IP。大多数像 Linode 以及 AWS 这样的托管平台都提供了为任何东西添加 IP 的能力。
一旦你有那些 IP,你就需要确认你的 web 服务器识别输入他们。如果你开始运行 ping,你就可能看到下面的输出:
$ ping you.new.ip.addr
PING you.new.ip.addr (you.new.ip.addr): 56 data bytes
Request timeout for icmp_seq 0 Request timeout for icmp_seq 1
...这是因为服务器忽略了没有配置的
IP 地址。要让服务器看到那些输入的 IP,我们需要更新网络接口。这听起来很可怕,但实际上并没有那么坏。我们开始编辑 /etc/network/interfaces 这个文件。 你大概会有一个庞大的清单是关于你的服务器所需要存储的 IP 地址的。
# Something like this probably already exists
auto eth0
iface eth0 inet static
address X.X.X.X/24
gateway X.X.X.1
dns-nameservers 8.8.8.8 8.8.4.4
dns-search your.dns.info
dns-options rotate这里,我们将会在
eth0 块下,添加新 IP 地址。
# Add support for our new IP addresses
iface eth0:1 inet static
address Y.Y.Y.Y/24
dns-nameservers 8.8.8.8 8.8.4.4
iface eth0:2 inet static
address Z.Z.Z.Z/24
dns-nameservers 8.8.8.8 8.8.4.4
尽管我在之前已经说的很详细了,但是在这里我还是想再提一点。使用 Let's Encrypt,我们有几种选择来取得证书。
# Get a cert for a domain (include all subdomains that apply to this file path, including www)
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'mysite.com,www.mysite.com' -w /var/www/mysite/public
# Get a cert for a domain and subdomain with different filesystem paths
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'mysite.com,www.mysite.com' -w /var/www/mysite/public \
-d 'blog.mysite.com' -w /var/www/mysite_blog/
# Get a cert for an entirely new domain name
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'newsite.com,www.newsite.com' -w /var/www/newsite/public
接下来,我们需要做一点 HTTPS 配置的修改,目的是使 nginx 从 域名+端口 认证方法切换到一种 ip+端口 的认证系统。这是在我们 HTTPS 服务器模块中改变监听(listen)指令最简单的配置方式 (并且在我的使用中一直没有问题) 。
最后,当我们在服务器上维护多个站点时,我们真的应该依赖某种方法自动更新我们的 Let's Encrypt 证书。没人愿意每三个月去手动更新一次。很幸运,Let's Encrypt 官方提供了一段代码来处理这个问题 ,而我们只需要创建一个计划任务,采用 cron 定时任务命令定期自动运行(这段代码) 。现在,我们创建一个文件 /etc/letsencrypt/auto_renew.sh。把下面的代码添加进来,你也可以自己做些修改,实现你想要的功能。
现在将以上的脚本添加到计划任务, 执行 sudo crontab -e 添加下面一行代码:
技术革新领域正在飞速发展,尽管这种发展在用户的隐私和安全方面并无助益。虽然没有明确言明,但是用户变成客户的过程在交互中已经隐含了双方的信任。不管是作为开发人员、工程师还是系统管理员,我们都有责任保障用户权益。
保障用户用 app 发出的任何连接都安全可靠是最佳方案。显然,没有一定程度上安全的连接难以轻松实现。Let's Encrypt 巧妙降低了进入开发领域的壁垒,成为开发人员亟需掌握的一步。由此可知,所有以避免为客户网站提供安全支持为目的的借口都是疏忽和无知。
希望本文对解决问题有所助益。
总结:如果你对从一个服务器托管多个 HTTPS 域名一无所知,使用 Let's Encrypt 和 Nginx 吧!轻松解决问题。
HTTPS 简述
在我们深入下面的细节之前,我们先弄清写这篇文章的目的。从同一服务器上托管多个 HTTPS 网站的问题与 HTTPS 连接的建立方式有关。安全的(读取:不是pwned)HTTPS 是在 TLS 上运行。当 TLS 连接建立时,我们倾向于认为它是与网站构建的。在技术上这是不正确的。 TLS 连接是连接到特定的 IP 地址。一旦你连接到那个 IP,服务器会假定这就是你想访问的网站。这意味着您不能在同一 IP 地址的主机上托管的多个 HTTPS 网站。
进入(和退出)SNI
SNI(服务器名称标识)是一项在 21 世纪初期就被引入的协议,引入的目的就是为了解决这个问题。它是一种用于在浏览器设置一个 TLS 连接时向网页服务器发送一个域名的方法。通过在初次握手阶段传入域名,网页服务器就可以知道你想要访问的是哪一个域,从而让其为正确的那一个提供服务。不过尽管其已经得到了广泛的支持,但也有不被支持的情况。我自己就曾在处理对 SNI 的依赖时掉进了移动端浏览器的坑。从另外一方面来看,IP 地址是廉价的,好像是 1 $/月,或者还要更便宜。因此你索性可以为你的 HTTPS 站点单独弄一个 IP,这样做所避免掉的一些在终端/浏览器组合上遇到的头疼事儿,花费的代价可能百倍不止。
添加 IP 地址
对于初学者而言,首先需要给每一个你准备从同一台服务器上托管在 HTTPS 上的域名获取一个 IP。大多数像 Linode 以及 AWS 这样的托管平台都提供了为任何东西添加 IP 的能力。一旦你有那些 IP,你就需要确认你的 web 服务器识别输入他们。如果你开始运行 ping,你就可能看到下面的输出:
$ ping you.new.ip.addr
PING you.new.ip.addr (you.new.ip.addr): 56 data bytes
Request timeout for icmp_seq 0 Request timeout for icmp_seq 1
...这是因为服务器忽略了没有配置的
IP 地址。要让服务器看到那些输入的 IP,我们需要更新网络接口。这听起来很可怕,但实际上并没有那么坏。我们开始编辑 /etc/network/interfaces 这个文件。 你大概会有一个庞大的清单是关于你的服务器所需要存储的 IP 地址的。
# Something like this probably already exists
auto eth0
iface eth0 inet static
address X.X.X.X/24
gateway X.X.X.1
dns-nameservers 8.8.8.8 8.8.4.4
dns-search your.dns.info
dns-options rotate这里,我们将会在
eth0 块下,添加新 IP 地址。
# Add support for our new IP addresses
iface eth0:1 inet static
address Y.Y.Y.Y/24
dns-nameservers 8.8.8.8 8.8.4.4
iface eth0:2 inet static
address Z.Z.Z.Z/24
dns-nameservers 8.8.8.8 8.8.4.4
如何获得证书
尽管我在之前已经说的很详细了,但是在这里我还是想再提一点。使用 Let's Encrypt,我们有几种选择来取得证书。# First we need the Let's Encrypt bin sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt有了 Let's EncryptOnce 软件包之后,我们可以用以下几种方法注册我们的域名。
# Get a cert for a domain (include all subdomains that apply to this file path, including www)
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'mysite.com,www.mysite.com' -w /var/www/mysite/public
# Get a cert for a domain and subdomain with different filesystem paths
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'mysite.com,www.mysite.com' -w /var/www/mysite/public \
-d 'blog.mysite.com' -w /var/www/mysite_blog/
# Get a cert for an entirely new domain name
/opt/letsencrypt/letsencrypt-auto certonly --webroot \
-d 'newsite.com,www.newsite.com' -w /var/www/newsite/public
更新 nginx 服务器
接下来,我们需要做一点 HTTPS 配置的修改,目的是使 nginx 从 域名+端口 认证方法切换到一种 ip+端口 的认证系统。这是在我们 HTTPS 服务器模块中改变监听(listen)指令最简单的配置方式 (并且在我的使用中一直没有问题) 。server { # Old method: # listen 443 ssl; # Ip-based: listen X.X.X.X:443 ssl; server_name: mysite.com www.mysite.com; # ... }
自动续期证书
最后,当我们在服务器上维护多个站点时,我们真的应该依赖某种方法自动更新我们的 Let's Encrypt 证书。没人愿意每三个月去手动更新一次。很幸运,Let's Encrypt 官方提供了一段代码来处理这个问题 ,而我们只需要创建一个计划任务,采用 cron 定时任务命令定期自动运行(这段代码) 。现在,我们创建一个文件 /etc/letsencrypt/auto_renew.sh。把下面的代码添加进来,你也可以自己做些修改,实现你想要的功能。#!/bin/sh # This script renews all the Let's Encrypt certificates with a validity < 30 days if ! /opt/letsencrypt/letsencrypt-auto renew > /var/log/letsencrypt/renew.log 2>&1 ; then echo Automated renewal failed: cat /var/log/letsencrypt/renew.log exit 1 fi nginx -t && nginx -s reload
现在将以上的脚本添加到计划任务, 执行 sudo crontab -e 添加下面一行代码:
@daily /etc/letsencrypt/auto_renew.sh
隐私和安全问题
技术革新领域正在飞速发展,尽管这种发展在用户的隐私和安全方面并无助益。虽然没有明确言明,但是用户变成客户的过程在交互中已经隐含了双方的信任。不管是作为开发人员、工程师还是系统管理员,我们都有责任保障用户权益。保障用户用 app 发出的任何连接都安全可靠是最佳方案。显然,没有一定程度上安全的连接难以轻松实现。Let's Encrypt 巧妙降低了进入开发领域的壁垒,成为开发人员亟需掌握的一步。由此可知,所有以避免为客户网站提供安全支持为目的的借口都是疏忽和无知。
希望本文对解决问题有所助益。
总结:如果你对从一个服务器托管多个 HTTPS 域名一无所知,使用 Let's Encrypt 和 Nginx 吧!轻松解决问题。
相关文章推荐
- 免费HTTPS证书不是梦!在Ubuntu(Linux)的VPS上使用Let's Encrypt为一堆域名申请并安装HTTPS证书
- nginx 使用 let's encrypt 配置https
- 网站升级HTTPS,免费SSL证书Let’s Encrypt安装使用教程:Apache和Nginx配置方法
- Let's Encrypt: 为CentOS/RHEL 7下的nginx安装https支持-具体案例
- OPS: Https配置 Let's Encrypt SSl 使用
- 使用let's encrypt为你的Ubuntu14+nginx网站保驾护航!
- 使用Let`s encrypt 免费的https 证书
- 使用Go和Let's Encrypt证书部署HTTPS
- centos7 nginx+tomcat配置https 安装免费SSL Let’s Encrypt
- 网站http改https Let’s Encrypt 安装 续期教程 免费ssl证书Let’s Encrypt使用教程Certbot
- 生成线上用https证书,支持通配符和多域名,初学Let’s Encrypt用于IIS,纯本地手动
- Linux CentOS 7 下 Nginx 安装使用 Let’ s Encrypt 证书的完整过程
- Let's Encrypt: 为CentOS/RHEL 7下的nginx安装https支持-具体案例
- 使用 Let's Encrypt 生成免费SSL证书 Https
- 全民https时代,Let's Encrypt免费SSL证书的申请及使用(Tomcat版)
- Let's Encrypt 使用教程,免费的SSL证书,让你的网站拥抱 HTTPS
- 使用 Let's Encrypt(Certbot) 配置 HTTPS
- docker使用Let’s Encrypt协议构建免费https协议
- IIS 使用Let's Encrypt并配置HTTP跳转HTTPS
- 使用 let's encrypt certbot部署https网站