F5 V9 LC Outbound 配置总结


本文只涉及到链路负载均衡的outbound部分,针对用户外出访问internet的多种情况一一进行描述,其目的是为大家建立一个通用的标准LC outbound配置模板,方便今后大家讨论。也许其中的很多功能,我们可以用别的方法解决或者F5别的功能实现,但我们希望通过建立一个规范的处理流程来帮助大家更好的理解F5 v9的设计理念,以及一个标准的分析流程。

在具体讲述outbound的设置的之前,大家现看一下一个标准的ourbount case中的rule 内容:

(本case 共有七条链路的outbound的负载均衡,现将原有的irule简化)


rule out_rule {

# outbound rule 通过判定用户的源IP和目标IP来确定用户外出的gateway地址(即ISP地址),所有外出的数据均会命中且只会命中下面的一个条件,所以F5的工程师的任务就是把用户描述转变成如下的条件判定流程!!


when CLIENT_ACCEPTED {

if { [IP::addr [IP::local_addr] equals 10.200.3.0/255.255.255.0 ] } {

    forward

}

elseif { [ matchclass [IP::local_addr] equals $::tel4www_addr ] } {

    pool mail_gw_pool

}

#下面这条policy是选择只走网通的客户IP,可以用作内网是网通的公网地址客户,或者只有单个VS在网通的服务器的外出访问包

elseif { [ matchclass [IP::client_addr] equals $::cnc_client ] } {

    pool cnc_only_gw

}

#下面这条policy与上面相对,判定客户的目标地址是否是网通地址

elseif { [ matchclass [IP::local_addr] equals $::cnc_addr ] } {

    pool cnc_only_gw

}

elseif { [ matchclass [IP::local_addr] equals $::telecom ] } {

    pool tel_only_gw

}

elseif { [ matchclass [IP::local_addr] equals $::unicom_addr ] } {

#当命中了这条policy的时候写入log;用来调试时监控是否命中策略

#    log " using unicom_only_gw!!!!————[IP::local_addr]!!!"    

    pool unicom_only_gw

}

else {

   pool default_gateway_pool

   snat automap

}

when LB_SELECTED {

   #上半段的rules是判断用户的外出包采用哪个gateway即哪个isp外出,这半段rules则在用户已经选择了外出的isp后,判断用户究竟用哪个source IP外出!!

   # 这段的重点就是我们通常所说的NAT/SNAT/SNATPOOL/iSNAT的具体实现。可以看到我们在选择用哪个snat IP时,其判定条件都是客户源地址和选定gateway地址的绑定。其原因为何?

   if {  [ matchclass [IP::local_addr] equals $::debug_class ]  } {

#  纪录属于dubug_class 向外访问的情况,可以轻松的通过添加需要监控的客户IP到debug_class,我们就可以实现监控数据包是如何分配的,日志写到/var/log/pktfilter

log local5.warning "select gateway [IP::client_addr]---> [IP::client_addr] -->[LB::server addr]!!!"

   } 

#  这里是在select gateway之后,实现NAT、SNAT、iSNAT到该gateway绑定的isp网段地址

   if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.83]} {

         snat 218.104.34.221

   }

   elseif {[IP::addr [LB::server addr] equals 221.224.233.89] and [IP::addr [IP::client_addr] equals 172.22.252.83]} {

         snat 222.92.15.8

   }

   elseif {[IP::addr [LB::server addr] equals 221.224.233.81] and [IP::addr [IP::client_addr] equals 172.22.252.83]} {

         snat 221.224.25.138

   }

elseif {[IP::addr [LB::server addr] equals 211.90.164.89] and [ IP::addr [IP::client_addr] equals 211.90.163.99 ] } {

# 如果内部使用公网地址,而且希望不是SNAT出去的,可以使用SNAT none语句

          snat none

}

else{

    snat automap 

}

}


一、

总论

在实施一个链路负载均衡项目中,针对outbound数据流,我们有三个基本原则在开始时,我们必须先声明:

数据流程图规则

