因为要做个拨测,需要拨测https,也就是要看是否能与https服务器正常通讯。
所以查了资料,结合wireshark分析了下,client hello 、server hello内容。
两个hello通讯的前43个字节,意义是相同的:
//https tls
struct ProtocolVersion{
uint8_t major;
uint8_t minor;
};
enum ContentType{
change_cipher_spec=20, alert, handshake,
application_data
};
enum handshake_type{
clien_hello=1, server_hello
};
typedef struct {
uint8_t type;//ContentType 不能用enum,因为enum的成员长度是4
struct ProtocolVersion record_layer_version;
uint16_t record_layer_length;
uint8_t handshake_type;//handshake_type
uint8_t unuse_flag;
uint16_t handshake_length;
struct ProtocolVersion handshake_version;
uint32_t time_stamp;
char random[28];
} TLSPlaintext;
再给一段生成client hello的代码,这个是根据firefox的抓包的出来的,很low但能用:
static int ssl_inited = 0;
static char ssl_client_hello[256];
if(ssl_inited==0){
ssl_inited = sprintf(ssl_client_hello, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",22,3,1,0,143,1,0,0,139,3,3,88,20,46,196,175,181,85,76,101,22,68,197,18,171,239,103,209,196,218,211,83,190,188,182,18,23,203,134,183,236,189,92,0,0,22,192,43,192,47,192,10,192,20,0,57,0,53,192,9,192,19,0,51,0,47,0,10,1,0,0,76,255,1,0,1,0,0,10,0,8,0,6,0,23,0,24,0,25,0,11,0,2,1,0,0,35,0,0,0,16,0,14,0,12,2,104,50,8,104,116,116,112,47,49,46,49,0,5,0,5,1,0,0,0,0,0,13,0,18,0,16,4,3,5,3,6,3,4,1,5,1,6,1,2,3,2,1);
}
str_len = ssl_inited;
struct timeval tv;
gettimeofday(&tv, NULL);
memcpy(sendStr, ssl_client_hello, str_len);
memcpy(sendStr+11, &tv.tv_sec, 4);
int i;
for(i=0;i<28;i++){
sendStr[15+i] = (sendStr[15+i]&0xFF + tv.tv_usec) & 0xFF;
}
把服务器返回的转为:TLSPlaintext*,即可获取相关的信息:
char server_response[512];
readMsg(fd, server_response, 511);
TLSPlaintext* tls_resp = (TLSPlaintext*) server_response;
,serverhello符合:
tls_resp->type==handshake && tls_resp->handshake_type==server_hello