提取 clienthello 里的 server_name
时间: 2023-07-15 22:14:02 浏览: 46
在TLS握手过程中,clienthello消息包含了客户端的一些信息,包括支持的加密套件、协议版本等等。如果客户端想要请求特定的主机名,可以在clienthello消息中添加server_name扩展。
如果你想提取clienthello里的server_name,可以按照以下步骤进行:
1. 解析clienthello消息,提取出server_name扩展的位置和长度。
2. 读取server_name扩展的内容,该内容应该是一个列表,表示客户端想要请求的主机名。
3. 如果列表中有多个主机名,选择其中一个作为请求的目标。
需要注意的是,如果clienthello中没有server_name扩展,那么客户端可能会请求默认的主机名。在这种情况下,你可以使用服务器配置文件中的默认主机名作为请求的目标。
相关问题
c语言 提取 clienthello 里的 server_name
在TLS协议中,ClientHello消息包含了客户端支持的加密算法、随机数、会话ID以及请求的服务端主机名(server_name)等信息。如果你想在C语言中提取ClientHello里的server_name,可以按照以下步骤进行:
1. 解析TLS握手协议,获取ClientHello消息。
2. 在ClientHello消息中查找“扩展”字段。
3. 在扩展字段中查找“server_name”字段。
4. 解析server_name字段,获取主机名。
以下是一个简单的示例代码,仅供参考:
```c
#include <stdio.h>
#include <string.h>
#include "tls.h"
int main() {
// 假设client_hello消息已经获取到了
char client_hello[] = "...";
int client_hello_len = strlen(client_hello);
// 解析TLS握手协议
struct tls_handshake *handshake = (struct tls_handshake *)client_hello;
int handshake_len = client_hello_len - sizeof(struct tls_record);
// 获取ClientHello消息
struct tls_client_hello *client_hello_msg = (struct tls_client_hello *)handshake->msg_body;
int client_hello_msg_len = handshake_len - sizeof(struct tls_handshake);
// 查找扩展字段
struct tls_extension *ext = (struct tls_extension *)client_hello_msg->extensions;
int ext_len = client_hello_msg_len - sizeof(struct tls_client_hello);
while (ext_len > 0) {
// 找到server_name字段
if (ext->type == TLS_EXT_SERVER_NAME) {
// 解析server_name字段,获取主机名
struct tls_server_name *server_name = (struct tls_server_name *)ext->data;
int server_name_len = ntohs(server_name->name_length);
char *host_name = (char *)server_name->name;
printf("server_name: %.*s\n", server_name_len, host_name);
}
ext_len -= sizeof(struct tls_extension) + ntohs(ext->data_length);
ext = (struct tls_extension *)((char *)ext + sizeof(struct tls_extension) + ntohs(ext->data_length));
}
return 0;
}
```
需要注意的是,以上代码仅适用于TLS 1.2版本及以下的协议。在TLS 1.3中,ClientHello消息结构有所改变,需要进行相应的调整。
c语言解析tls server_name
在C语言中,解析TLS的Server Name可以使用OpenSSL库来实现。以下是一个简单的示例代码,可以从TLS的ClientHello消息中提取出Server Name。
```c
#include <stdio.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define MAX_BUF_SIZE 1024
int main() {
SSL_library_init();
SSL_CTX *ctx = SSL_CTX_new(TLS_method());
SSL *ssl = SSL_new(ctx);
// 连接到TLS服务器
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints, *servinfo;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("example.com", "443", &hints, &servinfo);
connect(sock, servinfo->ai_addr, servinfo->ai_addrlen);
SSL_set_fd(ssl, sock);
// 发送ClientHello消息
SSL_connect(ssl);
// 从SSL对象中获取ClientHello消息
unsigned char buf[MAX_BUF_SIZE];
int len = SSL_get_client_hello(ssl, buf, MAX_BUF_SIZE);
// 解析Server Name
const unsigned char *p = buf + 5; // 跳过TLS版本号和随机数
p += (*p) + 1; // 跳过Session ID
p += 2; // 跳过Cipher Suite长度
p += 1; // 跳过Compression Method长度
if (*p == 0x00) {
p += 3; // 跳过Extension Type和Extension Length
unsigned short name_len = (*(p+1) << 8) + *(p+2);
p += 3; // 跳过Server Name Indication长度
if (name_len > MAX_BUF_SIZE) {
name_len = MAX_BUF_SIZE;
}
char server_name[name_len];
memcpy(server_name, p+3, name_len-3);
server_name[name_len-3] = '\0';
printf("Server Name: %s\n", server_name);
}
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
return 0;
}
```
需要注意的是,TLS的Server Name可能包含多个域名,每个域名之间使用NULL字节分隔,因此需要对Server Name进行逐个解析。此外,如果Server Name长度超过了缓冲区的大小,需要进行截断处理。