F5的工程师最重要的就是能够快速理解用户的实际需求,并将其简化、整理成为一个真正的数据流程图,从而判定在每个数据流程环节应该如何处理。

如上iRules所描述的,在本文中,我们将所有的outbound数据流处理分成两个部分,即路由选择部分(CLIENT_ACCEPTED事件)和SNAT转换部分(LB_SELECTED 事件)。任何用户的外出数据包在经过F5作链路负载均衡时,无非就是选择路由和选择外出的snatIP两个流程,而且一定是先选择路由再选择snatIP。我们实施链路负载均衡项目,也就是我们将用户的实际需求转化为上述两部分流程图的过程。基于此判定,我们就很容易分析下面罗列的各种客户需求,而做到万变不离其宗!

在本文讨论的链路负载均衡outbound数据流的流程图,一般为:

SourceIP & DestIP ?   

选用哪个isp外出?    

客户的源地址SNAT成啥地址?

当然,如果考虑到选用的isp故障时如何处理?第二流程还要细化!


配置规范原则

我们不是一个专业程序员,我们是F5这个设备的操作人员,所以我们追求的不是最快的处理方式,而是一个标准的处理方式。所以,本文中会要求很多参数有统一的命名规范以方便所有人理解其含义。更重要的是,我们希望建立的标准模板将今后的系统运维、故障诊断涵盖进去,即你的F5配置不会因为用户的服务器变动、数据流变动、程序变动发生根本改变,运维人员也无需改动你的irules就可以变更配置。所以,你可以在本文中看到大量使用class组来定义源或目标地址,就是为了用户能够简单添加或删除某个class的内容来实现变更。同时,你还会看到在配置中有很多log信息,就是为了方便大家今后的故障监测,所以大家在看的时候千万要设想一下为何要在这log,有啥目的,可以达到啥效果!同时,本文没有采用任何advance配置和internal 配置,就是希望大家在采用本文提到的方案时对自己有充分的信心,从而可以及时、快速得找到真正需要大家解决的bug问题。

在本文中,你可以看到 cnc_only_pool&cnc_first_pool,前者代表只能走CNC的应用,后者代表优先走CNC(如果CNC故障,可以考虑其它备份,采用priority 将pool中的CNC设置最高优先级,其它ISP低优先级,active member要求1)。


个例分析规则

在本文中我们先给出了一个完整的解决方案,或者说是标准的解决方案,我们希望分析的所有个例都能够基于该方案得到解答。我们分析的方案可能不是最优的,我们分解的案例可能也不完全,但是希望大家在这个平台上去丰富,把各种各样的案例拿处理,群策群力,最终都能得到解答! 同时,本文最后也探讨了一下优化性能的问题,只是抛砖引玉,希望更多编程高手能够加入!在不破坏这个平台的基础上,希望得到更多的优化方案。


二、分类描述

对于链路负载均衡中的outbound应用,我们总结下来,按照用户外出的snat方式,我们大致分为4大类:

第一类:  automap  

这是绝大多数内网用户上网时采用的算法,其特点是用户外出没有固定IP要求,只要保证选用哪个ISP就用哪个ISP的地址作为源地址就可。


第二类: 1:1 NAT/SNAT应用 (多个服务器对应一个VS)

这类地址一般是用户的MAIL 服务器、××× 服务器、终端服务器。其特点是:用户服务器原先就直接采用某一ISP的公网地址直接对外发布服务,现在只是将该服务器移动到内部的DMZ区,并不需要其对外提供多个ISP的接入服务。比较典型的是mail服务器,由于对端mail服务器会通过反向域名查询IP,故mail服务器如果多ISP发布很可能被对端mail服务器拒绝,故只采用单一IP对应域名方式。

该类应用的outbound难点在于,用户进来访问是通过VS(返回包会自动命中L4交换记录的会话信息,不用考虑),而服务器外出必须首先采用SNAT将其源地址变为VS的地址以保证应用的统一,而更重要的是由于其外出地址VS是固定的,其外出的gateway也必须选择该VS所在的ISP,而这就必须由rules来保证。

