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

news2025/6/8 17:02:58

一、模块定位与作用

  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-MD5
        smtp_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 Submission
        protocol    smtp;

        # 启用 STARTTLS
        starttls    on;

        # 允许 PLAIN、LOGIN、CRAM-MD5 三种认证方式
        smtp_auth     plain login cram-md5;

        # 明确通告客户端支持的扩展;NGINX 会自动附加 AUTH 和 STARTTLS
        smtp_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;      # 普通 SMTP
        protocol            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 端口:支持 STARTTLS
    server {
        listen               587;            # Submission
        protocol             smtp;
        starttls             on;             # 启用 STARTTLS

        # 在发送 220 欢迎前延迟 2 秒,拦截恶意探测
        smtp_greeting_delay  2s;

        # 允许明文登录(PLAIN/LOGIN)及质询式 CRAM-MD5
        smtp_auth            plain login cram-md5;

        # 声明支持的扩展;NGINX 会自动附加 AUTH=PLAIN LOGIN CRAM-MD5 和 STARTTLS
        smtp_capabilities    SIZE PIPELINING 8BITMIME ENHANCEDSTATUSCODES DSN;

        # 转发到后端 MTA
        proxy_pass           smtp_backend:25;
        proxy_timeout        2m;
        proxy_pass_error_message on;
    }

    # 465 端口:直接 SMTPS(TLS 加密)
    server {
        listen               465 ssl;         # SMTPS
        protocol             smtp;

        # 无需 STARTTLS,因为连接一开始即为 TLS
        smtp_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.coloradmin.cn/o/2404343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARM SMMUv3简介(一)

1.概述 SMMU&#xff08;System Memory Management Unit&#xff0c;系统内存管理单元&#xff09;是ARM架构中用于管理设备访问系统内存的硬件模块。SMMU和MMU的功能类似&#xff0c;都是将虚拟地址转换成物理地址&#xff0c;不同的是MMU转换的虚拟地址来自CPU&#xff0c;S…

hadoop集群datanode启动显示init failed,不能解析hostname

三个datanode集群&#xff0c;有一个总是起不起来。去查看log显示 Initialization failed for Block pool BP-1920852191-192.168.115.154-1749093939738 (Datanode Uuid 89d9df36-1c01-4f22-9905-517fee205a8e) service to node154/192.168.115.154:8020 Datanode denied com…

浏览器工作原理05 [#] 渲染流程(上):HTML、CSS和JavaScript是如何变成页面的

引用 浏览器工作原理与实践 一、提出问题 在上一篇文章中我们介绍了导航相关的流程&#xff0c;那导航被提交后又会怎么样呢&#xff1f;就进入了渲染阶段。这个阶段很重要&#xff0c;了解其相关流程能让你“看透”页面是如何工作的&#xff0c;有了这些知识&#xff0c;你可…

|从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面

&#x1f411; |从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面 &#x1f411; 文章目录 &#x1f411; |从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面 &#x1f411;♈前言♈♈调取Deepseek大模型♈♒准备工作♒♒调用API♒ ♈将模型嵌入到ui界面中♈♈…

pikachu靶场通关笔记20 SQL注入03-搜索型注入(GET)

目录 一、SQL注入 二、搜索型注入 三、源码分析 1、渗透思路1 2、渗透思路2 四、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入百分号单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取…

产品笔试专业名词梳理

目录 产品常识 四种常见广告形式 贴片广告 中插广告 信息流广告 横幅广告 BAT和TMD BAT TMD 付费渗透率 蓝海市场、红海市场 蓝海市场 红海市场 竞品研究 SWOT分析 SWOT分析的核心目的&#xff1a; SWOT分析的优点&#xff1a; SWOT分析的局限与注意事项&…

【前端】es6相关,柯里化

0. 严格模式 严格模式的概念从ES6引进。通过严格模式&#xff0c;可以在函数内部选择进行较为严格的全局或局部的错误条件检测。 MDN中严格模式的描述 严格模式通过抛出错误来消除了一些原有静默错误严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷&#xff1a;有时…

51单片机基础部分——矩阵按键检测

前言 上一节&#xff0c;我们说到了独立按键的检测以及使用&#xff0c;但是独立按键每一个按键都要对应一个IO口进行检测&#xff0c;在一些需要多按键的情况下&#xff0c;使用过多的独立按键会过多的占用单片机的IO资源&#xff0c;为了解决这个问题的出现&#xff0c;我们…

SpringBoot2.3.1集成Knife4j接口文档

首先要查看项目中pom文件里面有没有swagger和knife4j的依赖&#xff0c;如果有的话删除&#xff0c;加入以下依赖 <!-- swagger --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</…

容器安全最佳实践:云原生环境下的零信任架构实施

&#x1f4cb; 目录 引言&#xff1a;容器安全的重要性零信任架构基础理论云原生环境的安全挑战容器安全威胁模型分析零信任架构在容器环境中的实施关键技术组件与工具安全策略与最佳实践监控与响应机制案例研究与实施路径未来发展趋势 引言 随着容器技术和云原生架构的快速…

[BIOS]VSCode zx-6000 编译问题

前提&#xff1a;Python 3.6.6及以上版本安装成功&#xff0c;Python 3.6.6路径加到了环境变量# DEVITS工具包准备好 问题&#xff1a;添加环境变量 1&#xff1a;出现环境变量错误&#xff0c;“py -3” is not installed or added to environment variables #先在C:\Windows里…

CICD实战(二)-----gitlab的安装与配置

1、安装gitlab所需要的依赖包与工具 sudo yum install wget net-tools sudo yum install curl policycoreutils openssh-server openssh-clients postfix -y 2、配置清华源 vim /etc/yum.repo.d/gitlab-ce.repo[gitlab-ce] namegitlab-ce baseurlhttp://mirrors.tuna.tsin…

[GitHub] 优秀开源项目

1 工具类 1.1 桌面猫咪互动 BongoCat

Linux中su与sudo命令的区别:权限管理的关键差异解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析LLP (二)

低层协议&#xff08;Low Level Protocol, LLP&#xff09;详细解析 1. 低层协议&#xff08;Low Level Protocol, LLP&#xff09;核心特性 包基础 &#xff1a;基于字节的包协议&#xff0c;支持 短包 &#xff08;32位&#xff09;和 长包 &#xff08;可变长度&#xff0…

第4天:RNN应用(心脏病预测)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: Pytorch &#xff08;二&#xff09;具体步骤…

GIC700概述

GIC-700是用于处理外设与处理器核之间&#xff0c;以及核与核之间中断的通用中断控制器。GIC-700支持分布式微体系结构&#xff0c;其中包含用于提供灵活GIC实现的几个独立块。 GIC700支持GICv3、GICv3.1、GICv4.1架构。 该微体系结构规模可从单核到互联多chip环境&#xff0…

统信桌面专业版如何使用python开发平台jupyter

哈喽呀&#xff0c;小伙伴们 最近有学员想了解在统信UOS桌面专业版系统上开发python程序&#xff0c;Anaconda作为python开发平台,anaconda提供图形开发平台,提供大量的开发插件和管理各种插件的平台&#xff0c;但是存在版权问题&#xff0c;有没有其他工具可以替代Anaconda呢…

什么是预训练?深入解读大模型AI的“高考集训”

1. 预训练的通俗理解&#xff1a;AI的“高考集训” 我们可以将预训练&#xff08;Pre-training&#xff09; 形象地理解为大模型AI的“高考集训”。就像学霸在高考前需要刷五年高考三年模拟一样&#xff0c;大模型在正式诞生前&#xff0c;也要经历一场声势浩大的“题海战术”…

鸿蒙仓颉语言开发实战教程:购物车页面

大家上午好&#xff0c;仓颉语言商城应用的开发进程已经过半&#xff0c;不知道大家通过这一系列的教程对仓颉开发是否有了进一步的了解。今天要分享的购物车页面&#xff1a; 看到这个页面&#xff0c;我们首先要对它简单的分析一下。这个页面一共分为三部分&#xff0c;分别是…