You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python SSL包装套接字无法接收IoT设备连接问题排查求助

问题排查与修复方案

你的核心问题出在SSL上下文的初始化配置,以及IoT设备兼容的TLS参数设置上,以下是具体修复步骤:

1. 修正SSL上下文的Purpose参数

你当前用ssl.Purpose.CLIENT_AUTH初始化上下文,这是用于验证客户端证书的场景;作为TLS服务器,必须使用ssl.Purpose.SERVER_AUTH来创建适合服务器的默认上下文。

2. 兼容IoT设备的TLS版本与密码套件

IoT设备通常仅支持TLS 1.2(甚至更低版本),而Python默认SSL上下文可能禁用了旧版本,需要显式开启;同时要确保服务器支持设备Client Hello中列出的密码套件。

从你的非SSL日志里的Client Hello数据包来看,设备支持的密码套件包括:

  • 00= → TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • 005 → TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • 00< → TLS_RSA_WITH_AES_256_GCM_SHA384
  • 00/ → TLS_RSA_WITH_AES_128_GCM_SHA256
  • 00ff → TLS_EMPTY_RENEGOTIATION_INFO_SCSV

需要确保服务器启用这些套件,并兼容TLS 1.2。

3. 添加SSL调试日志

开启SSL调试日志可以直接看到握手失败的具体原因,比如证书不匹配、TLS版本不兼容等。


修改后的完整SSL服务器代码

import logging
import ssl
import asyncio
import sys

logger = logging.getLogger(__name__)
formatter = logging.Formatter(
    "%(asctime)s.%(msecs)04d %(levelname)s - %(name)s %(module)s:%(lineno)d -> %(message)s",
    "%m/%d/%y %H:%M:%S",
)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# 开启SSL调试日志,排查握手问题
logging.basicConfig(level=logging.DEBUG)
ssl_logger = logging.getLogger('ssl')
ssl_logger.setLevel(logging.DEBUG)


async def handle_client(reader, writer):
    try:
        while True:
            data = await reader.read(1024)
            if not data:
                break
            addr = writer.get_extra_info('peername')
            logger.info(f"Received from {addr!r} => {data.hex()}")
            
            # 可选:回显数据测试通信
            writer.write(data)
            await writer.drain()
    except Exception as e:
        logger.error(f"Client handler error: {e}")
    finally:
        logger.info("Closing the connection")
        writer.close()
        await writer.wait_closed()


async def main():
    # 使用服务器端专属的SSL上下文
    ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE
    ssl_context.load_cert_chain(certfile="certs/cert.pem", keyfile="certs/key.pem")
    
    # 启用TLS 1.2兼容IoT设备
    ssl_context.options &= ~ssl.OP_NO_TLSv1_2
    # 设置匹配设备的密码套件
    ssl_context.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384:RSA-AES128-GCM-SHA256')

    server = await asyncio.start_server(
        handle_client, "0.0.0.0", 23779, ssl=ssl_context
    )

    sock = server.sockets[0]
    addr = sock.getsockname()
    logger.info(f"Serving on {addr}")

    async with server:
        await server.serve_forever()

if __name__ == "__main__":
    logger.info("Starting SSL server...")
    asyncio.run(main())

额外验证步骤

  1. 确认证书CN与设备连接的域名完全匹配(你的证书是*.xlink.cn,确保设备访问的是xxx.xlink.cn格式的域名)
  2. 用openssl s_client测试服务器是否正常工作:
openssl s_client -connect localhost:23779 -servername your-device-domain.xlink.cn

如果该命令能完成握手,说明服务器配置正常。

内容的提问来源于stack exchange,提问作者baudneo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:18:09