在处理1:1 NAT时,F5相对于我们的竞争对手而言,可以说完全没有优势,我们必须采用VS+SNAT+irule才可以实现一个简单的NAT功能(特指在ISP LB项目中),所以我们应该鼓励客户将应用发布在多个ISP中,这样就能够体现我们的优势!或者,要求用户提供多台服务器同时对外提供服务(对我们而言,单一ISP发布和多ISP发布配置几乎一样)如果不行,大家就应该仔细分析用户需求,其实很多服务器外出并不一定要使用VS地址,可以使用任何地址!这样就不用考虑outbound的SNAT+irule而直接规类到第一类automap应用了。如果,用户一定要1:1 NAT而且要和竞争对手比较,你还可以大胆的提问客户,如果VS所在ISP故障,如何让服务器仍然可以外出internet? 竞争对手很难实现,我们则只要把外出irule中的CNC_ONLY_POOL 改为 CNC_FIRST_POOL就好了!


第三类: iSNAT 应用(多个VS对应1/N个服务器)

这类应用是F5的最大特色,也是真正意义上的ISP负载均衡。 其特点是,服务器在多个ISP上对外发布,其外出时选用哪个ISP就用该ISP上的VS地址作为SNAT地址。在这里,技术难点就是如何绑定snat地址,如何在snatpool依据选择的gateway挑选snat地址。


第四类: 内网有公网地址

此类应用,是最麻烦的,其inbound采用network VS 转发,而outbound原则上必须采用该公网地址段的ISP作为gateway(外出的返回包一定是走该ISP返回!)。我们要考虑的是,如果该ISP故障是否要让其走其它ISP,并采用SNAT automap作为源地址。



一、1 snat automap

对于内网用户访问internet,可能直接Automap 到 default_gate_pool 里做roundrobin。一般在iRules中,我们都是命中最后的else语句。

最简单的就是如下的组合(黑体字部分):

when CLIENT_ACCEPTED {

if { [XXXXXXXXXXXXXXXXXXXXXXXXXXXXX } {

pool XXX_only_gw    

}

else {

   pool default_gateway_pool

   snat automap

}

}

when LB_SELECTED {

   if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.83]} {

         snat 218.104.34.221

   }

。。。

else{

    snat automap 

}

}


只是,这样的规则并不能够优化外出outbound的访问速度,尤其是不能分解出去电信和网通的数据流,所以需要编写irule 脚本来做更进一步的设置。

举例:如果outbound 有电信和网通两条链路,我们需要建立3个gateway策略pool

telecom_only_pool  —— telecom gateway 地址

cnc_only_pool      —— cnc gateway 地址

default_gateway_pool —— 包含所有的gateway地址

     然后在DATA GROUP中建立2个class (telecom 和cnc) ,将电信和网通的地址段加入,在default_gateway_vs中(0.0.0.0:0)使用以下rule就可以解决的电信和网通的外出优化问题了。

 when CLIENT_ACCEPTED {

 if { [matchclass [IP::local_addr] equals $::telcom_class]} {

      pool telcom_only_pool

    }

 elseif { [matchclass [IP::local_addr] equals $::cnc_class]}  { 

      pool cnc_only_pool     

    }

else {

      pool default_gateway_pool

    }

  }


很多工程师再这样做了之后,测试功能的时候就会发现一个问题了,如果去掉电信的链路访问电信地址不通,去掉网通链路访问网通地址不通。这是因为在irule中的先匹配到电信得链路,然后就转发到指定得ISP_gateway, 所以就访问不通. 解决这个问题可以使用priority的功能,建立冗余措施:

telecom_first_pool  ——     telecom gateway addr    priority 10

                           cnc gateway addr   priority 1

cnc_first_pool      ——     cnc gateway addr    priority 10

                           telecom gateway addr   priority 1


default_gateway_pool ——    cnc gateway addr    priority 1

                           telecom gateway addr   priority 1


这样就可以使用first_pool来实现外出gateway的选择,telecom和cnc 两个class也是现成的。至于外出的snat由于是automap所以没有什么特殊之处。


