https原理(四)双向实践(java客户端+tcp代理)
本文采用客户端与服务端共用一个密钥对
1
将https代理服务器(三)实践中的mkcert p12分解为一个公钥一个私钥
mac@macdeMacBook mkcert % openssl pkcs12 -clcerts -nokeys -out myhost.com.pem -in myhost.com.p12
Enter Import Password:
MAC verified OK
mac@macdeMacBook mkcert % openssl pkcs12 -nocerts -out myhost.com-key.pem -in myhost.com.p12
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
2 将公钥导入jks
keytool -import -file myhost.com.pem -keystore myhost.com-client.jks
密码123456
3 curl
mac@macdeMacBook mkcert % chmod 777 myhost.com-key.pem
mac@macdeMacBook mkcert % curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to myhost.com (127.0.0.1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* unable to set private key file: 'myhost.com-key.pem' type PEM
* Closing connection 0
curl: (58) unable to set private key file: 'myhost.com-key.pem' type PEM
查下来是openssl分解可能存在很深的问题,不浪费时间
4 故从头开始
mkcert myhost.com
openssl pkcs12 -export -in myhost.com.pem -inkey myhost.com-key.pem -out myhost.com.p12
Enter Export Password:
Verifying - Enter Export Password:
把p12弄入springboot,作为keystore
keytool -import -file myhost.com.pem -keystore myhost.com-client(后改名未 -pub-capub).jks 作为truststore
curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v
成功
mac@macdeMacBook mkcert % curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to myhost.com (127.0.0.1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: O=mkcert development certificate; OU=mac@macdeMacBook.local
* start date: Feb 23 03:15:33 2023 GMT
* expire date: May 23 03:15:33 2025 GMT
* issuer: O=mkcert development CA; OU=mac@macdeMacBook.local; CN=mkcert mac@macdeMacBook.local
* SSL certificate verify ok.
> GET /test/test HTTP/1.1
> Host: myhost.com:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 4
< Date: Thu, 23 Feb 2023 03:23:38 GMT
<
* Connection #0 to host myhost.com left intact
DONE* Closing connection 0
5 java httpclient
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("mkcert/myhost.com.p12");
keyStore.load(inputStream, "changeit".toCharArray());
SSLContext sslcontext = SSLContexts.custom()
//忽略掉对服务器端证书的校验
.loadTrustMaterial(new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
})
//加载服务端提供的truststore(如果服务器提供truststore的话就不用忽略对服务器端证书的校验了)
//.loadTrustMaterial(new File("D:\\truststore.jks"), "123456".toCharArray(),
// new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, "changeit".toCharArray())
.build();
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, hostnameVerifier);
Executing request GET https://myhost.com:8080/test/test HTTP/1.1
11:26:48.940 [main] DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
11:26:48.969 [main] DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
11:26:48.971 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
11:26:48.988 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
11:26:48.990 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {s}->https://myhost.com:8080
11:26:48.995 [main] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to myhost.com/127.0.0.1:8080
11:26:49.005 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Connecting socket to myhost.com/127.0.0.1:8080 with timeout 0
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled protocols: [TLSv1, TLSv1.1, TLSv1.2]
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled cipher suites:[TLS_ECDHE_ECDSA_W。。。。。ENEGOTIATION_INFO_SCSV]
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
经查:
数据和安全②HTTPS单向和双向认证
https://www.codetd.com/article/11579403
5、将客户端证书添加到服务端jks中
## 将客户端证书导入服务端jks
keytool -import -v -file client.cer -keystore server.jks
### 查看证书文件 cer和crt证书文件一模一样,顶多去掉前缀
### 查看jks的证书文件,如下图
keytool -list -rfc -keystore server.jks -storepass 123456
## 服务端信任客户端证书、客户端证书信任服务端不行,要将根证书导入秘钥库
## 要将ca证书也导入证书库
keytool -import -file ca.crt -alias ca -keystore server.jks -storepass 123456

