近期在工作中用到了SSL证书,在开发调试过程中遇到了一系列的问题,对其中的一些问题进行总结。
1.创建自签名SSL证书
linux环境下使用系统自带的OpenSSL生成自签名SSL证书,支持多个域名及IP地址,适合内网或无域名的情况。
openssl genrsa -out my.key 2048
openssl rsa -in my.key -out my.key
openssl req -new -key my.key -out my.csr -config san_dev.cnf -extensions req_ext -days 720
openssl x509 -req -sha256 -in my.csr -signkey my.key -extfile san_dev.cnf -extensions req_ext -out my.crt -days 720
openssl pkcs12 -inkey my.key -in my.crt -export -out my.pfx -name my
这里仅是一个示例,创建自签名SSL证书的文章有很多,不再详细赘述。
2.使用自签名证书的利与弊
最大的好处就是免费并且支持IP地址绑定,适合内部局域网和开发环境,可以根据自己的需要随意创建自签名证书,证书信息和有效期都可以不受限制。商用SSL证书肯定是可以相信的,防护能力越强的SSL证书价格也是越贵的,大部分服务商都提供了免费SSL证书的申请,但都需要绑定域名。
自签名证书的弊端确实不少,主要集中在安全性上。由于是自签名的,想怎么改就怎么改,没有限制,就有很大的安全隐患。Chrome浏览器从某个特定版本之后就不再支持自签名证书了,使用上会造成不小的影响。自签名证书的有效期可以设置很长的时间,5年10年都可以,只要有人有心花足够的时间就可以将其破解,而商用SSL证书的有效期一般1到2年,降低了破解的概率。此外之前OpenSSL还爆出多个漏洞,比较有名的就是HeartBleed(心脏流血)漏洞。听这名字就感觉很严重,攻击者可以利用这个漏洞获取大量用户信息,事实上也造成了很大的影响。虽然这个漏洞在后续版本中被修复,但自签名证书的安全隐患依然存在。
此外,国内许多安全测评认证机构对于自签名证书的使用仍持保留态度,如果你的项目可能会面临等级保护测评、国家密码测评、信息安全测评等,还是要慎重考虑。
总的来说,使用自签名证书要根据实际需求,如果你的应用是面向互联网提供服务的,还是尽量不用自签名证书了。自己在内部网络或者开发环境做测试使用自签名证书倒是不错的选择。
3.使用SSL证书带来的性能影响
从原理上来看,HTTPS协议比HTTP增加了协议交互和加解密的过程。与HTTP的三次握手相比,HTTPS最多会增加7个网络RTT(round trip time),而加解密过程也肯定是需要时间的,所以同等网络条件下,HTTPS肯定是要慢于HTTP的。 如果数据量不大而且并发量不高,改成HTTPS后带来的性能影响可以忽略不计,在用户体验上并没有很大的差异。但如果数据量比较大或者并发量比较高,带来的影响可能就是肉眼可见的访问速度变慢。对于图片、视频等的访问还是有影响的,当然也不能一概而论,还是要看具体情况的。
4.HTTP与HTTPS的相互访问
安装完SSL证书后,发现一连串的问题接踵而至,这就涉及到HTTP与HTTPS的相互调用了。
HTTP访问HTTP当然没有问题,HTTPS访问HTTPS也没问题,HTTP访问HTTPS还是没有问题,最麻烦的就是HTTPS访问HTTP了。加解密的时间长短取决于密钥加密长度,使用1024、2048、4096位加密密钥的加解密时间会进一步增大。
4.1.HTTP重定向至HTTPS
如果SSL证书是在业务应用上线之后才添加的,通知客户修改原有的访问地址显然不太现实,那么就可以将原有的HTTP地址重定向至新的HTTPS地址。大部分Web服务器都提供了这个功能,以Nginx为例:
server {
listen 80;
server_name my.domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name my.domain.com;
[....]
}
注意:SSL证书默认绑定443端口,但并不是只能绑定443端口,其他端口也能用,就好像Web应用默认绑定的是80端口但不是只能绑定80端口一样。
4.2.HTTPS访问HTTP
理论上HTTPS直接访问HTTP请求就会有错误提示,所以只能想办法解决,可以把被访问的HTTP也改成HTTPS,也可以使用反向代理访问HTTP(曲线救国),常用的解决方式有这么几种:
- 如果在https网站中请求的http资源本身就支持https,可以在html页面加入,浏览器在解析请求的时候会自动把http请求转化为https请求。
- 如果如果在https网站中请求的http资源本身不支持https,可以把https网站换成http协议。(这句权当是废话)
- 如果如果在https网站中请求的http资源本身不支持https,但是请求的http资源在属于自己的服务上(非第三方服务),并且不考虑改为https协议带来的性能问题,可以把要请求的http资源协议改为https。
- 如果在https网站中请求的http资源本身不支持https,并且这些被请求的http资源都是静态资源(比如js、css等),可以考虑把这些资源下载下来放到现有的https服务器中,也可以寻找https协议的资源,很多免费的cdn服务都同时提供了https和http协议的静态资源。
- 如果在https网站中请求的http资源是动态资源(比如请求http接口),且是第三方接口(自己无法变更这个第三方接口是http协议的事实),可以用nginx代理的方式。
server {
location /httpresource {
proxy_pass http://XXXXXXX.XXX.XX/;
}
}
- 如果上面的方法都还不行,那么就干掉提出这个需求的人(当然也是不现实了)。
5.netcore开发调试中使用SSL
在开发调试中也有很多方式来实现SSL证书的启用,不必非要在生产环境中验证。
5.1.net core项目配置SSL
.net core项目可以在启动项中配置启用SSL证书。这是在使用自带的Kestrel托管的情况下。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
同时需要在配置文件中配置SSL证书相关选项。
{
"Kestrel": {
"Endpoints": {
"MyHttpsEndpoint": {
"Url": "https://localhost:5001",
"SslProtocols": ["Tls12", "Tls13"],
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
}
}
}
5.2.IISExpress调试启用SSL
如果项目使用IISExpress编译测试,可以在创建项目时勾选“启用SSL”。 同样也可以在项目创建后修改项目属性。 两处修改的效果是一样的,都是使用的IISExpress内置的SSL证书,适用于localhost调试。
5.3.Ocelot网关使用SSL
有资料显示Ocelot网关的上行路由UpStream不支持HTTPS,下行路DownStream由支持HTTPS。配置文件中也提供了忽略HTTPS验证错误的选项。
"DangerousAcceptAnyServerCertificateValidator": true
|