对于上网用户,如果用户数很多,我们常常考虑增加snat automap地址来实现提升snat的性能,通常方式是在BIG-IP接口添加多个floating IP来实现多个automap地址,但是不论v4.5和v9系统都是按照连接数轮询得采用这多个floatingIP,导致用户msn或者IE访问产生问题。如何解决?用图形界面简单的snat是无法解决的,还是要用iRules。

首先,我们如何模拟多floating IP的snat automap,其实很简单,我们已经对每个gateway决心了判定,在其最后,我们不用snat automap, 而用snat pool替代。


when LB_SELECTED {

#最后判定用户采用电信网关218.104.34.193

   if {[IP::addr [LB::server addr] equals 218.104.34.193] } {

         snat pool snat_tel_pool

   }

。。。

else{

    snat automap 

}

}

      其次,如何实现一个源地址只采用一个snatIP外出? 我想到的是hash算法,即将用户的源地址按照snatpool内地址个数取余数,然后按照余数分配snat地址,大致的语法是

if {[IP::addr [LB::server addr] equals 218.104.34.193] } {

         switch  “用户源地址取余数”

       “0”

               snat snat_tel_pool地址1

       “1”

               snat snat_tel_pool地址2

       “2”

               snat snat_tel_pool地址3

。。。

   }

。。。

else{

    snat automap 

}

由于时间关系,这里还没有尝试具体的算法,有待大家帮忙完整!





二、2 NAT应用

在前面的基础上我们的客户一定会又提出了一些具体的需求,某些应用需要以VS的地址 SNAT出去,这时需要将该VS对应的服务器组POOL中的所有服务器做1对1或N对1的SNAT;

   例如:VS (222.92.15.12)  POOL (172.22.253.12 + 172.22.253.13)

对于这种NAT应用,我们判定其数据流有如下几步:

1>当源地址等于特定服务器地址时,将优先选用该特定服务器对应的VS所处的gateway;

2>如果选定了VS所对应的gateway,则将该服务器的源地址SNAT成其VS的地址;

3>如果对应的gateway故障,且用户运行切换使用别的gateway,此时该服务器的源地址应该SNAT automap成对应选定gateway的地址。

步骤一,对应于irules中的以下内容:

