我有一个装有 centos7 的 HAProxy 盒,为 smtp 集群做负载平衡代理,为我们的客户提供邮件中继。
default gateway => 10.0.0.1
master-relay.example.net => 10.0.0.254
relay1.example.net => 10.0.0.10 | gateway 10.0.0.1
relay2.example.net => 10.0.0.11 | gateway 10.0.0.1
relay3.example.net => 10.0.0.12 | gateway 10.0.0.1
每个中继都将后缀配置为侦听端口 25 和 587。
我需要实现的是,当任何人尝试发送直接连接到 3 个中继(中继 1、中继 2 或中继 3)之一的邮件时,将应答数据包转发到默认网关。这通常发生在任何外部邮件服务器尝试向我们发送电子邮件并随机连接到具有相同优先级的 3 个 MX 服务器之一时。
但是,当移动或网络邮件客户端连接到集群以中继电子邮件时,它会中继到主中继,并且该客户端会连接到 3 个 MX 服务器之一来传递邮件。
这是集群的 HAProxy 配置:
# Puerto 25 - SMTP (Postfix Cluster)
frontend frontend-smtp-25
bind 10.0.0.254:25 transparent
option tcplog
default_backend backend-smtp-25
backend backend-smtp-25
option tcplog
source 0.0.0.0 usesrc clientip
server mx1 10.0.0.10:25 check
server mx2 10.0.0.11:25 check
server mx3 10.0.0.12:25 check
# Puerto 587 - STARTTLS (Postfix Cluster)
frontend frontend-smtp-587
bind 10.0.0.254:587 transparent
option tcplog
default_backend backend-smtp-587
backend backend-smtp-587
option tcplog
source 0.0.0.0 usesrc clientip
server mx1 10.0.0.10:587 check
server mx2 10.0.0.11:587 check
server mx3 10.0.0.12:587 check
内核参数:
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.ip_local_port_range = 1025 65535
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
防火墙规则:
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
现在,通过此配置,如果我将中继盒的默认网关更改为主中继网关,一切都会正常,并且在 postfix 日志中我可以看到客户端的 IP 地址,而不是主中继的 IP 地址,但这里我有一个问题,如果任何人都直接连接到relay1,例如这个通过主中继而不是通过网关应答,并且客户端丢弃数据包,因为不是来自relay1盒子。
我试图做的是在所有 3 个中继盒上标记主中继的源 mac 地址,并且所有与标记匹配的内容都会将默认网关更改为主中继的网关。
所有 IP 都是公共 IP,并且都可以从互联网上看到。
我能做的就是将 2 个 IP 放在同一个接口中,如果有任何数据包到达 IP1,则回复一个网关,如果到达 IP2,则回复另一个网关,但如果可能的话,我真的更喜欢 mac 规则。
我无法制定规则来强制如果数据包来自主中继 IP 地址,则再次回复它,因为它将使用客户端 IP 地址到达代理。
提前致谢
答案1
relay1
以下是中继(即、relay2
或)作为网关relay3
正确处理通过default-gateway
( 10.0.0.1
) 或透明模式下通过 HAProxy master-relay
( )的流量的目标和方法:10.0.0.254
中继应使用正常网关
default-gateway
进行正常流量,即:- 本地发起的流量,
- 已通过的远程发起流量的出站回复
default-gateway
。
中继应使用
master-relay
HAProxy 透明中继流量的备用网关,因此仅适用于:master-relay
已通过充当备用网关的远程发起流量的出站回复。
区分路由情况 1. 和情况 2. 的选择器是备用网关的源 MAC 地址
master-relay
。这么说吧02:03:04:05:06:07
。一旦在连接的第一个数据包上完成选择,该选择就应该对该连接的所有其他数据包部分保持相同。
这需要策略路由,具有备用路由表(ip route add table ...
,附加路由决策(ip rule add fwmark...
)依赖于iptables
使用mac
MAC地址选择器的匹配模块,MARK
改变路由决策的目标,以及CONNMARK
目标是记住整个连接的决定。
情况 1. 是没有特殊处理的默认情况,而情况 2. 是例外,您应该default-gateway
像往常一样恢复路由更改,以用作默认网关:
ip route replace default via 10.0.0.1
情况2.将被存储在备用路由表中。不用命名,任何数字都可以,让我们选择1000254
(254
已保留,这是主表...):
ip route add table 1000254 default via 10.0.0.254
iptables
使用它的路由决策将由标记值(来自的目标)触发MARK
。让我们选择254
:
ip rule add fwmark 254 lookup 1000254
可以看出Netfilter 和通用网络中的数据包流、或iptables
中的规则可以在路由决策(或重新路由检查)完成之前设置标记。这就是最终改变路线的方式。因此,对于单个传入数据包,这将是:mangle/PREROUTING
mangle/OUTPUT
iptables
iptables -t mangle -A PREROUTING -m mac --mac-source 02:03:04:05:06:07 -j MARK --set-mark 254
现在要记住整个连接,它应该用CONNMARK
调用,它在该流的 conntrack 条目中存储和检索标记,并允许仅在第一次设置它,而不会忘记 OUTPUT 方向。一些解释在这个博客中:Linux 及更高版本! Netfilter康马克。无需标记 LAN 流量的数据包,因此将其过滤掉(这conntrack -L
在最后使用 see 时会有所帮助)。最后,包括之前的规则,它变成:
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN
iptables -t mangle -A PREROUTING ! -s 10.0.0.0/24 -m mac --mac-source 02:03:04:05:06:07 -j MARK --set-mark 254
iptables -t mangle -A PREROUTING -j CONNMARK --save-mark
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
就是这样。这种情况甚至不需要设置rp_filter
松散模式,因为只涉及一个网络接口。
请注意,如果您需要冗余,您可以轻松插入更多表、规则和标记以拥有多个表、规则和标记(或者如果其 IP 可能因某种原因更改其 MAC 地址,master-relay
则只需添加一个额外的 MAC )。具有 IP和 MAC 的master-relay
附加 HAProxy 示例:10.0.0.250
0A:09:08:07:06:05
ip route add table 1000250 default via 10.0.0.250
ip rule add fwmark 250 lookup 1000250
iptables -t mangle -I PREROUTING 4 ! -s 10.0.0.0/24 -m mac --mac-source 0A:09:08:07:06:05 -j MARK --set-mark 250
conntrack -L
将显示 connmark,因此可用于区分连接是否通过master-relay
而不是默认连接,因为它的标记将254
代替0
:
# conntrack -L -s 198.51.100.1
tcp 6 431635 ESTABLISHED src=198.51.100.1 dst=10.0.0.10 sport=50230 dport=25 src=10.0.0.10 dst=198.51.100.1 sport=25 dport=50230 [ASSURED] mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1
tcp 6 431527 ESTABLISHED src=198.51.100.1 dst=10.0.0.10 sport=49554 dport=25 src=10.0.0.10 dst=198.51.100.1 sport=25 dport=49554 [ASSURED] mark=254 secctx=system_u:object_r:unlabeled_t:s0 use=1
conntrack v1.4.4 (conntrack-tools): 2 flow entries have been shown.