我创建了一个相当简单的端口转发规则,将对端口 25 的请求重定向到虚拟环境中的特定容器:
iptables -t nat -A PREROUTING -p tcp --dport 25 -j DNAT --to 10.10.10.4
转发似乎正在工作。当我通过 telnet 从外部访问它时,我可以到达目标邮件服务器:
telnet mail.mydomain.tld 25
Trying 1.2.3.4...
Connected to mail.mydomain.tld.
Escape character is '^]'.
220 mail.mydomain.tld ESMTP Postfix (Ubuntu)
quit
221 2.0.0 Bye
然而,当我从运行 Postfix 的目标容器中运行到 Gmail 的跟踪路由时,却无果而终。最终结果是所有非本地邮件投递都因 4.3.0 DSN 代码而延迟。
当我从 PREROUTING 链中删除上述 iptables 端口转发规则时,traceroute 会一直跳到目标 IP。
这是我正在使用的确切的跟踪路由命令:
traceroute -n -T -p 25 gmail-smtp-in.l.google.com
我最好的猜测是,我遗漏了 INPUT 链中的一些规则。但如果是这样的话,我不明白为什么从外部进行 telnet 会起作用。
现在我在 INPUT 链中没有任何规则(实际上不记得在这个特定环境中需要任何规则)。
我读到过,添加下面的规则可以解决这个问题,但我还没有尝试,以免产生一些不良后果。毕竟这是一个生产环境。
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
答案1
我创建了一个相当简单的端口转发规则,将对端口 25 的请求重定向到虚拟环境中的特定容器:
iptables -t nat -A PREROUTING -p tcp --dport 25 -j DNAT --to 10.10.10.4
它实际上太简单了,无法正常工作:它会拦截任何端口 25 目标...包括从容器到外部世界的连接,这些连接被重定向回容器。通常,容器的网络堆栈将看到来自外部的自己的 IP 地址,从自己的 IP 地址发送到自己的 IP 地址,并将其丢弃(没有进行 NAT 发夹),这比它可以工作要好:如果 SMTP 的配置允许这样的请求,容器中的服务器将循环回到自身,尝试路由电子邮件,但永远不会到达除自身之外的任何其他东西。
添加一个额外的过滤器来防止这种情况发生。它可以是每个接口或每个地址,取决于您的布局和意图。从问题的可用信息来看,为容器的 IP 本身添加例外可能就足够了。而不是使用初始规则:
iptables -t nat -A PREROUTING ! -s 10.10.10.4 -p tcp --dport 25 -j DNAT --to 10.10.10.4
这仍将拦截发送到主机的正确路由的 SMTP 流量并将其发送到容器,但容器的 SMTP 服务器现在将能够通过正确到达下一个 SMTP 服务器来转发此类电子邮件。这对主机本身不起作用(nat/OUTPUT
应该使用)。如果您遇到主机本身的问题或需要拦截主机的查询,则需要进行其他设置。