Postfix:转发邮件配置启用SSL/TLS

2024-03-25 16:58

本文主要是介绍Postfix:转发邮件配置启用SSL/TLS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Postfix:转发邮件配置启用SSL/TLS

Postfix Version:

[root@localhost postfix]# postconf -d | grep mail_version
mail_version = 2.6.6

Postfix在收到一封邮件后,会将其通过MTA进行转发到指定邮箱服务器。

默认情况下,Postfix在转发邮件时并不适用SSL/TLS,而是传统的TCP+SMTP(Port:25)。

如何配置Postfix使其在转发邮件时自动探测目的邮件服务器是否支持SSL/TLS?并尽可能用TLS/SSL呢?

查阅Postfix官网:

http://www.postfix.org/postconf.5.html#smtp_tls_security_level
http://www.postfix.org/TLS_README.html#client_tls_may


smtp_tls_security_level (default: empty)
默认是empty,并非”may”。

when a non-empty value is specified, this overrides the obsolete parameters smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername.
有两个信息:
1) smtp_use_tls等配置项是已废弃的;
2)配置项优先级smtp_tls_security_level高于已废弃的smtp_tls_security_level等配置项;

Use TLS if this is supported by the remote SMTP server, otherwise use plaintext.
smtp_tls_security_level配置为may时,若remote SMTP server支持TLS/SSL,则使用TLS/SSL传输,否则使用传统的SMTP+TCP。

When TLS handshakes fail, the connection is retried with TLS disabled.
当TLS握手失败时,将使用without TLS/SSL重试。

The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear.

With opportunistic TLS, mail delivery continues even if the server certificate is untrusted or bears the wrong name.
即使remote SMTP server SSL/TLS证书不被信任,Postfix也会继续发送邮件。

注:

smtp_use_tls (default: no)
This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_security_level instead.

smtp_use_tls 是已废弃的配置项,请尽可能使用smtp_tls_security_level。


默认Postfix配置文件为:

/etc/postfix/main.cf

注:重启Postfix,配置文件生效。

修改配置文件,在末尾添加:

smtp_tls_security_level = may

重启Postfix:

[root@localhost postfix]# service postfix restart
Shutting down postfix:                                     [  OK  ]
Starting postfix:                                          [  OK  ]

OVER!!!

以下内容为使用libcurl发送邮件自测过程,如不感兴趣可忽略:

在未开启(smtp_tls_security_level = may)时:

Code:

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>#define FROM_ADDR    "jiangjinwang@ebupt.com"
#define TO_ADDR      "1158801411@qq.com"#define FROM_MAIL "jiangjinwang@ebupt.com"
#define TO_MAIL   "1158801411@qq.com"static const char *payload_text[] = {"To: " TO_MAIL "\r\n","From: " FROM_MAIL "\r\n","Subject: SMTP example message\r\n","\r\n", /* empty line to divide headers from body, see RFC5322 */"The body of the message starts here.\r\n","\r\n","It could be a lot of lines, could be MIME encoded, whatever.\r\n","Check RFC5322.\r\n",NULL
};struct upload_status {int lines_read;
};static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{struct upload_status *upload_ctx = (struct upload_status *)userp;const char *data;if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;}data = payload_text[upload_ctx->lines_read];if(data) {size_t len = strlen(data);memcpy(ptr, data, len);upload_ctx->lines_read++;
return len;}
return 0;
}int main(void)
{CURL *curl;CURLcode res = CURLE_OK;struct curl_slist *recipients = NULL;struct upload_status upload_ctx;upload_ctx.lines_read = 0;curl = curl_easy_init();if(curl) {/* This is the URL for your mailserver */curl_easy_setopt(curl, CURLOPT_URL, "smtp://localhost:25");/* Note that this option isn't strictly required, omitting it will result* in libcurl sending the MAIL FROM command with empty sender data. All* autoresponses should have an empty reverse-path, and should be directed* to the address in the reverse-path which triggered them. Otherwise,* they could cause an endless loop. See RFC 5321 Section 4.5.5 for more* details.*/curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_ADDR);/* Add two recipients, in this particular case they correspond to the* To: and Cc: addressees in the header, but they could be any kind of* recipient. */recipients = curl_slist_append(recipients, TO_ADDR);curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);/* We're using a callback function to specify the payload (the headers and* body of the message). You could just use the CURLOPT_READDATA option to* specify a FILE pointer to read from. */curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);/*DEBUG*/curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);/* Send the message */res = curl_easy_perform(curl);/* Check for errors */if(res != CURLE_OK)fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));/* Free the list of recipients */curl_slist_free_all(recipients);/* curl won't send the QUIT command until you call cleanup, so you should* be able to re-use this connection for additional messages (setting* CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling* curl_easy_perform() again. It may not be a good idea to keep the* connection open for a very long time though (more than a few minutes* may result in the server timing out the connection), and you do want to* clean up in the end.*/curl_easy_cleanup(curl);}
return (int)res;
}

