多 ISP

来自 Alpine Linux

本文档描述了如何配置您的 Alpine Linux 路由器以使用多个 ISP,无论是否具有故障转移和负载均衡功能。

请注意: 需要 Alpine Linux v2.4.4 或更高版本。

接口 名称 IP 地址 描述
eth0 ISP1 DHCP 具有静态 IP 地址的互联网 (我们将使用 1.2.3.4/24 和 gw 1.2.3.1 作为示例)
eth1 DMZ 192.168.0.1 隔离区
eth2 LAN 192.168.1.1 本地网络
eth3 ISP2 DHCP 具有动态 IP 地址的互联网。

网络接口

如果存在多个静态 IP 地址,或者更准确地说,如果存在多个默认网关,则必须指定一个metric 值。指标值最低的网关将胜出。

/etc/network/interfaces:

auto eth0
iface eth0 inet static
  address 1.2.3.4
  netmask 255.255.255.0
  gateway 1.2.3.1
  metric 200

DHCP 客户端将自动为默认网关添加一个指标值。它将选择 200 + 接口索引。因此,对于 DHCP,我们无需担心这一点。

auto eth3
iface eth0 inet dhcp

对于 PPP 接口,有一个 defaultroute-metric 选项可以设置指标值。

Shorewall 区域

/etc/shorewall/zones 中,创建区域

INET    ipv4
DMZ     ipv4
LAN     ipv4

Shorewall 接口

我们需要让 shorewall 知道第二个 ISP 接口。在 /etc/shorewall/params 中,在 ISP2 下添加 ISP1。

ISP1_IF=eth0
ISP2_IF=eth3
DMZ_IF=eth1
LAN_IF=eth2

将其添加到 /etc/shorewall/interfaces

INET	$ISP1_IF	detect	dhcp
INET	$ISP2_IF	detect	dhcp
DMZ	$DMZ_IF	        detect	dhcp
LAN	$LAN_IF	        detect	dhcp

除非实际使用 dhcp,否则 dhcp 选项不是真正需要的。我们建议保留 dhcp 选项,以防 ISP 更改为 DHCP。

Shorewall 地址伪装

我们必须对互联网地址进行地址伪装,以便每个 ISP 获得正确的源地址。这在 /etc/shorewall/masq 中完成。

$ISP1_IF	0.0.0.0/0
$ISP2_IF	0.0.0.0/0

Shorewall 策略

我们通过在 /etc/shorewall/policy 中添加一个丢弃策略来禁止 2 个 ISP 之间的路由。

...
INET    INET    DROP
...

Shorewall 提供商

/etc/shorewall/providers 定义了 2 个 ISP,并允许防火墙数据包标记(防火墙可以标记某些数据包,这些数据包稍后可用于路由决策)。Shorewall 还将让防火墙标记传入的连接,以便跟踪响应应通过哪个网关发送。如果您对辅助 ISP 上的传入流量进行 DNAT,则这是必需的。如果没有连接跟踪,则传出流量将始终通过主 ISP 发送。


我们希望 shorewall 干预路由表(在旧版本的 pingu 中我们需要它这样做)。我们可以通过将 DUPLICATE 列设置为 '-',将 GATEWAY 列设置为 'none',并留空 COPY 列来告诉 shorewall 不要刷新 pingu 将管理的路由表。

在本示例中,eth0 连接到 ISP1,eth3 连接到 ISP2。

#NAME   NUMBER  MARK    DUPLICATE       INTERFACE    GATEWAY     OPTIONS                 COPY
ISP1	1       1       -               eth0         none        track,optional,loose
ISP2	2       2       -               eth3         none        track,optional,loose

重启 shorewall 后,应该可以使用命令 ip rule 查看防火墙标记的路由规则

...
10001:	from all fwmark 0x1 lookup ISP1 
10002:	from all fwmark 0x2 lookup ISP2 
...

Shorewall 路由规则

我们还使用 /etc/shorewall/route_rules 来设置一些静态路由规则。这是为了强制本地流量忽略 ISP 的备用路由表。

#SOURCE			DEST			PROVIDER	PRIORITY
# prevent local traffic go via providers' route tables
-			192.168.0.1/24		main		1000
-			192.168.1.1/24		main		1000

使 Shorewall 不触碰默认网关