when CLIENT_ACCEPTED {

。。。

if { [ matchclass [IP::client_addr] equals $::cnc_client ] } {

    pool cnc_only_gw

}

。。。

我们没有1对1的采用if语句判定特定服务器地址,而是将服务器的源地址如:172.22.253.12 和172.22.253.13 按照其VS 222.92.15.12处于cnc而加入cnc_client这个class。同样的,所有VS在cnc的pool服务器组成员均加入到cnc_client.当然,如果有特点客户必须走cnc链路的也可以加入cnc_client。

对于步骤3,我们需要用cnc_first_gw代替cnc_only_gw实现当cnc故障时系统能够选用别的gateway作为外出路径。

对于步骤2,我们将按照client_accepted事件中选定的gateway (LB:server addr 函数对应选定的gateway)并结合服务器源地址判定snat地址。切记必须两者绑定而非仅仅判定源地址!因为如果选定的不是指定vs对应的gateway,我们将使用snat automap外出。

when LB_SELECTED {

...  

    if {[IP::addr [LB::server addr] equals 222.92.15.12] and [IP::addr [IP::client_addr] equals 172.22.253.12]} {

         snat 222.92.15.12

   }

else{

    snat automap 

}

}

   有很多人会这样问: 在web界面中有一对一的SANT设置,而且他的优先级比

Automap的要高(automap和 1:1的snat都是全局属性),为什么还要这样做呢?

   答:在单独线路的Server LB的时候,我们在web 界面中设置1:1或1:N的SNAT,我们说是没有问题的,但是我们在两条或以上的时候,需要考虑到线路断线后的冗余问题。我们可以分析这两种实现方式的区别。

a.Web 界面的 1:1 SNAT 方式的判断逻辑:

Client IP——〉SNAT IP ——〉 Gateway_IPS_adder

   在这样的方式中,如果IPS线路断线,那么SNAT的地址出去就不能访问;

 

b. irule 的方式  1:1 SNAT 方式的判断逻辑:


Gateway_IPS_adder——〉Client IP——〉SNAT IP

在这样的方式中,由于使用了priority的方式,就算IPS线路断线,在irule中匹配gateway pool 之后,最终还是能够有备份线路来选择gateway,然后再根据client IP来判断,所以这样的方式是不会出现无法访问的现象。

     



二、3 iSNAT应用

iSNAT应用指得是内网的服务器组(1台或N台),已经按照链路负载均衡在多个ISP上构筑了VS。当服务器主动向外发起请求时,其外出的源地址按照其选定ISP而采用该ISP上的VS地址。我们来整理一下其数据流:

1.服务器发起对外的请求,达到F5后选择一个ISP的网关转发外出包;

2.当决定了转发的ISP网关后,将服务器的源地址改为该ISP上的对应VS地址;

3.如果含有VS的ISP都故障,是否让服务器采用别的ISP外出?

4.如果采用别的ISP外出是否采用SNAT automap解决源地址问题?

通常需要iSNAT的应用如IPSEC ×××,mail Server等 。在4.5版本中我们需要在CLI中使用SNAT pool的命令来实现iSNAT功能,可以很方便的将snat地址和isp绑定。而在V9的方式web界面中能够建立SNAT pool,但是我们将SNAT pool确无法自动选取ISP上的一个snat地址,即无法实现iSNAT,必须采用iRules 手工设定。

首先,让我们看看如何处理步骤1 ?我们首先要建立一个class将VS对应的所有服务器组pool成员添加进去,当然如果服务器只有一台就无需建立。举个例子我们的mail服务器172.22.252.81,对外发布两个VS (在cnc 为218.104.34.201 网关为218.104.34.193; 在telecom为222.92.15.27 网关为221.224.233.89)。我们的路由选择rules应该如此写:

when CLIENT_ACCEPTED {

。。。

if { [ matchclass [IP::client_addr] equals $::mail_srv ] } {

    pool mail_gw

}

。。。

}

其中,mail_srv class含有172.22.252.81这一个服务器地址,mail_gw 含有218.104.34.193:0 和221.224.233.89:0 两个网关。这样,我们就实现了172.22.252.81外出时可以走两条isp。

步骤2, 如何确定外出地址? 我们在iRules中的LB_SELECTED事件中建立gateway+clientIP绑定的判定以确定是我们所要处理的这台mail服务器,再分别选取要的snat地址。

when LB_SELECTED {

if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.81]} {

         snat 218.104.34.201

   }

elseif {[IP::addr [LB::server addr] equals 221.224.233.89] and [IP::addr [IP::client_addr] equals 172.22.252.81]} {

         snat 222.92.15.27

   }

}

如上所示,只有当选中218.104.34.193这个gateway并且服务器地址是mail的地址172.22.252.81,我们才会将其转换成mail的VS地址218.103.34.201.

其三,如何实现步骤三的冗余? 其实就是在mail_gw pool中将cnc和telecom的优先级设置为10,active member设置为1,然后将unicom等ISP加入pool中并将优先级定为1,这样当cnc和telecom故障时,仍然可以选用其它ISP链路。

其四,当你选用了其它ISP后,自然不能命中LB_SELECTED中的任何指定策略,只会命中else中的automap而外出。


  




二、4 公网地址应用

如果F5里面的某些服务器使用了公网地址,不做任何设置的时候是命中Automap,即使打开了0.0.0.0:0 forwarding vs 同样如此,如果希望以自己的地址路由出去,就必须不做SNAT出去。我们再来整理一下其数据流:

1>当客户的源地址是公网地址,外出访问internet时,我们需要把它转发到该公网地址所属的ISP;

2>由于其是公网地址,我们在外出snat中应该明确标注其snat none;

3>如果该公网地址所属ISP故障,是否切换到其它ISP;

4>当切换到其它ISP时,外出时必须选用其它ISP地址作为snat地址才能外出;

对于步骤1,我们只需要在client_accepted事件中描述出该公网网段,并将其指定到所属的isp gateway, 如下文所示,当公网网段222.224.15.0/24外出时,我们将只把它转发到telecom (注意telecom_only_gw这个pool)