编译 && 执行:

[ismp@localhost ssl3]$ gcc -o ssl ssl.c -lcurl
[ismp@localhost ssl3]$ ./ssl

由于libcurl开启了DEBUG模式,所以有DEBUG信息,便于观察:

* Rebuilt URL to: smtp://localhost:25/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 25 (#0)
< 220 localhost.localdomain ESMTP Postfix
> EHLO localhost
< 250-localhost.localdomain
< 250-PIPELINING
< 250-SIZE 10240000
< 250-VRFY
< 250-ETRN
< 250-ENHANCEDSTATUSCODES
< 250-8BITMIME
< 250 DSN
> MAIL FROM:<jiangjinwang@ebupt.com>
< 250 2.1.0 Ok
> RCPT TO:<1158801411@qq.com>
< 250 2.1.5 Ok
> DATA
< 354 End data with <CR><LF>.<CR><LF>
< 250 2.0.0 Ok: queued as AC68A7F996
* Connection #0 to host localhost left intact

查看Postfix日志:

/var/log/maillog

Mar  5 14:26:28 localhost postfix/smtpd[4536]: connect from localhost[::1]
Mar  5 14:26:28 localhost postfix/smtpd[4536]: AC68A7F996: client=localhost[::1]
Mar  5 14:26:28 localhost postfix/cleanup[4539]: AC68A7F996: message-id=<20180305222628.AC68A7F996@localhost.localdomain>
Mar  5 14:26:28 localhost postfix/qmgr[4444]: AC68A7F996: from=<jiangjinwang@ebupt.com>, size=488, nrcpt=1 (queue active)
Mar  5 14:26:28 localhost postfix/smtpd[4536]: disconnect from localhost[::1]
Mar  5 14:26:28 localhost postfix/smtp[4540]: connect to mx3.qq.com[240e:ff:f040:28::f]:25: Network is unreachable
Mar  5 14:26:29 localhost postfix/smtp[4540]: AC68A7F996: to=<1158801411@qq.com>, relay=mx3.qq.com[183.57.48.35]:25, delay=0.93, delays=0.02/0/0.15/0.76, dsn=2.0.0, status=sent (250 Ok: queued as ) Mar  5 14:26:29 localhost postfix/qmgr[4444]: AC68A7F996: removed

看到“Sent”,OK!!!

抓包看下:

[root@localhost ~]# tcpdump port 25 -i eth0 -s 0 -w withoutSSL.cap

用wireshark打开cap包:

withoutSSL.cap

在开启(smtp_tls_security_level = may)时:

代码不变,只修改/etc/postfix/main.cf配置文件 && 重启Postfix,然后测试:

libcurl的DEBUG输出:

* Rebuilt URL to: smtp://localhost:25/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 25 (#0)
< 220 localhost.localdomain ESMTP Postfix
> EHLO localhost
< 250-localhost.localdomain
< 250-PIPELINING
< 250-SIZE 10240000
< 250-VRFY
< 250-ETRN
< 250-ENHANCEDSTATUSCODES
< 250-8BITMIME
< 250 DSN
> MAIL FROM:<jiangjinwang@ebupt.com>
< 250 2.1.0 Ok
> RCPT TO:<1158801411@qq.com>
< 250 2.1.5 Ok
> DATA
< 354 End data with <CR><LF>.<CR><LF>
< 250 2.0.0 Ok: queued as B10387F996
* Connection #0 to host localhost left intact

Postfix Logs(/var/log/maillog):

