Jimliu


一只刚上路的前端程序猿


OS X本地搭建https (译)

原文地址: How to set up stress-free SSL on an OS X development machine
Raw


在Web开发中降低复杂性(读取:压力)的最佳方法之一是最小化您的开发和生产环境之间的差异。在尝试在本地计算机和生产环境中统一SSL方法后,我找到了一个工作流程,使得协议在所有环境保持相同。

大多数工作流程做出以下妥协:

在服务器环境使用https,在开发环境使用http
这是非常烦人的,因为它使环境不一致,并且协议选择泄漏到堆栈。例如,当使用cookie的安全标志时,Web应用程序需要了解底层协议。如果你没有得到这个,你的HTTP开发服务器将无法读取它写的cookies,或者更糟糕的是,你的HTTPS生产服务器可以通过不安全的连接传递敏感的cookie。

在本地使用生产环境SSL证书
SSL凭证不应轻易传递,理想情况下应仅存在于被认证的机器上。此外,即使使用通配符证书,提出一个方案,将开发主机和生产主机放在同一命名空间下有一些奇怪的情况(如果生产应用程序是从myproject.com提供,开发应用程序从哪里提供? )

完全放弃HTTPS
如果在2013年,这是没错的。

所以我的方法是分一下四步:

1.解决所有开发工作的顶级域名;
2.为每个项目创建通配符SSL证书;
3.告诉OS X信任证书,避免HTTPS警告;
4.使用https;

下面我们开始

如果你还没有安装homebrew那么请先安装

1
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

解决域名解析到项目

将域名解析到本地最常用的方法是修改hosts,可是你却需要给每一个你正在开发的项目添加一条解析记录
先做一点小工作,我们就可以给我们所有的项目绑定域名而不去动我们的hosts。

Dnsmasq一个轻量级的DNS转发器,可以帮我们完成这些工作。

1
2
3
4
5
brew install dnsmasq
mkdir -pv $(brew --prefix)/etc
sudo cp -v $(brew --prefix dnsmasq)/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo mkdir -pv /etc/resolver

一旦安装并运行,我们需要选择我们想要解决的TLD到我们的本地。 OS X保留.local TLD,许多开发人员使用.dev,但我喜欢使用名称作为TLD的想法,以便在同一项目的其他开发人员的上下文中更容易地推理我的本地环境。所以我要让Dnsmasq在本地解析以我的OS X用户ID结尾的所有主机(也称为短名称,以及在终端中键入whoami时得到的结果)。因为我的用户id是jed,这意味着从apple.jed到zebras.jed到apple.zebras.jed的一切将解析为127.0.0.1。

所有以下shell脚本假设您使用您的用户标识作为您的顶级域名,但感觉通过替换$(whoami)与您选择的TLD相应地更改它们。

1
2
echo "address=/.$(whoami)/127.0.0.1" | sudo tee -a $(brew --prefix)/etc/dnsmasq.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/$(whoami)

现在我们需要验证我们安装的Dnsmasq是否生效。

1
2
3
cd /Applications
sleep 1 && open "http://some.domain.$(whoami):9520" &
python -m SimpleHTTPServer 9520

这应该打开一浏览器,显示您的应用程序文件夹的内容,如下所示:

image

不过如果出错,浏览器会告诉我们找不到DNS:

error
如果出现这种情况,我们需要去重启机器,或者检查我们的安装步骤。

为每个项目创建通配符SSL证书

现在我们的DNS配置已经生效,下一步就是为域名创建通配符证书。

首先,我们创建一个与我们项目名称相同的文件夹。

1
mkdir ~/Desktop/myproject && cd $_

接下来,让我们创建一个临时配置文件,使用openssl来创建我们的证书。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cat > openssl.cnf <<-EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = *.${PWD##*/}.$(whoami)
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.${PWD##*/}.$(whoami)
DNS.2 = ${PWD##*/}.$(whoami)
EOF

openssl req \
-new \
-newkey rsa:2048 \
-sha1 \
-days 3650 \
-nodes \
-x509 \
-keyout ssl.key \
-out ssl.crt \
-config openssl.cnf

rm openssl.cnf

现在我们在项目目录中有两个文件:ssl.key,用于签名证书的私钥和证书本身的ssl.crt。

到这时候我们已经基本做完了配置本地https的所有工作,不过这里还有一个问题。
problem

我们尝试通过HTTPS从此域提供的任何内容获得IMMA-LET-YOU-FINISHed通过类似上面的可怕消息,警告我们所提供的证书不受信任。这个消息因浏览器而异,您可能会想继续前进,忽略它,但这不是一个好习惯,而且很可能导致开发复杂性。

避免https警告,我们需要告诉OS X信任这个证书

由于我们的证书是自签名的,因此当我们的HTTPS网站使用它时,我们会收到警告。我们需要使用Keychain Access来告诉OS X。
open

1.在Keychain Access打开证书

1
open /Applications/Utilities/Keychain\ Access.app ssl.crt

2.点击 Don’t Trust.

3.选择新导入的证书,它应显示在证书列表的底部,然后单击[i]按钮.

4.在弹出窗口中,单击信任左侧的▶按钮,并选择使用此证书时始终信任.

使用简单的HTTPS

现在OS X知道我们的自签名证书是合法的,让我们启动一个HTTPS服务器,以确保一切正常。你可以使用Apache或Nginx或任何你喜欢的,但在这里我们将使用nodejs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sleep 1 && open "https://myproject.$(whoami):8443" &
sleep 1 && open "https://subdomain.myproject.$(whoami):8443" &

node <<-EOF
var https = require("https")
var fs = require("fs")

var options = {
key: fs.readFileSync("ssl.key"),
cert: fs.readFileSync("ssl.crt")
}

var server = https.createServer(options, function(req, res) {
res.writeHead(200, {"Content-Type": "text/plain"})
res.end("It worked!\n")
})

server.listen(8443, console.log)
EOF

就像你看到的,顶级域名和子域名都生效。

success
success1

请注意,这将满足Chrome和Safari,但由于Firefox不会从OS X继承相同的Keychain Access,它会告诉你证书是不受信任的。在这种情况下,单击我了解风险,然后添加例外…,然后提示时确认安全异常。

完:)

最近的文章

我的2016

2016过得好快感觉刚刚写完2015总结,年龄越大时间越快。(内附音乐) …

于  闲扯, 随笔 继续阅读
更早的文章

ubuntu配置服务端 shadowsock

这两天一直在折腾服务器,给域名加https,升级http2。然后就手贱的重置了好几次服务器,每次都去配置shadowsocks。所以写下来记录一下配置。 …

于  梯子 继续阅读