如果没有添加根证书到jks秘钥库,报错如下:
SSLHandshakeException: Received fatal alert: bad_certificate
跟着操作:
mkcert -CAROOT
keytool -import -file /Users/mac/Library/Application\ Support/mkcert/rootCA.pem -alias ca -keystore myhost.com-pub-capub.jks
查看ca证书是否已经在里面了:
mac@macdeMacBook mkcert % keytool -v -list -keystore myhost.com-pub-capub.jks
输入密钥库口令: 密钥库类型: JKS
密钥库提供方: SUN 您的密钥库包含 2 个条目 别名: ca
创建日期: 2023-2-23
条目类型: trustedCertEntry 所有者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
发布者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
序列号: 235d3f5c76501a7ed133bc9d0bc44bd3
有效期开始日期: Mon Dec 12 14:53:21 CST 2022, 截止日期: Sun Dec 12 14:53:21 CST 2032 别名: mykey
创建日期: 2023-2-23
条目类型: trustedCertEntry 所有者: OU=mac@macdeMacBook.local, O=mkcert development certificate
发布者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
序列号: 6e414b515e161572f3da9edbaf732ba7
有效期开始日期: Thu Feb 23 11:15:33 CST 2023, 截止日期: Fri May 23 11:15:33 CST 2025
重启
成功
6 透明代理
将http代理服务器(三)fiddler【重点】中的透明代理拿来
请求成功
代理输出:
二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler channelRegistered
信息: [id: 0x5522c775] REGISTERED
二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler bind
信息: [id: 0x5522c775] BIND(0.0.0.0/0.0.0.0:1999)
二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler channelActive
信息: [id: 0x5522c775, /0:0:0:0:0:0:0:0:1999] ACTIVE
二月 23, 2023 11:35:25 上午 io.netty.handler.logging.LoggingHandler logMessage
信息: [id: 0x5522c775, /0:0:0:0:0:0:0:0:1999] RECEIVED: [id: 0x6b813dbd, /127.0.0.1:59079 => /127.0.0.1:1999]
--------------------cc----------------------
------------------------------------------
服务器输出:
个人证书信息:OU=mac@macdeMacBook.local, O=mkcert development certificate
说明经过了代理传递了证书,逻辑上 java httpclient与springboot直接ssl双向握手
7
自签名证书穿越want
keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore"
keytool -importkeystore -srckeystore test.keystore -destkeystore test.p12 -srcstoretype jks -deststoretype pkcs12
可以穿越,但拿不到证书
8 ca证书穿越want
mkcert -pkcs12 testca
11:58:28.670 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
11:58:28.946 [main] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
11:58:28.947 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection discarded
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1769)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:124)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager is shutting down
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1130)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager shut down
at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1216)
说明want一旦开始搞就会搞到底,不如不给客户端证书或自签名证书
9 mkcert myhost.com作为客户端证书
两种方式 直接mkcert p12 与mkcert pem再openssl合并,结果都同8 error
所以mkcert两次即使签发同一个cn,证书内容也不相同
10 不给truststore
家里所有请求都失败 java和curl
公司可以不知道为啥 (https原理(六)系统分析中解释了)
| 家里有truststore | 公司没有truststore | |
| 原始 | 通过有证书 | 通过有证书 |
| 自签名 | 通过但没证书 | 通过但没证书 |
| ca不同cn | ssl失败 | / |
| ca 相同cn p12 | ssl失败 | / |
| ca 相同cn pem p12 | ssl失败 | / |
11 那么对于want
https://qa.1r1g.com/sf/ask/1047344861/
我的应用程序需要对特定URL进行客户端身份验证,在客户端身份验证成功后,应用程序本身也会对客户端证书主题进行一些验证(使用spring security x509过滤器).我想配置tomcat来强制特定URL的客户端身份验证(clientAuth = true),但基于这篇文章,似乎我不能只使用tomcat - 只为特定的URL模式配置tomcat进行客户端身份验证.
我的问题是,如果我使用clientAuth = want,当服务器请求证书时,以下内容如下:
- 如果设备具有身份证书但不受tomcat truststoreFile中配置的CA信任,则不会传递证书,并且请求将在spring安全过滤器中失败(证书将为null)
- 如果设备具有由tomcat truststoreFile中配置的CA信任的身份证书,但无效(不确定执行了哪些验证)或过期,则认证将在tomcat中失败(在安全过滤器之前)或在选项1中没有证书将传递并且请求将在spring安全过滤器中失败(证书将为null) 我这里直接ssl失败
使用此配置的want +安全过滤器,是否存在我可能缺少的安全漏洞?我想问题是 - 如果证书最终从设备传递到服务器,服务器将始终验证它(未过期,受信任等),即使使用clientAuth = want也不会允许客户端继续,如果证书是无效?没有证书通过的情况由安全过滤器覆盖,该过滤器将检查证书不为空.
您在1和2中的假设都是正确的.Tomcat不允许将不受信任或无效的证书通过您的应用程序.如果获得空证书,则可以假定未传递证书,或者传递了不受信任/无效的证书.
在我正在开发的项目上,我们有与您相同的要求:仅限某些URL的客户端证书.我们通过实验发现了"clientAuth = want"的工作原理.
https原理(四)双向实践(java客户端+tcp代理)的更多相关文章
- Tengine HTTPS原理解析、实践与调试【转】
本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...
- Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用
介绍 Memcached java client是官方推荐的最早的memcached java客户端.最新版本:java_memcached-release_2.6.1. 官方下载地址:http ...
- 【大量干货】史上最完整的Tengine HTTPS原理解析、实践与调试
本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...
- HTTPS 原理与证书实践
1.1 网络安全知识 1.1.1 网结安全出现背景 网络就是实现不同主机之间的通讯,网络出现之初利用TCP/IP协议簇的相关协议概念,已经满足了互连两台主机之间可以进行通汛的目的,虽然看似简简单单几句 ...
- https原理与实践
HTTPS 原理与证书实践 分类: Web应用 1.1 网络安全知识 1.1.1 网结安全出现背景 网络就是实现不同主机之间的通讯,网络出现之初利用TCP/IP协议簇的相关协议概念,已经满足了 ...
- Atitit.异常的设计原理与 策略处理 java 最佳实践 p93
Atitit.异常的设计原理与 策略处理 java 最佳实践 p93 1 异常方面的使用准则,答案是:: 2 1.1 普通项目优先使用异常取代返回值,如果开发类库方面的项目,最好异常机制与返回值都提供 ...
- Java实现TCP之Echo客户端和服务端
Java实现TCP之Echo客户端和服务端 代码内容 采用TCP协议编写服务器端代码(端口任意) 编写客户机的代码访问该端口 客户机按行输入 服务器将收到的字符流和接收到的时间输出在服务器consol ...
- java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端
java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端 启动界面如下图: 首先启动服务器: 客户端登陆,登陆成功后为: 默认发送是全部用户,是多人发送. 当在边列 ...
- Https双向认证Android客户端配置
Https .cer证书转换为BKS证书 公式https://blog.csdn.net/zww986736788/article/details/81708967 keytool -importce ...
- TCP/UDP client/server library for Java, 最好的java语言tcp udp 服务器客户端实现库
这个库andrdoi也可以用,而且是基于类的使用方式: 它支持类似聊天室的功能,即一个人说话,所有客户端都能收到,当然也支持点点通信.它还支持 RMI 的方式调用远程过程. https://githu ...
随机推荐
- linux 进程组和会话 守护进程
这两个概念的产生,是为了shell更好的管理作业,管理其创建的子进程 对其进行暂停,终止 执行命令,命令之间有时还需要管道进行通信 进程组是进程的合集 会话是进程组的合集 一个会话共用一个控制终端,也 ...
- win10bug可导致系统崩溃
1.使用浏览器访问访问路径:\\.\globalroot\device\condrv\kernelconnect会立刻导致系统崩溃.会影响Windows10 1709及以上版本 2.使用以下代码保存成 ...
- windows自带xbox game bar如何更改录制视频保存位置
若要更改保存游戏剪辑的位置,请使用文件资源管理器根据需要将"捕获"文件夹移动到电脑上的任意位置. Windows 会将游戏剪辑和屏幕截图保存在该文件夹中(无论移动到哪里). ...
- SFTP实现密钥登陆并上传文件
什么是SFTP,公开键认证,SFTP可不是FTP协议的扩展,他是基于SSH的文件传输协议. 而当SFTP服务器登录有客户端的公开键时,客户端就可以用自己的私有键去跟服务器握手(handshake)已实 ...
- vscode的python开发环境搭建,环境变量支持终端命令行(执行当前
vscode的python开发环境设置 安装vscode,这里不介绍了 安装插件 在${workspaceFolder}的目录下,新建.vscode文件夹(或者修改一下配置,也可以自动生成该文件夹) ...
- 【23期】请你谈谈关于IO同步、异步、阻塞、非阻塞的区别
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别? 这个问题其实不同的人给 ...
- docker部署rocketmq
docker pull foxiswho/rocketmq:server-4.7.0 (拉取镜像) docker pull foxiswho/rocketmq:broker-4.7.0 (拉取镜像) ...
- Web学习篇—Http协议
Http协议简介 h3 { background: rgba(0, 154, 205, 1); color: rgba(255, 255, 255, 1); border-radius: 6px; f ...
- javase_note
我上班摸鱼重新学习java基础做的笔记,从面向对象开始 面向对象基础 类与对象 人类.鸟类.鱼类...所谓类,就是对一类事物的描述 对象是某一类事物实际存在的每个个体,因此也称为实例 类是抽象概念,对 ...
- 微积分 II 笔记
5.1 定积分的概念 定义 定积分是积分的一种,是函数 \(f(x)\) 在区间 \([a,b]\) 上积分和的极限 若 \(f(x)\) 在 \([a, b]\) 有界,在 \([a, b]\) 上 ...