when CLIENT_ACCEPTED {

if { [IP::addr [IP::local_addr] equals 222.224.15.0/255.255.255.0 ] } {

    pool telecom_only_gw

}

}

对于步骤2,更简单,我们只要在LB_SELECTED事件中将该网段标识出来,并选取snat none。切记!为了可以实施下两个步骤,我们还是用gateway+sourceIP的绑定而非纯sourceIP的判定,来选取这些服务器。

when LB_SELECTED {

if {[IP::addr [LB::server addr] equals 221.224.233.89] and [ IP::addr [IP::client_addr] equals 222.224.15.0/255.255.255.0 ] } {

            snat none

}

。。。

     对于步骤3,如果考虑到电信故障,需要切换,同样的我们可以将telecom_only_gw改为telecom_first_gw,就可以在电信故障是切换到其它isp了。

     由于切换到其它ISP,如果我们仍然用telecom的公网地址外出,则必定无法访问,所以我们这时候必须让其命中automap(当然也可以是其它你知道并明确的snat规则)。这就是为何我们在步骤2中必须绑定选定的gateway,否则只判定源地址,那么当我们切换到其它ISP时,仍然命中该规则,而导致仍然用电信的公网地址外出。


以上简单的描述了4种SNAT的方式的实现方法,也许大家会觉得这样的做法比较笨,比较麻烦,所以还是请具体问题具体分析咯。


三、

系统优化

以下所述的优化,必须是完全理解前面的配置后,才方便实施!而且以下的配置主要是优化系统性能,并不增强功能。

三、1 LB_SELECTED事件中if的优化

按照前面所述,我们在LB_SELECTED事件中采用gateway+sourceIP绑定的方式书写if判定。这种方式在少量snat设置中十分简单易懂,但当snat数量达到十多个时,对性能影响甚大。为什么?因为如果你有30个判定,则snat automap必将作30个if判定后才到达最后的automap,性能影响甚大。最简单的方式就是按照gateway先规类判定一次后,再接下去判定sourceIP,如此可以减少大量if判定。如下:

when LB_SELECTED {

   if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.81]} {

         snat 218.104.34.221

   }

   elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.82]} {

         snat 218.104.34.23

   }

   elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.83]} {

         snat 218.104.34.24

   }

   elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.84]} {

         snat 218.104.34.25

   }

}

我们可以先判定网关是CNC的218.104.34.193,再分析源地址。这样如果客户选定的是telecom gateway就可以避免后续的if判定。如下:

when LB_SELECTED {

   if {[IP::addr [LB::server addr] equals 218.104.34.193] } {

         if { IP::addr [IP::client_addr] equals 172.22.252.81] } {

snat 218.104.34.21

      }

      elseif { [IP::addr [IP::client_addr] equals 172.22.252.82]} {

          snat 218.104.34.23

      }

      elseif { [IP::addr [IP::client_addr] equals 172.22.252.83]} {

          snat 218.104.34.24

      }

      elseif { [IP::addr [IP::client_addr] equals 172.22.252.84]} {

        snat 218.104.34.25

      }

  else {

snat automap

  }

   }

}


事实上,我们在现网中就应该用这样的嵌套if规则定义LB_SELECTED事件,本文主要是为了让大家容易理解SNAT运作才使用了上一章的gateway+sourceIP绑定if。但大家必须注意,随着语法改动带来的冗余切换尤其是automap的命中!!



三、2 对于大量1:1 SNAT的优化

在上面众多的1:1 SNAT中后来在Devcentrol中看到一个case,深受启发。但是由于时间关系,没有测试,如果那位兄弟有条件的测试一下看能够实现,造福于他人.

首先,将所有在CNC 上的1:1 / n:1 SNAT 地址配置到一个cnc_snat_addr class中,其格式如下:

"client_ip  SNAT_IP"

"10.0.0.1  200.0.0.1"

"10.0.0.2  200.0.0.2"

      。。。