Shorewall 将在启动时存储默认网关,并在停止时尝试恢复。不幸的是,它做得不好,导致在停止时丢失默认网关。此外,默认网关可能在运行时已更改,这是由于 dhcp 租约续订。我们需要配置 shorewall 完全不处理默认网关,而让 pingu 处理此问题。

将以下内容添加到 /etc/shorewall/shorewall.conf

RESTORE_DEFAULT_ROUTE=No

使用 Pingu 的策略路由

我们需要确保在使用 ISP1 的 IP 地址作为源地址时,必须使用 ISP1 的默认网关。否则,我们可能会通过 ISP2 发送具有 ISP1 IP 源地址的数据包。响应将通过 ISP2 的接口到达,防火墙将阻止。

由于 IP 地址和默认网关可能会更改(DHCP 租约续订),我们需要一个守护程序来监视通过接口的网关的源地址。这就是 pingu 所做的。

apk add pingu

我们在 /etc/pingu/pingu.conf 中配置 pingu 以监视我们的 eth0 和 eth3 接口

interface eth0 { 
  # route-table must correspond with NUMBER column in /etc/shorewall/providers
  route-table 1
  # the rule-priority must be a higher number than the priority in /etc/shorewall/route_rules
  rule-priority 20000
}
interface eth3 {
  # route-table must correspond with NUMBER column in /etc/shorewall/providers
  route-table 2
  rule-priority 20000
}

当 pingu 启动时,您应该能够使用以下命令查看路由规则

ip rule
...
20000:	from 1.2.3.4 lookup ISP1 
20000:	from 192.168.254.4 lookup ISP2 
...

并使用以下命令查看 ISP 路由表

ip route show table 1
default via 1.2.3.1 dev eth0  metric 200
1.2.3.0/24 dev eth0  proto kernel  scope link  metric 200 

使用 Pingu 的互联网故障转移

要进行故障转移,我们需要一种方法来检测 ISP 是否仍然在线。我们配置一些主机,pingu 将定期为我们 ping 这些主机。当主机停止响应时,我们认为该主机已离线。我们可以将 ping 主机绑定到 pingu 中的接口,当足够多的主机停止响应时,pingu 将从主路由表中删除该网关,并且指标值较低的网关将接管。我们通常希望 ping 多个主机,因为单个主机可能会宕机,但这并不意味着互联网的其余部分都宕机了。

我们还希望选择不太可能更改的主机。DNS 服务器在这方面表现良好。它们很少更改,因为这将需要所有客户端进行重新配置。在本示例中,我们将使用 Google 的 DNS 和 OpenDNS 主机。

将主机添加到 /etc/pingu/pingu.conf 并绑定到主 ISP。我们还将 ping 超时设置为 2.5 秒。

...
# Ping responses that takes more than 2.5 seconds are considered lost.
timeout 2.5
# ping google dns via ISP1
host 8.8.8.8 {
  interval 60
  bind-interface eth0
}
# ping opendns via ISP1
host 208.67.222.222 {
  interval 60
  bind-interface eth0
}

现在,如果两个主机都停止响应 ping,则 ISP-1 将被视为已关闭,并且通过 eth0 的所有网关都将从主路由表中删除。请注意,网关不会从路由表 '1' 中删除。这是为了我们可以继续尝试通过 eth0 进行 ping,以便我们可以检测到 ISP 重新联机。当 ISP 重新开始工作时,网关将再次添加回主路由表。

负载均衡

通过使用多路径路由,可以给人留下负载均衡的印象。它不会让 http 文件下载使用两个 ISP 来获得双倍的下载速度,但它会让一些用户通过 ISP1 浏览,而另一些用户通过 ISP2 浏览,从而使带宽使用量分散在两个 ISP 上。

请注意,负载均衡不会是完美的,因为它是基于路由的,并且路由会被缓存。这意味着到常用站点的路由将始终通过同一提供商。这也意味着源 IP 可能会更改,因此需要登录的网站(网络邮件、银行等)如果检查客户端 IP 是否一致,则会中断。银行站点经常这样做。如果可能,建议避免使用此功能

要启用负载均衡,只需将 'load-balance' 关键字添加到 /etc/pingu/pingu.conf 中应进行负载均衡的所有接口。


interface eth0 {
  ...
  load-balance
}
interface eth3 {
  ...
  load-balance
}
...