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

AIOSMTPD服务器无法配置TLSContext兼容TLS1.1问题排查

问题原因分析

出现NO_PROTOCOLS_AVAILABLE错误的核心原因有三点:

  1. SSL上下文Purpose配置错误
    服务器端创建SSL上下文时误用了ssl.Purpose.CLIENT_AUTH——该配置用于客户端验证服务器证书的场景,而SMTP服务器需要使用ssl.Purpose.SERVER_AUTH(服务器向客户端提供身份证书),错误的Purpose会导致上下文默认配置与服务器需求不匹配。

  2. 错误的Options设置
    代码中错误地将PROTOCOL_TLSv1、PROTOCOL_TLSv1_1等常量赋值给context.options。这些是创建SSLContext实例的协议类型标识,并非options的合法位掩码选项(options仅接受OP_*开头的常量,比如OP_NO_SSLv2)。这种错误赋值会破坏SSL上下文的协议支持配置,导致TLS1.1等协议被意外禁用。

  3. Python 3.10+默认禁用老旧TLS版本
    Python 3.10及以上版本出于安全考虑,默认禁用了TLS1.0和TLS1.1。即使显式设置minimum_version,也需要确保密码套件兼容且未被系统/全局SSL配置进一步限制。

解决方案及修正代码

修正后的服务器代码

from aiosmtpd.controller import Controller
from aiosmtpd.smtp import SMTP
from aiosmtpd.handlers import Debugging
import ssl, signal


class CustomController(Controller):
    def factory(self):
        # 服务器端必须使用SERVER_AUTH类型的上下文
        context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
        
        # 设置兼容TLS1.1的密码套件,保留MEDIUM级别套件(TLS1.1依赖此类套件)
        context.set_ciphers('HIGH:MEDIUM:!LOW:!DHE:!aNULL')
        context.set_ecdh_curve("secp384r1")
        
        # 仅禁用SSLv2/SSLv3,不要添加PROTOCOL_*到options中
        context.options |= ssl.OP_NO_SSLv2
        context.options |= ssl.OP_NO_SSLv3
        
        # 明确设置支持的TLS版本范围
        context.minimum_version = ssl.TLSVersion.TLSv1_1
        context.maximum_version = ssl.TLSVersion.TLSv1_3

        base_path = '/etc/letsencrypt/live/smtp.server.com'
        context.load_cert_chain(
            '{}/fullchain.pem'.format(base_path),
            '{}/privkey.pem'.format(base_path)
        )

        return SMTP(
            handler=self.handler,
            ident="Welcome.",
            tls_context=context,
        )


if __name__ == '__main__':
    controller = CustomController(Debugging(), hostname="localhost", port=2525)
    controller.start()
    print("Daemon started. Waiting for SIGINT or SIGQUIT to quit.")
    sig = signal.sigwait([signal.SIGINT, signal.SIGQUIT])
    print("Quitting SMTP Daemon")
    controller.stop()

关键修正点说明

  • 将ssl.Purpose.CLIENT_AUTH改为ssl.Purpose.SERVER_AUTH,匹配SMTP服务器的角色定位。
  • 删除所有context.options |= ssl.PROTOCOL_TLSv*的错误代码,仅保留SSLv2/3的禁用配置。
  • 调整密码套件,确保包含TLS1.1支持的MEDIUM级套件,同时排除不安全的空套件。
  • 若无需兼容TLS1.0,直接将minimum_version设为ssl.TLSVersion.TLSv1_1,进一步缩小支持范围。

额外注意事项

  • 如果系统OpenSSL配置默认禁用了TLS1.1,需修改/etc/ssl/openssl.cnf(或对应路径),移除MinProtocol中的限制,或添加TLSv1.1到允许列表。
  • Python 3.12对老旧TLS版本限制更严格,需确保测试环境的OpenSSL版本支持TLS1.1(OpenSSL 1.0.1及以上版本支持,但部分发行版可能默认禁用)。

内容的提问来源于stack exchange,提问作者Cyril N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:19:53