最近遇到了一个DMZ区服务器出向访问Internet公网的故障,故障大致是最外层ADS封禁公网DNS地址导致F5 LC出向健康检查失败,进而引起DMZ无法访问公网。当然ADS封禁DNS本质上也阻断了DMZ区服务器解析,属于是“一石二鸟”了。。。。。
正好借此机会把F5 LC的出向负载思路整理一下,尽量谈它的负载逻辑,提供一个配置和排错的思路。多运营商接入的数据中心中,看看网工是怎么帮你在出站访问时,选择最佳的链路。
这里也推荐一篇文章《F5 LC outbound配置总结》,写得很详细F5 LC outbound配置总结_年轻人,少吐槽,多搬砖的技术博客_51CTO博客
一、架构举例
上图左边是F5设备在互联网接入区的一种组网架构,GTM-LC-LTM,GTM可能现在叫智能DNS,上图右侧服务器通过LC访问三条运营商线路,三条运营商线路和LC之间串联二层FW/ADS。在实践中,需要考虑isp网关、isp网段集class、网关pool及monitor、snat-ip,并用iRules将其串起来。
本文主要探讨服务器通过LC做多链路出向的部分。
二、outbound链路负载思路
对于服务器出向访问来讲,基本可以归纳成如下4个问题:
- 服务器私网源地址、公网目的地址是什么?
- 选择哪个运营商(IPS线路)出访?
- 服务器的私网源地址转换成哪个公网地址出访?
- 特别需求:例如ISP故障时期的自动切换怎么处理?例如允许哪些服务器出访?
这4个问题,也是整个F5 LC做Outbound链路负载的基本逻辑思路。
三、链路负载均衡outbound数据流的流程图
以一台服务器4.4.4.4,需要访问LT运营商的地址2.2.254.2为例。
1.服务器出访公网
4.4.4.4访问2.2.254.2,源地址是4.4.4.4,公网目的地址为2.2.254.2公网,当然DMZ区服务器的出网路由首先指向LC,这毋庸置疑
2.命中出向VS进入iRules
进入LC后,命中出向VS,然后进入iRules,这是负载的关键:访问LT运营商,我就需要让源地址转化成LT运营商的ip
3.判断目的地址确定转发Pool
这里我们知道2.2.254.2属于class_lt这个地址集,因此需要iRule触发CLIENT_ACCEPT事件判断,丢向pool_lt_first
4.根据链路负载机制确定转发Member
这里丢向优先级最高的2.2.2.6网关,如果2.2.2.6网关不可达(这里用monitor判断,见第四节),就丢向次优先级的1.1.1.6网关,以此类推。这里我们以丢向2.2.2.6Member为例
5.根据转发Member确定链路
好了既然我们知道Member是2.2.2.6了,那这个网关是ISP-LT的网关,自然选用ISP-LT链路
6.判断转发链路和源地址
但在丢给运营商前,我们需要做一次限制源地址的判断。虽然我们知道这个数据包是丢向公网的,但这个服务器是不是在我们允许出访的范围内呢?因此这里做一次iRules出访LB_SELECTED事件判断源地址,是在class-outbound范围内的服务器我们就转发,如果不是就reject
7.源地址转换
在iRules中,我们继续将源地址SNAT成对应运营商的nat-ip,丢给运营商网关
这里贴一下iRules
when CLIENT_ACCEPT {
if { [class match [IP::local_addr] equals class_dx] } {
pool pool_dx_first
}
elseif { [class match [IP::local_addr] equals class_lt] } {
pool pool_lt_first
}
elseif { [class match [IP::local_addr] equals class_yd] } {
pool pool_yd_first
}
else {
pool pool_dx_first
}
}
when LB_SELECTED {
set gw_dx 1.1.1.6
set gw_lt 2.2.2.6
set gw_yd 3.3.3.6
if { [IP::addr [LB::server addr] equals $gw_dx] } {
if { [class match [IP::client_addr] equals class_outbound] } {
snat 1.1.1.1
}
}
elseif { [IP::addr [LB::server addr] equals $gw_lt] } {
if { [class match [IP::client_addr] equals class_outbound] } {
snat 2.2.2.1
}
}
elseif { [IP::addr [LB::server addr] equals $gw_yd] } {
if { [class match [IP::client_addr] equals class_outbound] } {
snat 3.3.3.1
}
}
else {
reject
}
}
四、总结
1.服务器私网源地址、公网目的地址是什么?
这里其实主要做的是对于LC之前的交换机层面的出向路由控制,以及LC 0.0.0.0/0这个特殊的VS捆绑pool-default-gateway,这个可以参考F5BIG-IPLC标准配置文档-20221021.docx了解
2.选择哪个运营商(IPS线路)出访?
这里主要靠iRules判断目的地址属于某个运营商的地址集class,来分发给这个运营商关联的网关pool。
3.服务器的私网源地址转换成哪个公网地址出访?
这个依旧靠iRules判断负载到的member ip,属于哪个运营商,就给他snat成对应运营商的某个网段内ip。这里其实可以做的很巧妙,鉴于网关pool其实可以利用优先级的方式添加冗余member ip网关,这样选择运营商和私网源地址到底snat哪个ip,就可以做到解耦,利用两个iRules事件CLIENT_ACCEPT、LB_SELECTED,分开处理即可。
4.特别需求:例如ISP故障时期的自动切换怎么处理?例如允许哪些服务器出访?
isp线路自动切换这个主要靠网关pool健康检查,当某个网关member ip的健康检查down,这条线自然就不会被负载到。这里对于Health Monitors其实有一些细节:
- 健康检查建议做3个或以上的健康检查,并且至少通过2个健康检查才Available
- 健康检查建议icmp检查网关,配合多个icmp检查dns(不要ping114.114.114.114,部分运营商上禁ping114的,很坑)
- ping dns的健康检查一定要勾选transparent,强制走检测线路,避免走缺省路由
- 服务器配置的dns最好和健康检查配置的dns一致,这样某条线路的dns不可达,在服务器和LC层面反映是一致的
允许哪些服务出访,就是利用iRules,在数据包源地址被snat前判断这个私网源地址是否属于可访问datagroup list。