使用getpeername获取客户端连接的实际TCP服务器端口
解决TCP加密代理中客户端获取服务器实际端口的问题
首先明确一个核心TCP协议常识:服务器端与客户端建立连接后,用于该连接通信的本地端口就是监听端口(比如你提到的443)。TCP协议通过复用监听端口处理所有入站连接,accept()返回的新套接字的本地地址端口与监听套接字完全一致,不存在所谓“协商后分配的独立端口”。因此你在客户端调用getpeername()拿到的就是服务器端对应该连接的实际端口。
如果你的需求是想获取服务器端作为代理去连接后端目标服务时使用的出口端口(即代理服务器作为客户端向目标服务发起连接的源端口),这个端口是服务器端本地生成的,客户端无法通过TCP API直接获取——除非服务器主动将该端口信息封装到加密数据包中发送给客户端,但这会违背你“减少开销”的初衷。
针对你的IV种子设计,若想进一步增强唯一性,无需额外传输数据的方案有:
- 在客户端连接建立后,生成一个短随机数(比如32位),将其作为第一个加密数据包的前缀发送给服务器。双方以「当前时间 + 客户端源端口 + 该随机数」作为IV种子,既保证全局唯一性,额外开销仅几个字节。
- 利用TCP连接的初始序列号(ISN),但该值在应用层无法直接通过标准socket API获取,部分系统(如Linux)可通过
TCP_INFO选项获取,但跨平台兼容性差,不推荐使用。
你的现有代码整理:
客户端获取自身源端口:
getsockname(stack[i][1], (struct sockaddr*)&source, &sockaddr_size);
服务器端获取客户端源端口:
getpeername(stack[i][0], (struct sockaddr*)&source, &sockaddr_size);
内容的提问来源于stack exchange,提问作者Dimitris
相关产品推荐
相关产品推荐

