跳转到主要内容

于 2025年04月22日 摘录自 Postfix IPv6 Support

简介

Postfix 2.2 引入了对 IPv6(IP 版本 6)协议的支持。对于较旧的 Postfix 版本,IPv6 支持可通过附加补丁获取。下文的"与 Postfix <;2.2 IPv6 支持的兼容性"部分将讨论这些实现之间的差异。

IPv6 的主要特点是使用 128 位 IP 地址,而非 IPv4 使用的 32 位地址。因此,它能够支持数量庞大的主机和网络,无需借助 NAT 等复杂技术。更大的地址空间还带来一个额外好处:随机网络扫描变得不切实际。

Postfix 在 IPv6 上使用与 IPv4 网络相同的 SMTP 协议,并在 DNS 中除了查询旧的 A 记录外,还会查询 AAAA 记录。有关 IPv6 的更多信息,请参阅 http://www.ipv6.org/

本文档提供了以下主题的信息:

支持的平台

Postfix 版本 2.2 在以下平台上支持 IPv4 和 IPv6:

  • AIX 5.1+
  • Darwin 7.3+
  • FreeBSD 4+
  • Linux 2.4+
  • NetBSD 1.5+
  • OpenBSD 2+
  • Solaris 8+
  • Tru64Unix V5.1+

在其他平台上,Postfix 将继续使用 IPv4,与以往一致。

请参阅"不支持 IPv6 的平台上的 IPv6 支持"以获取将 Postfix IPv6 支持移植到其他环境的提示。

配置

Postfix IPv6 支持引入了两个新的 main.cf 配置参数,并在匹配列表(如 mynetworksdebug_peer_list

Postfix 的 IPv6 地址语法有点复杂,因为有几个地方必须将 IPv6 地址用 "[]" 字符包围,而另一些地方则不能这样做。建议仅在必须使用 "[]" 的少数情况下使用。在进行与 IPv6 相关的 Postfix 配置工作时,请随时查阅 postconf(5) 手册。

  • master.cf 中硬编码 127.0.0.1 和 ::1 回环地址,请在 main.cf 中指定 "inet_interfaces = loopback-only"。这样,无论 Postfix 是否在支持 IPv6 的系统上运行,都可以使用相同的 master.cf 文件。
  • 第一个新参数称为inet_protocols。该参数指定 Postfix 在建立或接受网络连接时使用的协议,同时控制 Postfix 在建立网络连接时使用的 DNS 解析方式。

    /etc/postfix/main.cf:
    # 修改此参数后必须重启 Postfix。
    inet_protocols = all(启用 IPv4,如果支持则启用 IPv6)
    inet_protocols = ipv4 (仅启用 IPv4)
    inet_protocols = ipv4, ipv6 (启用 IPv4 和 IPv6)
    inet_protocols = ipv6(仅启用 IPv6)
    

    默认值取决于编译时环境: 当 Postfix 在支持 IPv6 的软件发行版上构建时为 "all",否则为 "ipv4"。

    注释 1:修改 inet_protocols 配置参数后,必须停止并重新启动 Postfix。

    注释 2:在较旧的 Linux 和 Solaris 系统上,设置 "inet_protocols = ipv6" 并不会阻止 Postfix 接受 IPv4 连接。

    若要使用不支援的測試選項來編譯不支援 IPv6 的 Postfix,請參閱 INSTALL 文件中的 NO_IPV6 選項。

  • 另一个新参数是 smtp_bind_address6。该参数用于设置出站 IPv6 SMTP 连接的本地接口地址,与 smtp_bind_address 参数对 IPv4 的作用相同:

    /etc/postfix/main.cfsmtp_bind_address6 = 2001:240:587:0:250:56ff:fe89:1
    
  • 如果您将mynetworks参数的值保留为默认值(即 未在 main.cf 中设置 mynetworks)Postfix 将自行确定其网络地址。以下是一个典型的设置示例:

    % postconf mynetworks
    mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001:240:587::]/64 
    

    如果你在 main. cf 中指定了 mynetworks 参数值,则需要更新 mynetworks 的值,以包含系统所在的 IPv6 网络。请确保将 IPv6 地址信息包含在 "[]" 中,例如:

    /etc/postfix/main.cfmynetworks = ...IPv4 网络... [::1]/128 [2001:240:587::]/64 ...
    

