在 Postfix 中使用多个“myhostname”

在 Postfix 中使用多个“myhostname”

postfix 是否允许动态更改“myhostname”?我进行了很多研究,但没有发现任何定性内容。我的安装是 postfix 多域、多 ip(在 master.cf 中调整)和多 dkim sig,但 master.cf 中的 myhostname 指令未包含在内。

这类东西:

192.168.1.12:smtp inet n - n - - smtpd -o myhostname=mail.mail2.com -o smtpd_banner=mail.mail2.com -o smtp_helo_name=mail.mail2.com

无论如何,banner 和 helo 都没问题,但是 myhostname 仍然是 main.cf 中包含的那个。

答案1

Postfix 具有高度可配置性。因此,rtfming 似乎只比阅读来源(只是开个玩笑)。

事实上,有很多方法可以动态覆盖静态配置。至少需要对 Postfix 工作流程有所了解。概述

了解以下内容也很有用:

  • 不同的 Postfix 守护进程引用main.cf 静态配置的不同部分。
  • 大多数内置的 Postfix 服务都是可定制的;
  • 特别定制服务(米尔特斯等)可以插入到工作流程中;
  • 如果一切都失败了,多个 Postfix 实例可以部署;每个都指的是单独的main.cf静态master.cf配置


按照 OP 的说法,有条件地发送邮件给某些外部收件人:

感兴趣的方法是基于以下任一条件的方法:

  • 监听smptd端口
  • 发件人域名

显然,正是在这方面,出于希望很快就能清楚的原因,Wietse Venema做了一些*关键改变在 Postfix 2.7 中内容过滤总结一下:

Postfix 2.7 之前版本:

如果未指定,默认的下一跳目的地是 $myhostname (即:)localhost


Postfix 2.7:

如果未指定,则默认的下一跳目的地是收件人域。

通过使用 sender_dependent_default_transport_maps


