握手过程
cd /data/angelotong/openssl/openssl-master/apps time ./openssl s_client -debug -connect 14.152.86.41:443 -showcerts -prexit -servername appdlssl.dbankcdn.com -state -tls1_2>/dev/null
可以看到ssl具体握手过程:

源码分析
打开s_client.c,进入s_client_main函数:

从890~2975行,初始化环境,并根据./openssl s_client传入的参数 设置握手信息。
1903行,SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
此处设置握手时每个步骤都会执行的回调函数,参见文档,也就是说每个握手执行后,都会调用这个函数。


从2975行开始,是一个for (;;)状态机,执行握手,数据传输时的状态转换。
下面不远处,2915行,真正开始SSL握手,文中指定了握手协议使用TLSv1.2。

源码修改
上面说到回调函数apps_ssl_info_callback,我们可以在这个回调函数里控制ssl握手过程,如client接收到server hello之后,执行sleep,探测服务端握手超时时间:
vim apps/s_cb.c

apps_ssl_info_callback功能很简单,调用SSL_state_string_long(s)来得到当前握手的步骤,包括:
SSL_connect:before SSL initialization SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS write client hello SSL_connect:SSLv3/TLS read server hello ... SSL_connect:SSLv3/TLS read server certificate SSL_connect:SSLv3/TLS read server key exchange SSL_connect:SSLv3/TLS read server done SSL_connect:SSLv3/TLS write client key exchange SSL_connect:SSLv3/TLS write change cipher spec SSL_connect:SSLv3/TLS write finished SSL_connect:SSLv3/TLS write finished SSL_connect:SSLv3/TLS read server session ticket SSL_connect:SSLv3/TLS read change cipher spec SSL_connect:SSLv3/TLS read finished
修改apps_ssl_info_callback函数,加入:
if(strcmp(SSL_state_string_long(s), "SSLv3/TLS write client key exchange") == 0){ sleep(59); }
这里的sleep(59)可以让握手过程中client接收到server hello之后,等待一段时间再向server发送write client key exchange :

重新编译
保存上面修改,重新编译:
由于我们之前执行过config,并且不需要安装,所以仅执行make就可以:
cd /data/angelotong/openssl/openssl-master make -j 48
gdb调试
开始调试
cd apps gdb ./openssl run s_client -debug -connect 14.152.86.41:443 -showcerts -prexit -servername appdlssl.dbankcdn.com -state -tls1_2>/dev/null
可以看到客户端收到server hello后,59s后才执行client key exchange

可以看到,server等待59s后收到client key exchange操作,仍可以继续进行sll握手
修改sleep(59)为sleep(61),再次执行,发现server返回ssl握手失败

结论:server端握手超时时间为60s。
抓包分析
在我们上面设置sleep(59)前,开始抓包:
tcpdump -i eth0 host 14.152.86.41 -w baidu.pcap
抓包继续,将sleep时间设置为61,重新编译运行。
使用wireshark打开刚刚抓的包,第一次sleep(59)时握手成功:

第二次sleep(61),握手失败,再次验证了server端握手超时时间为60s的结论。
