Kernel 5.3(Fedora30/31)下启用Kernel TLS ULP时setsockopt调用失败求助
解决Kernel 5.3(Fedora 30/31)Kernel TLS ULP启用错误的问题
我来帮你拆解遇到的几个错误,并一步步解决问题:
1. 普通用户执行时的「No such file or directory」错误
这个问题很明确:当你以普通用户身份运行程序时,tls内核模块还未加载,而普通用户没有自动加载内核模块的权限,内核找不到对应的ULP实现,因此返回ENOENT错误。
2. sudo执行后的「Unknown error 524」错误
错误码524对应内核的EKEYREJECTED,本质原因是你只启用了TLS ULP,但没有配置必要的TLS密钥和上下文信息。Kernel TLS的规则是:启用ULP之后,必须先通过setsockopt设置TLS_CONF选项,提供加密算法、密钥、IV等参数,否则内核会拒绝后续操作。
另外,先确认你的Fedora内核是否开启了Kernel TLS的必要配置:
zcat /proc/config.gz | grep CONFIG_TLS
你需要看到CONFIG_TLS=y或者CONFIG_TLS=m(模块形式),如果显示# CONFIG_TLS is not set,说明内核未编译该功能,需要重新编译内核或更换支持的内核包。
修复步骤
步骤1:手动加载tls模块(需要sudo权限)
先确保模块已加载,避免后续权限问题:
sudo modprobe tls
执行后用lsmod确认:
lsmod | grep tls
正常会输出:
tls 57344 0
步骤2:完善测试代码,添加TLS上下文配置
你的原代码只做了启用ULP的操作,缺少关键的TLS参数配置。下面是修改后的测试代码,添加了最基础的AES-GCM算法配置(示例密钥仅用于测试,实际需从TLS握手获取):
// tls.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <linux/tls.h> #include <netinet/ip.h> #include <netinet/tcp.h> int main() { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket creation"); exit(EXIT_FAILURE); } // 启用TLS ULP if (setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) == -1 ) { perror("tls init"); exit(EXIT_FAILURE); } // 配置TLS上下文(示例参数,仅用于测试) struct tls_conf conf = { .version = TLS_1_2, .cipher_type = TLS_CIPHER_AES_GCM_128, }; // 示例密钥和IV(实际场景需从TLS握手流程获取) unsigned char key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; unsigned char iv[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}; conf.rx_key.key = key; conf.rx_key.key_len = sizeof(key); conf.rx_key.iv = iv; conf.rx_key.iv_len = sizeof(iv); // 测试用:发送方向复用相同密钥IV,实际场景应使用独立的发送密钥 memcpy(&conf.tx_key, &conf.rx_key, sizeof(struct tls_key)); if (setsockopt(sock, SOL_TLS, TLS_CONF, &conf, sizeof(conf)) == -1) { perror("tls config"); exit(EXIT_FAILURE); } printf("Kernel TLS ULP 启用成功!\n"); close(sock); return EXIT_SUCCESS; }
步骤3:编译并运行修改后的代码
编译代码:
gcc tls.c -O0 -g
运行(需要sudo权限,因为设置TLS配置需要CAP_NET_ADMIN权限):
sudo ./a.out
如果一切正常,会看到输出:
Kernel TLS ULP 启用成功!
额外注意事项
- Kernel TLS仅负责对称加密的数据路径,TLS握手过程仍需用户态程序完成(比如用OpenSSL完成握手后,将密钥传递给内核)。
- 必须拥有
CAP_NET_ADMIN权限才能设置TLS配置选项,这也是需要sudo运行的原因。 - Fedora 30/31的默认内核通常已开启
CONFIG_TLS,如果未开启,需要安装内核源码重新编译,或更换支持该功能的内核包。
内容的提问来源于stack exchange,提问作者lukash256
相关产品推荐
相关产品推荐