注意:在配置 Postfix 匹配列表(如 mynetworksdebug_peer_list时,必须在 "[]" 中指定 IPv6 地址信息,并在以 "/file/name" 模式指定的文件中。 cf参数值中,并在以 "/file/name" 模式指定的文件中。IPv6 地址包含 ":" 字符,否则会与 "type:table" 模式混淆。 ;

已知限制

  • Postfix SMTP 客户端在版本 2.8 之前会尝试通过 IPv6 连接,然后再尝试 IPv4。在较新的 Postfix 版本中,IPv6 与 IPv4 的出站连接尝试顺序可通过 smtp_address_preference 参数进行配置。
  • Postfix 2.6 之前的版本不支持对 IPv6 客户端 IP 地址进行 DNSBL(DNS 阻塞列表)查询。
  • IPv6 没有 A、B、C 等类型的网络。在 IPv6 网络中,设置 "mynetworks_style = class" 与设置 "mynetworks_style = subnet" 效果相同。
  • 在 Tru64Unix 和 AIX 系统上,Postfix 无法自动识别本地子网掩码,并始终假设网络为 /128。此问题仅在 "mynetworks_style = subnet" 且在 main.cf 中未显式设置 mynetworks 时出现。

与 Postfix <;2.2 IPv6 支持的兼容性

Postfix 2.2 版本的 IPv6 支持基于 Dean Strik 等人开发的 Postfix/IPv6 补丁,但在某些细节上有所不同。

  • main.cfinet_interfaces 参数不支持 "ipv6:all" 或 "ipv4:all" 这种表示方式。请改用 inet_protocols 参数。
  • main.cf:指定 "inet_protocols = all" 或 "inet_protocols = ipv4, ipv6" 以启用 IPv4 和 IPv6 支持。
  • main.cfinet_protocols 参数还控制 Postfix 在发送或接收邮件时尝试进行的 DNS 解析。
  • main.cf:指定 "inet_interfaces = loopback-only" 以仅监听回环网络接口。
  • lmtp_bind_addresslmtp_bind_address6 功能已被省略。Postfix 2.3 版本将 LMTP 客户端合并到 SMTP 客户端中,因此没有必要继续为 LMTP 客户端添加功能。
  • SMTP 服务器现在要求 SMTP 命令中的 IPv6 地址以 [ipv6:ipv6address] 格式指定,如 RFC 2821 中所述。
  • IPv6 网络地址匹配代码已从头重写,预计将更符合规范。此更改可能与 Postfix/IPv6 补丁不兼容。

未支持平台的 IPv6 支持

在其他平台上使 Postfix IPv6 正常工作涉及以下步骤:

  • 指定 Postfix 如何查找本地网络接口。Postfix 需要此信息以避免邮件循环并确定 user@[ipaddress] 的邮件是本地还是远程目的地。

    如果您的系统具有 getifaddrs() 例程,请在 src/util/sys_defs.h 文件的系统特定部分添加以下内容:

    #ifndef NO_IPV6
    # define HAS_IPV6
    # define HAVE_GETIFADDRS
    #endif
    

    否则,如果您的系统在 /usr/include/*/*.h 中包含 SIOCGLIF ioctl() 命令,请在 src/util/sys_defs.h 文件的系统特定部分添加以下内容:

    #ifndef NO_IPV6
    # define HAS_IPV6
    # define HAS_SIOCGLIF
    #endif
    

    否则,Postfix 将不得不使用旧的 SIOCGIF 命令,并忍受 IPv6 功能受限(它将无法识别您的 IPv6 子网掩码,而这些掩码对于 "mynetworks_style = subnet" 设置是必要的)。在 src/util/sys_defs.h 文件的系统特定部分添加以下内容:

    #ifndef NO_IPV6
    # define HAS_IPV6
    #endif
    
  • 测试 Postfix 是否能正确识别接口信息。

    在以常规方式编译 Postfix 后,进入 src/util 目录并输入 "make inet_addr_local"。手动运行此文件应生成所有接口地址和网络掩码,例如:

    % make
    % cd src/util
    % make inet_addr_local
    [... 部分输出 ...]
    % ./inet_addr_local
    [... 一些消息 ...]
    ./inet_addr_local: inet_addr_local: 配置了 2 个 IPv4 地址
    ./inet_addr_local: inet_addr_local: 配置了 4 个 IPv6 地址
    168.100.189.2/255.255.255.224
    127.0.0.1/255.0.0.0
    fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
    2001:240:587:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
    fe80:5::1/ffff:ffff:ffff:ffff::
    ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
    

    以上内容适用于旧版 FreeBSD 系统。其他系统可能会产生略微不同的结果,但基本原理相同。

如果以上所有方法均无法获得可用结果,请发送邮件至 [email protected] 邮件列表,我们将尽力协助您解决问题。

致谢

以下信息部分基于 Dean Strik 整理的资料。

  • Mark Huizer 编写了原始的 Postfix IPv6 补丁。
  • KAME 项目的 Jun-ichiro 'itojun' Hagino 进行了重大改进。此后,我们称之为 KAME 补丁。
  • PLD Linux发行版将代码移植到其他堆栈(尤其是USAGI)。我们称之为PLD补丁。PLD补丁的一个非常重要的特性是,它可以与Lutz Jaenicke为Postfix开发的TLS补丁配合使用。
  • Dean Strik 将 IPv6 支持扩展到 KAME 和 USAGI 以外的平台,更新了补丁以跟上 Postfix 的开发进度,并提供了一个结合 IPv6 + TLS 的补丁。有关他的工作详情,可访问 Dean Strik 的 Postfix 网站:http://www.ipnet6.org/postfix/
  • Wietse Venema 采用了 Dean Strik 的 IPv6 补丁,将其合并到 Postfix 2.2 中,并借此机会移除了 Postfix 中所有可移除的 IPv4 特定代码。对于内核和系统库中不支持 IPv6 的系统,Postfix 提供了一个简单的兼容性层,因此它将像以前一样使用 IPv4。