言成言成啊 | Kit Chen's Blog

SSL证书

发布于2024-11-09 19:20:07,更新于2024-11-17 22:55:22,标签:java  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

之前写的HTTP反向代理工具,在实际使用时,碰到反代失败的问题。跟踪了一下,才发现是由于对方使用了自签名SSL证书,导致发起HTTP请求时,验证失败。因此简单记录一下。

针对该问题的复现,从两个方面来展开

  1. 理解SSL
  2. 忽略SSL

一、理解SSL

1.1 HTTPS与SSL

SSL是用于加密传输的协议,也是最初的加密标准,目前已被TLS取代,但由于历史原因,大家还是会称为SSL。

HTTPS是HTTP上实现加密传输的协议,依赖SSL/TLS来确保安全性。

从不求甚解的角度来理解,HTTPS=HTTP+SSL/TLS

1.2 证书分类

SSL常见的证书分类有两种

  • CA证书
  • 自签名证书

这两者的区别如下

特性自签名证书CA证书
签发机构由证书持有者自己签发由受信任的证书颁发机构(CA)签发
信任级别默认不被浏览器或操作系统信任,需手动安装信任被大多数浏览器和操作系统默认信任
身份验证无身份验证,持有者自行生成证书CA会对证书持有者进行身份验证
安全性安全性较低,可能被伪造或滥用高安全性,通过身份验证保障证书真实性
应用场景适用于开发、测试和内部网络适用于生产环境和面向互联网的服务
成本免费需要付费,费用根据证书类型和CA机构不同而异
浏览器警告会弹出“不安全连接”警告不会弹出警告,用户信任度高
管理复杂度管理简单,但不适合公开环境管理较复杂,需要向CA申请和续期

互联网服务使用的一般都是CA证书,由于操作系统已经内置了一系列根证书,当访问一个使用CA签发证书的HTTPS网站时,就不会出现“不安全连接”的警告。

而自签名证书,由于操作系统缺少对其的信任,访问就会被拦截了。此时服务提供方,需要给调用方提供自签名证书,以便调用方可以信任该连接。

1.3 OpenSSL生成自签名证书

1.3.1 扩展名说明

像我购买的CA证书,部署到Nginx时,一般都是.pem.key文件。但在自己生成证书的过程中,发现还有.crt文件。直观的感受是,这些扩展名特别的混乱。经过查阅资料,下面简单记录这些扩展名的区别。

  • crt: 存储证书(公钥)。该证书可提供给第三方使用,比如HTTPS客户端
  • key: 私钥。该私钥文件只应给服务提供者使用。
  • csr: 向证书颁发机构申请签署密钥的请求,不包含密钥本身。
  • pem: 基于Base64编码的文本格式。它可以是上述任何文件。
  • der: 基于二进制编码的文本格式。它可以是上述任何文件。

参考

ssl - Difference between pem, crt, key files - Stack Overflow

Difference between .pem and .crt and how to use them - Help - Let’s Encrypt Community Support

1.3.2 自签名证书

下面使用OpenSSL生成自签名的公钥和私钥证书。

1
2
3
4
5
6
7
8
9
10
11
12
# 生成一个2048位的RSA私钥,并保存到private.key文件中
openssl genrsa -out private.key 2048

# 根据私钥,生成一个证书签名请求
openssl req -new -key private.key -out request.csr

# X.509是SSL/TLS中最常用的公钥证书标准
# 通过私钥和证书签名请求,生成一个时效为365天的证书
openssl x509 -req -days 365 -in request.csr -signkey private.key -out public.pem

# 验证证书内容
openssl x509 -in public.pem -noout -text

二、忽略SSL

2.1 服务端部署证书

2.1.1 Nginx

以Nginx为例,部署证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

server {
listen 443 ssl;
server_name 10.0.0.1;

ssl_certificate /usr/local/nginx/conf/cert/public.pem;
ssl_certificate_key /usr/local/nginx/conf/cert/private.key;

location / {
root /usr/local/nginx/html;
index index.html;
}
}
}

2.1.2 Vertx

使用Java中的Vertx 4.5.10版本开启HTTPServer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions()//使用自签名证书开启ssl
.addCertPath("/usr/local/nginx/conf/cert/public.pem")
.addKeyPath("/usr/local/nginx/conf/cert/private.key");
Future<HttpServer> serverFuture = vertx.createHttpServer(new HttpServerOptions()
.setSsl(true)
.setKeyCertOptions(pemKeyCertOptions))
//注册路由
.requestHandler(router)
.listen(port);
serverFuture.onComplete(re -> {
if (re.succeeded()) {
log.info("http server started on port {}", port);
} else {
log.error("http server failed to start", re.cause());
}
});

2.2 客户端忽略校验

2.2.1 CURL

curl忽略ssl校验比较简单,添加-k参数即可。

1
curl -k "https://10.0.0.10:443"

2.2.2 Apache HttpPClient and OkHttpClient

设置忽略SSL的核心逻辑如下,具体的写法还需根据框架而定。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 信任所有SSL证书,包括CA证书和自签名证书。实现效果类似于`curl -k`
* @see <a href="https://blog.csdn.net/qq_20683411/article/details/142996223">Apache HttpClient 4.3.2 和 4.5.13 - 忽略证书问题_apache 4.3.5 忽略ssl-CSDN博客</a>
*/
public SSLContext trustAllCerts() {
try {
TrustManager[] trustManagers = {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, new SecureRandom());
return sslContext;
} catch (Exception ignore) {

}
return null;
}

public HostnameVerifier getNoopHostnameVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(final String s, final SSLSession sslSession) {
return true;
}

@Override
public final String toString() {
return "NO_OP";
}
};
}
发布:2024-11-09 19:20:07
修改:2024-11-17 22:55:22
链接:https://meethigher.top/blog/2024/ssl-certificate/
标签:java 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