随着对安全的重视和几大公司的推动,https服务已经成为标配了。出于成本和其他因素的考量,最近需要对后台服务升级到https连接。通常证书的创建需要一个域名,但实际上可以无需域名而绑定ip地址。通过搜索和尝试,搞定:
- 创建CA,签署绑定到ip的服务器证书
我的操作环境是OS X 10.13.6。
创建CA(Certificate Authority)
创建私钥:这里生成长度1024的,你也可以生成更长的;密码要牢记,下面的处理过程中,不止一次会用到
openssl genrsa -out ca-key.pem -des 1024
通过CA私钥生成CSR
openssl req -new -key ca-key.pem -out ca-csr.pem
通过CSR文件和私钥生成CA证书
openssl x509 -req -in ca-csr.pem -signkey ca-key.pem -out ca-cert.pem
服务端证书
为服务器生成私钥
openssl genrsa -out server-key.pem 1024
利用服务器私钥文件服务器生成CSR,其中openssl.cnf格式如下:
openssl req -new -key server-key.pem -config openssl.cnf -out server-csr.pem
openssl.cnf文件示例:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = JS
localityName = Locality Name (eg, city)
localityName_default = WX
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = MyCA
commonName = ee ltd
commonName_max = 64[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names[alt_names]
IP.1 = 127.0.0.1
这一步的确非常重要,我在csdn看到的blog中也提到了添加v3_req,并且在 alt_names下添加了DNS和IP的记录,都没有成功。
注意这里只添加了IP。
通过服务器私钥文件和CSR文件生成服务器证书
openssl x509 -req -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in server-csr.pem -out server-cert.pem -extensions v3_req -extfile openssl.cnf
客户端证书
生成客户端私钥
openssl genrsa -out client-key.pem
利用私钥生成CSR
openssl req -new -key client-key.pem -out client-csr.pem
这一步中,Common Name之类的可以随意填。
生成客户端证书
openssl x509 -req -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in client-csr.pem -out client-cert.pem
测试
为了方便,可以将证书和私钥打包成pfx格式。
打包服务器端证书
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -certfile ca-cert.pem -out server.pfx
打包客户端证书
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -certfile ca-cert.pem -out client.pfx
测试
先修改服务端,服务端使用的Express,在www中修改:
var cnodeOptions = {
//key: fs.readFileSync('./bin/server-key.pem'),
//ca: [fs.readFileSync('./bin/ca-cert.pem')],
//cert: fs.readFileSync('./bin/server-cert.pem'),
pfx:fs.readFileSync('./bin/server.pfx'),
passphrase:'生成pfx时所用的密码',
};
注意:如果不使用pfx的话,就把pfx和passphrase行注释。
然后修改客户端:
var https = require('https');
var fs = require('fs');
var options = {
hostname: "127.0.0.1",
port: 3000,
path: '/https',//'/',
methed: 'GET',
pfx:fs.readFileSync('./client.pfx'),
passphrase:'生成pfx时所用的密码',
agent: false
};
options.agent = new https.Agent(options);
var req = https.request(options, function(res) {
res.setEncoding('utf-8');
res.on('data', function(d) {
console.log(d);
});
});
req.end();
req.on('error', function(e) {
console.log(e);
});
启动服务端,运行客户端,如果能正常请求,就说明证书确认成功了。
在实际开发过程中,我们可以给options添加属性,使得开发过程中对证书不做校验:
rejectUnauthorized: false
或者:
checkServerIdentity: function (host, cert) {
return undefined;
}
但切记不要在生成环境也这么做!
参考说明
在搜索过程中,参考了csdn,cnblog的多篇文章,但对我最有用的还是用Node.js创建自签名的HTTPS服务器。
看来关键字还是得和工作内容相联系,才能找到有用的信息。
名词解释
CA: Certificate Authority
CSR: Certificate Signing Request
Comments