Mar  5 14:35:20 localhost postfix/smtpd[4704]: connect from localhost[::1]
Mar  5 14:35:20 localhost postfix/smtpd[4704]: B10387F996: client=localhost[::1]
Mar  5 14:35:20 localhost postfix/cleanup[4707]: B10387F996: message-id=<20180305223520.B10387F996@localhost.localdomain>
Mar  5 14:35:20 localhost postfix/qmgr[4700]: B10387F996: from=<jiangjinwang@ebupt.com>, size=488, nrcpt=1 (queue active)
Mar  5 14:35:20 localhost postfix/smtpd[4704]: disconnect from localhost[::1]
Mar  5 14:35:20 localhost postfix/smtp[4708]: connect to mx3.qq.com[240e:ff:f040:28::f]:25: Network is unreachable
Mar  5 14:35:20 localhost postfix/smtp[4708]: certificate verification failed for mx3.qq.com[183.57.48.35]:25: untrusted issuer /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
Mar  5 14:35:21 localhost postfix/smtp[4708]: B10387F996: to=<1158801411@qq.com>, relay=mx3.qq.com[183.57.48.35]:25, delay=1, delays=0.01/0.03/0.32/0.67, dsn=2.0.0, status=sent (250 Ok: queued as )
Mar  5 14:35:21 localhost postfix/qmgr[4700]: B10387F996: removed

看到”certificate verification failed”失败没关系,Postfix即使证书不信任,但依然会发送邮件。

看到Sent,已发送邮件成功(到目的邮箱服务器)。

抓包看下:

tcpdump host 183.57.48.35 -i eth0 -s 0 -w withSSL.cap

withSSL.cap

看到了吗?协议是TLSv1.2。这个时候已经无法通过抓包来获取邮件明文内容!

其实,libcurl的DEBUG信息在本测试中并无关紧要,是由于libcurl的DEBUG信息,仅指明了libcurl(client)和本地邮局Postfix(server)之间的交互过程,无论Postfix是否配置转发启用SSL/TLS配置项,这个过程都是不变的。

libcurl(client MUA)–>postfix(server MTA)–>目的邮箱服务器(MTA,例如QQ企业邮箱,163,etc)–>MUA

这篇关于Postfix:转发邮件配置启用SSL/TLS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/845645

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res

mysql8.0.43使用InnoDB Cluster配置主从复制

《mysql8.0.43使用InnoDBCluster配置主从复制》本文主要介绍了mysql8.0.43使用InnoDBCluster配置主从复制,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录1、配置Hosts解析(所有服务器都要执行)2、安装mysql shell(所有服务器都要执行)3、

java程序远程debug原理与配置全过程

《java程序远程debug原理与配置全过程》文章介绍了Java远程调试的JPDA体系,包含JVMTI监控JVM、JDWP传输调试命令、JDI提供调试接口,通过-Xdebug、-Xrunjdwp参数配... 目录背景组成模块间联系IBM对三个模块的详细介绍编程使用总结背景日常工作中,每个程序员都会遇到bu

JDK8(Java Development kit)的安装与配置全过程

《JDK8(JavaDevelopmentkit)的安装与配置全过程》文章简要介绍了Java的核心特点(如跨平台、JVM机制)及JDK/JRE的区别,重点讲解了如何通过配置环境变量(PATH和JA... 目录Java特点JDKJREJDK的下载,安装配置环境变量总结Java特点说起 Java,大家肯定都

linux配置podman阿里云容器镜像加速器详解

《linux配置podman阿里云容器镜像加速器详解》本文指导如何配置Podman使用阿里云容器镜像加速器:登录阿里云获取专属加速地址,修改Podman配置文件并移除https://前缀,最后拉取镜像... 目录1.下载podman2.获取阿里云个人容器镜像加速器地址3.更改podman配置文件4.使用po

Vue3 如何通过json配置生成查询表单

《Vue3如何通过json配置生成查询表单》本文给大家介绍Vue3如何通过json配置生成查询表单,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录功能实现背景项目代码案例功能实现背景通过vue3实现后台管理项目一定含有表格功能,通常离不开表单

mybatis映射器配置小结

《mybatis映射器配置小结》本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定... 目录select中字段的映射问题使用SQL语句中的别名功能使用mapUnderscoreToCame

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java