net/http go包有一个类型请求,它定义了一个包含ConnectionState
的TLS字段。尽管如此,描述中的最后一条语句说它被HTTP客户端忽略了。我在调试时也检查了它,它是nil
。
我需要从该连接状态(或其他地方)获取值TLSUnique
,以便在将其注册/发送到服务器之前将其包含在证书请求(也称为CSR)中。
服务器不在我的问题范围内,我关心的是客户端。
然后,服务器接收请求,并检查CSR的签名沿着TLS唯一值,证明与TLS连接建立的同一客户端与签署CSR的客户端相同。
这是来自RFC 7030 -第3.5节(EST协议)的内容
[我用的是什么]
我正在试验GlobalSign EST Go包,它们似乎不包括此功能。
他们的EST客户端似乎为每个EST操作创建了一个http客户端,我想我可以改变这种行为,让一个客户端发送所有请求。
然而,由于客户端接受RoundTripper接口,我不能在实现之外使用底层连接的信息。
3条答案
按热度按时间igetnqfo1#
注意事项:在这个答案下的评论线程中,很明显OP是在发出客户端请求时获取“TLS unique”值之后。对此,请参阅my other answer或OP的解决方案。
我决定保留这个答案作为参考,因为它展示了一个有用的技术。
示例化
http.Server
,然后将其字段ConnContext
设置为您需要编写的某个函数。该函数在客户端创建到服务器的每个新TCP连接时被调用一次(一个连接能够服务多个请求)。当调用时,它接收服务客户端请求的
net.Conn
,因此您可以将其类型Assert为tls.Conn
,然后在其上调用ConnectionState
并在返回值中检查TLSUnique
。由于您可能需要使此值可用于通过该连接执行的HTTP请求,因此可以说最明智的解决方案是将该内容作为“值”隐藏在上下文中,该上下文将通过处理程序代码中的
http.Request
s提供。要做到这一点,在同一个回调代码中,您可以“ Package ”与请求关联的原始
context.Context
,并将其传递给回调,并从该TLSUnique
中提取一些值,以便您可以在服务于请求的HTTP处理程序中检查它。类似这样(未经测试):
字符串
查看有关
context.Context.Value
的文档,了解如何声明mypkg.MyKey
。您可能还需要在提取
TLSUique
时实际复制它的值-我不知道是否需要。qpgpyjmq2#
其中一种方法是对全局符号EST包进行一个小的更改。
就像我前面说的,当前的实现为每个EST操作(CACerts、CSRAttrs、Enroll等)创建一个新的http客户端。
1-让我们为所有EST操作创建一个http客户端。
2-无论哪种方式,我们都需要在注册CSR之前打电话获取CA证书。
3-对任何客户端请求的http响应都会公开字段
http.Response.TLS.TLSUnique
。4-让客户端在证书请求中包括它,签名并注册它。
当我想到全局签名EST包以及为什么他们每次都选择创建一个新的http客户端时,我不确定这是否有任何安全问题。
(除非它只是根据用户的意愿等待使用的示例)
5m1hhzi43#
好吧,根据我的另一个答案下的评论线程,下面是我如何实现客户端的:
字符串
关键点:
newCSR
(我假设这是所需的)创建了一个新的http.Request
,它:context.Context
,它:Read
方法第一次调用它,它就会自动返回。此变量与HTTP跟踪程序共享
context.Context
。http.Transport
通过任何方式 * 获得 * 一个连接来执行被跟踪的请求 * 时,HTTP跟踪器的“got conn”回调会被调用。* 这包括新连接或从空闲(重用)连接池中拉取的连接。如果连接是
tls.Conn
,回调的代码将从中提取“TLS unique”值,并将其保存到变量中,该变量是隐藏在上下文中的指针。http.Transport
开始读取请求的主体,这就是“懒惰主体构造”的开始:它读取包含跟踪器获得的“TLS unique”数据的变量的指针,并使用它来构造实际的CSR数据,然后以“正常方式”读取。代码是复杂的,但在另一方面,它可以与底层
http.Transport
的任何设置一起工作-连接池是主要的兴趣点。当然,如果你确切地知道你的设置的要求,这种方法很容易被过度使用。例如,如果你知道 * 或要求 * 不应该使用池,那么可以走一条更简单的路线,比如:
tls
包创建一个tls.Conn
,保存到某个地方,同时保存从中提取的“TLS unique”数据。http.Transport
,它:DialTLSWithContext
字段设置为仅返回已保存连接的回调。http.RoundTripper
中,以确保在任何给定时间只有一个RoundTrip
调用处于活动状态。