tomcat白名单(五)其他
0 跟我想法一致
https://www.coder.work/article/2852937
我想从 TLS Client Hello Message
中找到主机名。我想在 java 为透明 ssl 代理
完成握手之前找到主机名。
有没有什么方法可以在不编写整个 ssl 握手
逻辑的情况下找到 SNI 扩展
值?
Java 是否支持带有初始内存缓冲区的ssl 握手
? 我的想法是:
- 读取 TLS 客户端问候消息,解析并找到 SNI 值
- 调用
sslSocket.startHandshake(initialBuffer)
初始缓冲区将包含 TLS 客户端 hello 数据包数据。所以 Java 可以进行握手。
第二个想法是使用SSLEngine 类
。但它似乎比要求更多的实现。我假设 SSLEngine
在我不需要它的情况下大部分用于异步。
第三个想法是实现完整的TLS协议(protocol)
。
哪个想法更好?
1 JSSE
ava安全套接字扩展(Java Secure Socket Extension,JSSE)为基于SSL和TLS协议地Java网络应用程序提供了API及参考实现。使用JSSE,能够保证采用各种应用层协议(比如HTTP、FTP等)地客户程序与服务器程序安全地交换数据。
https://blog.csdn.net/weixin_44641388/article/details/117399609
安全网络通信(SSL&JSSE)
非常全的文章,对JSSE如何实现SSL
2 http://www.uml.org.cn/j2ee/201409013.asp
Netty系列之Netty安全性(二)
有些SslHandler源码分析
3 SNi
3.1 SNI问题
https://www.jianshu.com/p/78576039b1e2
非常好的文章,对几个客户端支持SNI的情况有详细描述
在 TLS 握手信息中并没有携带客户端要访问的目标地址。这样会导致一个问题,如果一台服务器有多个虚拟主机,且每个主机的域名不一样,使用了不一样的证书,该和哪台虚拟主机进行通信?这也就解释了为什么SLB需要SNI,我这里可以改为为什么Openshift/HAProxy需要SNI,因为它根据host来决定分发到哪个pod。
需要注意:
- 有 host 参数的都会在创建 Socket 的时候自动连接 host
- 只有直接以 String 传递 host 的方式才会在握手中使用 SNI,以 InetAddress 传递 host 的方式握手时都不会带着 SNI
SSLConnectionSocketFactory
3.3 https://qa.1r1g.com/sf/ask/2008203851/
JDK 1.8似乎提供以下选项来显式设置Hostname以连接到启用SNI的站点,
SNIHostName serverName = new SNIHostName("www.example.com");
List<SNIServerName> serverNames = new ArrayList<>(1);
serverNames.add(serverName);
sslParameters.setServerNames(serverNames);
3.4 https://blog.csdn.net/weixin_44388689/article/details/131171346
# determined by the next backend in the chain which may be an app backend (passthrough termination) or a backend
# that terminates encryption in this router (edge)
frontend public_ssl
bind :443
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
# if the connection is SNI and the route is a passthrough don't use the termination backend, just use the tcp backend
# for the SNI case, we also need to compare it in case-insensitive mode (by converting it to lowercase) as RFC 4343 says
acl sni req.ssl_sni -m found
acl sni_passthrough req.ssl_sni,lower,map_reg(/var/lib/haproxy/conf/os_sni_passthrough.map) -m found
use_backend %[req.ssl_sni,lower,map_reg(/var/lib/haproxy/conf/os_tcp_be.map)] if sni sni_passthrough
# if the route is SNI and NOT passthrough enter the termination flow
use_backend be_sni if sni
# non SNI requests should enter a default termination backend rather than the custom cert SNI backend since it
# will not be able to match a cert to an SNI host
default_backend be_no_sni
————————————————HA如此重视SNI,肯定不让你乱搞,注定了方案二的流产
https://www.haproxy.com/blog/enhanced-ssl-load-balancing-with-server-name-indication-sni-tls-extension
当 haproxy 接收到 HTTPS (443 端口)请求,会检查 HTTPS 请求支持 sni (TLS Server Name Indication)
这边的处理对应了 Router 对 HTTPS 流量的终结方式:
edge HTTPS 流量将在 Router 中解密并以纯 HTTP 转发至后端 Pod
passthrough TLS 加密包直接递交给后端 Pod,Router 不做任何 TLS 终结,不需要 TLS 相关证书
re-encryption 是 edge 的变种,HTTPS 流量将在 Router 中解密后再使用其他证书加密后转发至后端 Pod
也就是 route API 中的 termination 字段。
3.5
3.5.1 【HAPROXY】四层TCP转发及SNI Proxy简记
https://luotianyi.vc/6818.html
SNI转发是在TCP转发的基础上识别SNI并将流量以四层转发的形式送往源站,好处就是作为中间节点可以直接转发任意站点的流量而不涉及SSL证书的部署。简而言之,不用跟客户端握手,直接转发tcp流量,本质就是SLB侵入SSL协议ClientHello,跟我们干的事情差不多
所以SNI在我看来两个作用:
1)一个服务器多个域名多个证书,服务器通过SNI来决定用那个证书
2)正向代理4层转发,用于Openshift/HAProxy
3.5.2 haproxy配置sni实现https多域名代理
https://blog.csdn.net/yanggd1987/article/details/80737612
从上面的tcp代理处,我们可以看到通过sni区分不同的域名从而选择后端的服务器。
另在http代理处,我们可以看到也使用host区分域名实现不同的后端转发。
一个4层 1个7层
4 总结:
透明 ssl 代理
完成握手之前找到主机名
这也就解释了为什么SLB需要SNI,我这里可以改为为什么Openshift/HAProxy需要SNI,因为它根据host来决定分发到哪个pod
有点像7层的nginx根据host头转发,只不过它在4层
在 TLS 握手信息中并没有携带客户端要访问的目标地址
作为中间节点可以直接转发任意站点的流量而不涉及SSL证书的部署。简而言之,不用跟客户端握手,直接转发tcp流量,本质就是SLB侵入SSL协议ClientHello,跟我们干的事情差不多
所以SNI在我看来两个作用:
1)一个服务器多个域名多个证书,服务器通过SNI来决定用那个证书
2)正向代理4层转发,用于Openshift/HAProxy
从上面的tcp代理处,我们可以看到通过sni区分不同的域名从而选择后端的服务器。
另在http代理处,我们可以看到也使用host区分域名实现不同的后端转发。