当前位置: 首页 > news >正文

用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`

一、模块定位与作用

  1. 协议代理

    • NGINX 监听指定端口(如 25、587、465 等),接收客户端的 SMTP 会话请求。
    • 代理层在会话中透明转发客户端的 EHLO、MAIL FROM、RCPT TO、DATA 等命令到后端 MTA。
  2. 认证控制

    • 通过 smtp_auth 指令指定允许的 SASL 认证方式(例如 PLAINLOGINCRAM-MD5EXTERNAL);
    • 也可设置为 none,直接跳过代理层认证,让后端 MTA 完成验证。
  3. 功能协商(EHLO 扩展)

    • 使用 smtp_capabilities 定义代理层响应给客户端的 SMTP 扩展列表;
    • NGINX 会自动在扩展列表中添加 AUTH=...STARTTLS(若启用)等,使客户端知道可用功能。
  4. 性能与安全优化

    • smtp_client_buffer 控制读取客户端命令的缓冲区大小,避免大命令时分段造成性能抖动;
    • smtp_greeting_delay 可在发送 220 欢迎消息前加入延迟,用于拦截不等待问候就发送命令的恶意客户端。

二、核心指令详解

2.1 smtp_auth

smtp_auth method ...;

默认值smtp_auth plain login;
上下文mail, server

功能
  • 指定允许客户端使用的 SASL 身份验证机制。
  • 如果未包含 plainlogin,则 AUTH PLAINAUTH LOGIN 仍可执行,但不会自动列入 EHLO 扩展列表。
支持的认证方式
方法说明
plainAUTH PLAIN:客户端以 Base64 传输 \0username\0password。需 TLS 加密,否则存在明文风险。
loginAUTH LOGIN:分两步传输用户名与密码,也需 TLS 加密才能保证安全。
cram-md5AUTH CRAM-MD5:质询-响应式验证,后端需保存明文或可生成 MD5 摘要。更安全,但需后端支持。
externalAUTH EXTERNAL (1.11.6+):使用客户端 TLS 证书进行外部认证。
none禁用代理层认证,让后端 MTA 或其他机制处理身份验证;客户可直接继续后续 SMTP 对话。
示例
mail {server {listen      587;            # SMTP Submission (STARTTLS)protocol    smtp;# 只允许 AUTH PLAIN、AUTH LOGIN 和 AUTH CRAM-MD5smtp_auth   plain login cram-md5;# 后端 MTA 地址proxy_pass  smtp_backend:25;}
}
  • 客户端在执行 EHLO example.com 后会看到 250-AUTH PLAIN LOGIN CRAM-MD5
  • 如果用户发送 AUTH CRAM-MD5 <response>,NGINX 会将验证请求转发到后端 MTA。

2.2 smtp_capabilities

smtp_capabilities extension ...;

默认值:无(若不配置,则仅显示后端默认 EHLO 响应,并附加 AUTHSTARTTLS
上下文mail, server

功能
  • 定义 NGINX 代理在客户端 EHLO 响应中通告的 SMTP 扩展列表;
  • NGINX 会自动添加当前 smtp_auth 中定义的 AUTH=...,以及 STARTTLS(如果启用 starttls);
  • 建议将后端 MTA 实际支持的扩展在此列出,例如 SIZEPIPELINING8BITMIMEENHANCEDSTATUSCODES 等。
常见扩展选项
扩展含义
SIZE通告客户端最大邮件大小(如 SIZE 10485760 表示最大 10MB)。
PIPELINING支持 SMTP 管道式命令,允许一次发送多个命令减少网络往返。
8BITMIME支持 8 位传输编码(允许直接发送 8 位字符)。
ENHANCEDSTATUSCODES支持扩展状态码格式 250 2.1.0 OK,提高错误信息的可读性。
DSN支持传输状态通知(Delivery Status Notification)。
STARTTLS支持在 587/25 端口上升级到 TLS 加密通道;若启用 starttls on;,NGINX 会自动添加此扩展。
AUTH=PLAIN LOGIN CRAM-MD5smtp_auth 自动补充,通知客户端可用的 SASL 机制。
示例
mail {server {listen      587;             # SMTP Submissionprotocol    smtp;# 启用 STARTTLSstarttls    on;# 允许 PLAIN、LOGIN、CRAM-MD5 三种认证方式smtp_auth     plain login cram-md5;# 明确通告客户端支持的扩展;NGINX 会自动附加 AUTH 和 STARTTLSsmtp_capabilities SIZE PIPELINING 8BITMIME ENHANCEDSTATUSCODES DSN;proxy_pass    smtp_backend:25;}
}
  • 客户端 EHLO mail.example.com 时,NGINX 返回:

    250-mail.example.com Hello [192.0.2.1]
    250-SIZE
    250-PIPELINING
    250-8BITMIME
    250-ENHANCEDSTATUSCODES
    250-DSN
    250-AUTH PLAIN LOGIN CRAM-MD5
    250-STARTTLS
    250 HELP
    

2.3 smtp_client_buffer

smtp_client_buffer size;

默认值:与系统内存页大小相当(4K 或 8K)
上下文mail, server

功能
  • 指定 NGINX 在读取客户端发送的 SMTP 命令时所使用的缓冲区大小
  • 当客户端发出长字符串、Base64 编码凭证或大型邮件头时,可能超过默认缓冲区,需要适当放大;
  • 过小会导致分段读取、性能抖动;过大则占用更多内存。
示例
mail {server {listen              25;      # 普通 SMTPprotocol            smtp;# 将缓冲区增大到 16K,以一次性消费大型输入smtp_client_buffer  16k;smtp_auth           plain login;smtp_capabilities   SIZE PIPELINING 8BITMIME;proxy_pass          smtp_backend:25;}
}
  • 当客户端发送长 AUTH PLAIN <base64-credentials> 时,16K 缓冲可一次读取完整凭证,避免折行或多次读取增加延迟。

2.4 smtp_greeting_delay

smtp_greeting_delay time;

默认值0(无延迟)
上下文mail, server

功能
  • 在向客户端发送 SMTP 220 欢迎消息之前延迟指定时间;
  • 主要用于防御“恶意客户端”或“探测脚本”——它们可能不会等待 220,再立刻发送 EHLO 或其他命令;
  • 若客户端在延迟期内提前发送命令,NGINX 可以直接拒绝或丢弃连接,节省后端资源。
示例
mail {server {listen               25;protocol             smtp;# 在发送 220 欢迎前延迟 3 秒smtp_greeting_delay  3s;smtp_auth            plain;smtp_capabilities    SIZE PIPELINING;proxy_pass           smtp_backend:25;}
}
  • 攻击脚本若不等待延迟直接发命令,将收到连接重置或拒绝;
  • 合法客户端会在 3 秒后收到标准 220 欢迎并继续会话。

三、综合示例:部署 SMTP 代理(Submission 与 SMTPS)

下面给出一个完整的生产环境示例,包含 Submission(587)和 SMTPS(465)两种监听方式,以及启动 STARTTLS、SASL 认证、协议扩展等配置。

worker_processes auto;
events { worker_connections 2048; }mail {# 全局缓冲区,可根据实际负载调整smtp_client_buffer 8k;# 587 端口:支持 STARTTLSserver {listen               587;            # Submissionprotocol             smtp;starttls             on;             # 启用 STARTTLS# 在发送 220 欢迎前延迟 2 秒,拦截恶意探测smtp_greeting_delay  2s;# 允许明文登录(PLAIN/LOGIN)及质询式 CRAM-MD5smtp_auth            plain login cram-md5;# 声明支持的扩展;NGINX 会自动附加 AUTH=PLAIN LOGIN CRAM-MD5 和 STARTTLSsmtp_capabilities    SIZE PIPELINING 8BITMIME ENHANCEDSTATUSCODES DSN;# 转发到后端 MTAproxy_pass           smtp_backend:25;proxy_timeout        2m;proxy_pass_error_message on;}# 465 端口:直接 SMTPS(TLS 加密)server {listen               465 ssl;         # SMTPSprotocol             smtp;# 无需 STARTTLS,因为连接一开始即为 TLSsmtp_auth            plain login cram-md5;smtp_capabilities    SIZE PIPELINING 8BITMIME ENHANCEDSTATUSCODES DSN;# TLS 配置ssl_certificate      /etc/nginx/ssl/smtp.crt;ssl_certificate_key  /etc/nginx/ssl/smtp.key;ssl_protocols        TLSv1.2 TLSv1.3;ssl_ciphers          HIGH:!aNULL:!MD5;ssl_session_cache    shared:mail_ssl:10m;ssl_session_timeout  10m;proxy_pass           smtp_backend:25;proxy_timeout        2m;proxy_pass_error_message on;}
}

核心解析

  1. Submission(587)与 SMTPS(465)并行

    • Submission:587 端口支持明文连接后升级到 TLS(starttls on;);
    • SMTPS:465 端口直接强制 TLS 加密,无需 STARTTLS
  2. 延迟问候

    • smtp_greeting_delay 2s;:在发送 220 example.com ESMTP 前等待 2 秒,以拦截不等待问候的恶意连接。
  3. 认证方式

    • smtp_auth plain login cram-md5;:允许 AUTH PLAINAUTH LOGINAUTH CRAM-MD5,保证兼容大多数客户端;
    • 若后端 MTA 支持客户端证书验证,可改用 smtp_auth external;
  4. 通告扩展

    • smtp_capabilities size pipelining 8bitmime enhancedstatuscodes dsn;:明确告诉客户端后端支持的功能;
    • NGINX 会自动在 EHLO 响应中加入 AUTH=PLAIN LOGIN CRAM-MD5 以及 STARTTLS
  5. 缓冲区与超时

    • smtp_client_buffer 8k;:保证一次性读取大部分 SMTP 命令,避免多次系统调用;
    • proxy_timeout 2m;:如果后端在 2 分钟内未响应,则关闭连接。
  6. 错误透传

    • proxy_pass_error_message on;:当后端返回错误(如认证失败、邮箱满等),直接将错误信息转发给客户端,方便客户端做相应处理。

四、最佳实践与注意事项

  1. TLS 与明文认证绝配

    • 当启用 plain/login,务必使用 TLS(Submission 或 SMTPS),否则用户名和密码会以 Base64 明文形式在网络中传输。
    • 可结合 ssl_verify_client on; 强制客户端出示证书并使用 smtp_auth external; 进行双向认证。
  2. 通告与后端保持一致

    • smtp_capabilities 中仅列出后端 MTA 真实支持的扩展;
    • 如果后端不支持 DSNENHANCEDSTATUSCODES,切勿在代理层通告,以免客户端发送不受支持的命令。
  3. 缓冲区大小调整

    • 默认 4k/8k 缓冲适配大多数场景;
    • 若观察到大型 AUTH PLAIN 字符串或大邮件标头导致分段读取,可将 smtp_client_buffer 调至 16k 或更高;
    • 注意内存占用与并发量的平衡。
  4. 延迟问候谨慎使用

    • smtp_greeting_delay 可拦截那些“不等待 220 就发命令”的垃圾邮件机器或探测脚本;
    • 但若延迟过长会让合法客户端感觉连通性不佳,一般设为 1s~3s 即可。
  5. 日志与调试

    • 通过 mail_log 记录 SMTP 会话关键日志(认证成功/失败、邮件投递状态等);
    • 通过 error_log 捕获代理层错误与连接异常。
    • 在调试阶段,可将 proxy_pass_error_message on; 打开,观察后端具体的错误响应。

五、总结

ngx_mail_smtp_module 为 NGINX 增加了强大的 SMTP 代理能力,让你能够:

  • 灵活控制 SASL 认证方式(PLAIN、LOGIN、CRAM-MD5、EXTERNAL 或跳过),
  • 自定义 EHLO 扩展通告,与后端 MTA 完美协同,
  • 优化客户端缓冲与超时,提升并发与稳定性,
  • 通过问候延迟拦截恶意探测,减少垃圾邮件源头连接。

结合 NGINX 在并发、TLS 加速与日志收集方面的优势,你可以轻松搭建安全、高效且易于扩展的 SMTP 代理网关,为企业级邮件系统保驾护航。希望本文的指令详解与配置示例,能够帮助你快速上线 SMTP 代理,并在生产环境中获得稳定可靠的运行效果。祝你部署顺利!

http://www.lqws.cn/news/165385.html

相关文章:

  • 深度学习N2周:构建词典
  • 板凳-------Mysql cookbook学习 (十)
  • ReLU 激活函数:重大缺陷一去不复返!
  • reverse笔记
  • 目标检测实战:让AI“看见“并定位物体(superior哥AI系列第11期)
  • Web后端基础(Maven基础)
  • 8天Python从入门到精通【itheima】-69~70(字符串的常见定义和操作+案例练习)
  • 从Copilot到Agent,AI Coding是如何进化的?
  • 2025爱分析·银行数字化应用实践报告|爱分析报告
  • [闭源saas选项]Pinecone:为向量数据库而生的实时语义搜索引擎
  • 关于智能体API参考接口
  • SpringBoot自动化部署实战技术文章大纲
  • 前端使用 preview 插件预览docx文件
  • 【cmder】--- Windows 下 cmder 经典常用快捷键 显著提高效率
  • python打卡day45
  • 如何实现本地mqtt服务器和云端服务器同步?
  • Spring @Scheduled vs XXL-JOB vs DolphinScheduler vs Airflow:任务调度框架全景对比
  • DeepSeek私有化部署的理性抉择:谁需要?谁不必?
  • 408第一季 - 408内容概述
  • 【Linux基础知识系列】第十一篇-Linux系统安全
  • 安科瑞防逆流方案落地内蒙古中高绿能光伏项目,筑牢北疆绿电安全防线
  • 企业级AI迈入黄金时代,企业该如何向AI“蝶变”?
  • 摄像机ISP处理流程
  • COMSOL学习笔记-静电场仿真
  • 【强化学习】——03 Model-Free RL之基于价值的强化学习
  • 软件测试基础知识总结
  • RMSE可以融合均值与标准差
  • [zynq] Zynq Linux 环境下 AXI BRAM 控制器驱动方法详解(代码示例)
  • Tensorrt python api 10.11.0笔记
  • 【信息系统项目管理师-选择真题】2025上半年(第一批)综合知识答案和详解