修改openssl s_client使用录制ClientHello的信息对go中的https进行一致性测试

lyhuzi · · 3077 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

背景:nginx的https支持使用的是openssl库,对于大部分线上请求都能正确处理,可以大部分需求。但是在go语言中的https功能并未经过长期的考验,没有经过大项目的检验,所以一致性尤为重要。

方法:1、升级nginx中的代码,从线上抽样打印ssl的ClientHello信息。

          2、分析日志获取ClientHello信息。

          3、修改openssl s_client 代码,能够加载ClientHello信息。

从线上抽样打印ssl的ClientHello信息

这里主要讲述ngxin中如何对数据进行收集和openssl s_client 代码的修改。

关于nginx中需要在ngx_http_request.c中ngx_http_ssl_handshake函数,在ngx_ssl_create_connection函数调用成功后添加如下逻辑:

调用SSL_set_msg_callback来设置回调函数ngx_ssl_handshark_msg,自己可以实现ngx_ssl_handshark_msg的具体处理逻辑。

然后设置回调函数使用的参数:SSL_set_msg_callback_arg(c->ssl->connection, &param_cb);


加载ClientHello信息

在  s23_clnt.c 文件的函数 ssl23_client_hello 中的657行后添加了修改client hello信息代码:

以为当前线上没有ssl3一下的请求,所以我们这里只修改了ssl3的相关处理。

这里修改client hello信息的时候,不要修改random的信息。因为random的信息有时间信息,我们录制的client hello信息中的random信息多半是昨天以前的,所以如果直接用这样的random信息会出错的,所以一定不要修改这部分信息,其他信息完全拷贝就行了。修改完以后一定要修改s->init_num和s->init_off的数据。

为了能够通过命令行指定我们的client hello信息,我们对参数的处理进行了修改。

当前命令行的用法是:

openssl s_client -host 127.0.0.1 -port 1280 -client_hello 1603010050123412Ab231234123412341234123434123412341234……

切记要是用client_hello这个功能, 就不要再指定 ssl或tls的版本了,因为一旦指定版本,就不在使用ssl23_client_hello 这个默认函数了,那么我们修改的逻辑就走不到了。

相关修改ClientHello信息的代码:

s23_clnt.c

119 extern unsigned char *client_hello = NULL;
120 static int atoi_hex(const unsigned char data) {
121 int ret = -1;
122 
123 if (data >= '0' && data <= '9') {
124 ret = data - '0';
125 }
126 
127 if (data >= 'A' && data <= 'F') {
128 ret = data - 'A' + 10;
129 }
130 
131 if (data >= 'a' && data <= 'f') {
132 ret = data - 'a' + 10;
133 }
134 return ret;
135 }
136 
137 static int atoi_buf_hex(const unsigned char *src_data, size_t src_len, unsigned char *dist_data, size_t dist_len) {
138 unsigned char value = 0;
139 int tmp = 0;
140 size_t i = 0;
141 if (src_len != dist_len * 2) {
142 return -1;
143 }
144 
145 for (i = 0; i < dist_len && i * 2 < src_len; ++ i) {
146 tmp = atoi_hex(src_data[i * 2]);
147 if (tmp < 0) {
148 return -1;
149 }
150 value = (unsigned char)tmp;
151 
152 tmp = atoi_hex(src_data[i * 2 + 1]);
153 if (tmp < 0) {
154 return -1;
155 }
156 value = value << 4 | tmp;
157 dist_data[i] = value;
158 }
159 return 0;
160 }
161 
162 static int fill_client_hello_info(SSL *s, const unsigned char *data, size_t len) {
163 unsigned char *buf = NULL;
164 size_t offset = (32 + 11) * 2;
165 if (NULL == s || NULL == s->init_buf || NULL == s->init_buf->data) {
166 printf("error general in fill_client_hello_info");
167 return -1;
168 }
169 
170 buf = s->init_buf->data;
171 if (atoi_buf_hex(&data[0], 22, buf, 11)) {
172 return -1;
173 }
174 
175 if (atoi_buf_hex(&data[offset], len - offset, &buf[offset / 2], (len - offset) / 2) < 0) {
176 return -1;
177 }
178 
179 s->init_num = len / 2;
180 s->init_off = 0;
181 
182 return 0;
183 }


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3077 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传