然后在LB_SELECETED规则中,就可以只判端是否为CNC gateway,而不需要采用gateway+sourceIP的判定,直接从cnc_snat_addr中选取该源地址对应的snat地址,如果没有就选取automap。

when LB_SELECTED {

   if {[IP::addr [LB::server addr] equals 218.104.34.193] {

      set my_snat [ findclass [IP::client_addr] $::cnc_snat_addr " " ]

         if { $my_snat ne "" } {

               snat $my_snat

             }

         else { snat automap}

      }

这样做的目的,是可以大大减少irule的if语句判定数量,并且极大的方便用户维护。举例,如果你在CNC有30个1:1的NAT,那你在LB_SELECTED 中就得有30判定if,而现在我只要判定一次gateway就搞定了,效率相差甚大。其次,如果你要添加第31个1:1NAT,不用这种方式,你必须在众多的if语句中添加一个if,而现在,你只要在cnc_snat_addr中添加一行,然后在client _accepted事件对应的cnc_client中也添加一个源地址就可以了,完全不需要改变irules!




三、3 troubleshoot中如何获取负载分担信息

  由于目前在V9 平台上我们建立了0.0.0.0:0的 VS的时候,如果现在standard  —〉all protocal 的时候就会直接改变为performance laryer 4的type,这样我们在tcpdump的时候就不能抓到内部向外的数据包,因为performance layer 4 的 vs是 直接走PVA 芯片,不会经过CPU的处理,所以对我们的troubleshooting带来很大的麻烦。

  但是可能有人会建议建立两个VS,0.0.0.0:0   standard ——〉 tcp protocal 和0.0.0.0 standard ——〉ucp protocal ; 但是对于一个应用同时都要用到udp 和tcp的时候,那数据包会满天飞。

  所以我们在测试的时候在可以在irule中打开log功能。


下面例子中就是先建立一个debug_class,然后如果发现有客户端outbound有问题,我们就可以将client IP放在debug_class中,然后再/var/log/中 使用命令tail –f  pktfilter, 就可以通过log看到客户端向外访问情况了。

when LB_SELECTED {

if {  [ matchclass [IP::local_addr] equals $::debug_class ]  } {

           log local5.warning "select gateway [IP::client_addr]--> [IP:local_addr]->[LB::server addr]!!!"

}

这条if语句可以放在最前面或最后,为何要作debug_class?因为在正式环境中如果直接添加log "select gateway [IP::client_addr]--->[LB::server addr]!!!",这样会有很多的log很快就会写满硬盘的,当然在测试的时候是没有问题啦。而采用debug_class 就可以轻松的决定要跟踪哪个IP,而不需要改变irules。

    其他的log 方式还是需要根据毛主席他老人家的思想去做啦: 具体问题具体分析啦。

     

当然,如果我们想连snat成哪个IP都跟踪,则必须在LB_SELECTED语句中修改snat方式,举例,(时间关系,没有验证下面的语法是否准确!只是描述用意)

when LB_SELECTED {

set my_snat_addr “automap”

   if {[IP::addr [LB::server addr] equals 218.104.34.193] } {

         if { IP::addr [IP::client_addr] equals 172.22.252.81] } {

$my_snat_addr = 218.104.34.22

      }

      elseif { [IP::addr [IP::client_addr] equals 172.22.252.82]} {

          $my_snat_addr = 218.104.34.23

      }

      elseif { [IP::addr [IP::client_addr] equals 172.22.252.83]} {

          $my_snat_addr = 218.104.34.24

      }

   …

    }

snat $my_snat_addr

log local5.warning “ snat addr is $my_snat_addr ”

}

附一

我们在v9 的outbound的测试经常会碰这样的问题, 向外一直ping 一个电信的地址,拔掉电信得链路的时候会发现ping 包会丢包会很长时间恢复,但是向外的ftp,http smtp都不受影响,迅速的切换回来。 这是因为v9中吧ping作为一个长连接,所以timeout时间过来才会切换到另一条联路。 如果要解决这个问题就是,在default_gateway_pool中actione service down中选择reselect 的option. 这样就能够实现ping 包的快速切换。