这种区别是有问题的,因为仍然有人停留在 2.7 之前的 Postfix 安装上。例如:对于一些依赖官方 rpm 的 Red Hat 用户,例如,仍然使用 centOS 5x => Postfix 2.3 的用户和使用 centOS 6x => Postfix 2.6 的用户(但我可能是错的,dyor 等


Postfix 2.7:

事情变得更容易了!下面是几种方法。

第一种方法是设置几个smtpd监听不同非标准端口的守护进程,并根据smtpd我们将出站电子邮件提交到哪个端口来使用自定义传输:

  • 端口 10026 => custom1_smtp
  • 端口 10027 => custom2_smtp

这是通过动态定义定制过滤服务content_filter&覆盖邮件传输协议服务。过滤器是一个虚拟的。我们实际上不会编写和部署我们自己的自定义过滤服务。相反,我们只是劫持了一个 postfixsmtp服务实例,其唯一目的是myhostname在电子邮件最终被推送到外面之前获得访问权限并动态覆盖指令。

这只能发生在 Postfix 2.7(也可能是后续版本)中,因为指定传输的默认下一跳目的地被定义为收件人域在 Postfix 2.7 以下的版本中,它被定义为$myhostname,因此电子邮件会循环回到 Postfix,从而导致其崩溃。


第二种方法是按书本和用途sender_dependent_default_transport_maps有条件地将我们的出站电子邮件路由到几个更多自定义的传输;并取决于发件人的域名:

  • parrots.tld => custom3_smtp:
  • 企鹅.tld => custom4_smtp:

就像sender_dependent_default_transport_mapssender_dependent_relayhost_maps但不是将来自指定发件人域的外发邮件路由到指定的目标域,而是sender_dependent_default_transport_maps用于在内部将来自指定发件人(域)的外发邮件路由到指定的(自定义)传输中定义master.cf


我们将以下指令添加到/etc/postfix/main.cf

sender_dependent_default_transport_maps = hash:/etc/postfix/sender_transports


然后创建映射文件/etc/postfix/sender_transports

@parrots.tld    custom3_smtp:
@penguins.tld   custom4_smtp:

使用以下方式建立数据库postmap

postmap hash:/etc/postfix/sender_transports


然后我们在以下位置定义所有自定义传输/etc/postfix/master.cf

custom4_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.penguins.tld
             -o smtp_bind_address=m.n.o.p
             -o smtp_helo_name=penguins.tld


custom3_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.parrots.tld
             -o smtp_bind_address=i.j.k.l
             -o smtp_helo_name=parrots.tld


custom2_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.cats.tld
             -o smtp_bind_address=e.f.g.h
             -o smtp_helo_name=cats.tld


custom1_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.dogs.tld
             -o smtp_bind_address=a.b.c.d
             -o smtp_helo_name=dogs.tld



# our main internal entry for the dogs site; all outgoing dogs traffic is
# sent to this (non-standard) port and routed to our custom1_smtp transport
10026             inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.dogs.tld
             -o content_filter=custom1_smtp:  


# our main internal entry for the cats site; all outgoing cats traffic is
# sent to this (non-standard) port and routed to our custom2_smtp transport
10027             inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.cats.tld
             -o content_filter=custom2_smtp:  


# default smtpd entry;  outgoing traffic sent to this port (25) will get routed 
# subject to the conditions in our sender_dependent_default_transport_maps file
smtp              inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.tld


# hoorah.
#


Postfix 2.7 之前版本:

Postfix 小精灵通常建议的方法是设置多个 Postfix 实例。

但在这里,了解 Postfix 工作流程就派上用场了。因为通过设计一个自定义 Postfix 服务链,只需一个 Postfix 实例即可实现。中无需main.cf更改任何内容。静态配置可以在我们在中定义的自定义服务链中动态覆盖master.cf

每个服务都会读取配置中所有指令的子集main.cf。因此,随着我们沿着自定义服务链前进,我们可以覆盖链中每个相应的 Postfix 服务中可能允许的任何设置。

(此外,请注意,我们甚至可以为任何默认的 Postfix 守护进程编写自己的自定义替代品。这非常酷)。


/etc/postfix/master.cf

# each Postfix service reads it's own subset of directives from main.cf config.
# many settings can be dynamically overridden as we move thro the service chain..
# here we override the $myhostname setting depending upon which port we send our 
# outgoing smtp email to.

# custom2  cats service chain 
custom2_cleanup   unix  n       -       -       -       0        cleanup             -o queue_service_name=custom2_qmgr
custom2_qmgr      fifo  n       -       n       300     1        qmgr                -o rewrite_service_name=custom2_rewrite
custom2_rewrite   unix  -       -       n       -       -        trivial-rewrite     -o default_transport=custom2_smtp:
custom2_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.cats.tld
             -o smtp_bind_address=e.f.g.h
             -o smtp_helo_name=cats.tld


# custom1 dogs service chain 
custom1_cleanup   unix  n       -       -       -       0        cleanup             -o queue_service_name=custom1_qmgr
custom1_qmgr      fifo  n       -       n       300     1        qmgr                -o rewrite_service_name=custom1_rewrite
custom1_rewrite   unix  -       -       n       -       -        trivial-rewrite     -o default_transport=custom1_smtp:
custom1_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.dogs.tld
             -o smtp_bind_address=a.b.c.d
             -o smtp_helo_name=dogs.tld


# our main internal entry for the dogs site; all outgoing dogs traffic is
# sent to this (non-standard) port and routed to our custom1 service chain
10026             inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.dogs.tld
             -o cleanup_service_name=custom1_cleanup
           # NB: attempting to override the content_filter directive 
           # *will not work* in postfix < 2.7 since an unspecified nexthop 
           # destination defaults to localhost and causes the email to loop
           # -o content_filter=custom1_smtp:  


# our main internal entry for the cats site; all outgoing cats traffic is
# sent to this (non-standard) port and routed to our custom2 service chain
10027             inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.cats.tld
             -o cleanup_service_name=custom2_cleanup

# yeehar! acu ;)
#


注释1: 需要注意的是:
虽然诸如cleanup_service_name和之类的指令rewrite_service_name 记录在配置参数,它们似乎没有被记录为任何 Postfix 的可配置选项参数守护进程?!

所以至少这看起来是一个未记录的方法,因此在官方圈子里很可能会遭到反对,甚至被视为邪恶。〜我不知道,因为我从来没有能够提出一个足够有说服力的问题来勇敢地进入[email protected]官方邮件列表!


笔记2
有一些人试图以其他富有想象力的方式来做这种事情,例如设置 header_checks FILTER 以便localhost通过动态编写完整的内容来克服默认的 nexthop 目的地transport:recipient-domain-destination

/etc/postfix/master.cf

custom2_smtp      unix  -       -       n       -       -        smtp
             -o myhostname=mailer.external.cats.tld
             -o smtp_bind_address=e.f.g.h
             -o smtp_helo_name=cats.tld

custom2_cleanup   unix  n       -       -       -       0        cleanup 
             -o header_checks=regexp:/etc/postfix/custom2_header_checks

#conditional processing contingent upon entry via some non-standard port
10027             inet  n      -        n       -       -        smtpd
             -o myhostname=mailer.internal.cats.tld
             -o cleanup_service_name=custom2_cleanup


然后在中/etc/postfix/custom2_header_checks,使用正则表达式将收件人域从标头字段中拉出,并将其提供给过滤器指令,如下所示:

/^To:.*@(.*)$/      FILTER    custom2_smtp:$1

虽然这看起来是个好主意,并且部分可行,但它无疑是一种可怕的黑客攻击;具有潜在的不安全性,并且至少在发送的电子邮件包含多个收件人时会失败。咄!


注释3
如果以上内容都没有任何意义,那么您可能需要做更多的 rtfming ;)

但说真的,我知道这里有很多东西。由于各种我无法控制的原因,这生意停留在 Postfix 2.3 上,我需要花超过 5 分钟的时间来整理他们的要求;以至于我的小时费率已经下降到哥斯达黎加菠萝采摘者(只有我不要受益于他们的哥斯达黎加生活)。所以我试着趁着记忆犹新的时候把这一切都说清楚,而不是鹦鹉学舌地重复官方文件;希望这样可以帮助下一个走上这条特殊道路的可怜人;)

答案2

经过大量测试,我必须得出结论,您无法做到这一点。可以动态更改 myhostname,但它不会影响 Received 标头。

使用 $myhostname 进行横幅测试后,我可以看到当我使用时它会发生变化

-o myhostname=test.test.test

但收到的标头却没有。

我尝试在 main.cf 中使用

mydomain=test.test.test
myhostname=$mydomain

这确实会影响已接收标头和横幅。但尝试覆盖 $mydomain

-o mydomain=test.test.test

只会再次影响横幅。

因此,似乎 Received 标头中使用的变量是由 $myhostname 填充的从命令行参数覆盖 $myhostname。

相关内容