背景:积累常见irule
1. 友好界面
背景:客户要求需要在停机更新或者系统出故障时进行页面提示【系统维护中】 F5判断系统各节点是否存活 如果全部不存活就跳到指定提示页面 如果至少一台就不用跳转到提示页面,正常进行负载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 when HTTP_REQUEST { if { [ active_members test_pool ]==0 } { HTTP::respond 200 content { <html> <head > <title>维护界面</title> </head> <body> 界面维护中!!! </body> </html> } } }
2. 基于源地址负载均衡
背景:并配置负载均衡算法为基于源地址负载均衡算法,将192.168.11.0/24的IP地址访问分配给服务器A,将192.168.12.0/24的IP地址访问分配给服务器B。
1 2 3 4 5 6 7 8 9 10 11 when HTTP_REQUEST { if { [IP::addr [IP::client_addr] equals 192.168.11.0/24] }{ pool pool_A member 211.136.2.11 80 } elseif { [IP::addr [IP::client_addr] equals 192.168.12.0/24] } { pool pool_A member 211.136.2.12 80 } } when LB_FAILED { log local0. "src_shibai" LB::reselect pool pool_A }
3. 基于URI负载均衡
示例一:配置负载均衡算法为基于http uri请求内容的负载均衡算法,将请求URL中含有“test1”的发送给服务器A,将请求URL中含有“test2”的发送给服务器B。
1 2 3 4 5 6 7 8 9 10 11 12 when HTTP_REQUEST { set url [HTTP::uri] if { ([string match {*test1*} $url ]) & ([active_members pool_A]==1)} { pool pool_A log local0.info "[HTTP::uri] -- pool_A" } elseif { ([string match {*test2*} $url ]) & ([active_members pool_B]==1)} { pool pool_B log local0.info "[HTTP::uri] -- POOL_B" } else { pool pool_default } }
示例二:配置负载均衡算法为基于http uri请求内容的负载均衡算法,如果URI中以“test1”开始开始,则把流量发送给pool_A,如果以其他字段开头,则拒绝接受流量。
1 2 3 4 5 6 7 when HTTP_REQUEST { if { [HTTP::uri] starts_with "/test" } { pool pool_A }else { reject } }
4. 基于客户端浏览器负载均衡
背景:配置负载均衡算法为基于HTTP Header信息的负载均衡算法,按照HTTP请求的Header中User-Agent类型(包含终端或浏览器等信息)进行负载均衡,将匹配User-Agent类型为Chrome的发送给服务器组A,将匹配User-Agent类型Firefox发送给服务器组B,其它HTTP请求发送给服务器组C。
1 2 3 4 5 6 7 when HTTP_REQUEST { if { [HTTP::header User-Agent] contains "Chrome" } { pool pool_A } elseif { [HTTP::header User-Agent] contains "Firefox" } { pool pool_B } else { pool pool_C } }
5. http头部插入字段
背景:需要在http头部插入字段。
1 2 3 4 5 6 7 when HTTP_REQUEST { HTTP::header insert "CLIENT_ORG_IP" [IP::client_addr] if { [HTTP::header CLIENT_ORG_IP] contains [IP::client_addr] } { log local0. "ok" } HTTP::header insert "CLIENT_ORG_PORT" [TCP::client_port] }
6. 流量通过F5访问流程
背景:通过Irule查看流量地址信息 。
1 2 3 4 5 6 7 when SERVER_CONNECTED { log local0.info " client connection from [IP::client_addr]:[TCP::client_port] access to [clientside {IP::local_addr}]:[clientside {TCP::local_port}] Snat to [IP::local_addr]:[TCP::local_port] TO server [IP::server_addr]:[TCP::server_port]" }
7. DNS解析
背景:在本地GTM进行A记录域名解析,当客户端来本地访问AAAA记录信息时,则去另外的GTM进行AAAA地址解析。再把解析结果返回给客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 when DNS_REQUEST { switch [string toupper [DNS::question type ]] { "AAAA" { pool v6_dns } "MX" { pool v6_dns } "TXT" { pool v6_dns } } } when DNS_RESPONSE { if {([DNS::header rcode] equals "NXDOMAIN" ) or ([DNS::header rcode] equals "REFUSED" ) }{ DNS::header rcode NOERROR } }
8. 基于域名的出向选路规则
1. 当接收DNS流量时,配置出向dns请求。如果请求域名以date_group中配置的域名结尾,则去pool_dns_test去进行域名解析,否则去pool_dns_default中进行域名解析。
1 2 3 4 5 6 7 8 when DNS_REQUEST { if {[class match [DNS::question name] ends_with data_group] } { pool pool_dns_test }else { pool pool_dns_default } }
2. 当收到DNS响应时,如果请求的域名在domain_test中,就把A记录或者AAAA记录以及对应的域名存储在test_table表中。
1 2 3 4 5 6 7 8 9 when DNS_RESPONSE { if { ([DNS::question type ] eq "A" ) or ([DNS::question type ] eq "AAAA" ) } { if {[class match [DNS::question name] contains domain_test] } { set rrs [DNS::answer] foreach rr $rrs { table set -subtable "test_teble" [DNS::rdata $rr ] [DNS::question name] } } }
3. 配置出向选路,如果出向访问的IP在test_teble表中,则出向流量走pool_test,否则出向流量走Default_pool。注意:设备配置在出口位置,还需要把地址转换为公网地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 when CLIENT_ACCEPTED { if { [table lookup -subtable "test_teble" [IP::local_addr] ] != "" } { pool pool_test }else { pool Default_pool } } when LB_SELECTED { if { [IP::addr [LB::server addr] equals 1.1.1.1]} { snatpool snat_test }else { snat automap } }
9. 清空http uri
背景:清除http uri。
1 2 3 when HTTP_REQUEST { HTTP::uri "/" }
10. 一个vs运行http和https
背景:客户需要使用同一个vs,接收并处理https和http业务请求。
实现方式:配置https虚拟服务并配置证书,配置irule,https用户使用特定网段正常负载转发,http用户关闭ssl profile并负载转发
1 2 3 4 5 6 7 8 when CLIENT_ACCEPTED { if { [IP::addr [IP::client_addr] equals 192.168.10.0/24 ] } { pool test_side_2 } else { SSL::disable clientside pool test_side_1 } }
11. 多条策略使用switch命中规则案例
1 2 3 4 5 6 7 8 9 10 11 12 13 when CLIENT_ACCEPTED { switch [string toupper [IP::client_addr]] { "10.252.149.11" { snatpool sp_10.252.255.11 } "10.252.149.12" { snatpool sp_10.252.255.12 } "default" { drop } } }
12. irule 防止x-forwarded-for 攻击
1 2 3 4 5 6 7 8 9 10 11 12 13 when HTTP_REQUEST { set xff 0 foreach x [HTTP::header names] { if { [string tolower $x ] equals "x-forwarded-for" } { set xff 1 HTTP::header remove $x HTTP::header insert X-FORWARDED-FOR [IP::client_addr] } } if { $xff == 0 } { HTTP::header insert X-FORWARDED-FOR [IP::client_addr] } }
13. https业务指定源地址迁移
1 2 3 4 5 6 7 8 when CLIENT_ACCEPTED { if { [IP::addr [IP::client_addr] equals 111.20.119.234/32 ] }{ pool pool_159_443 } else { SSL::disable serverside pool g_KHDQ3_VSMobileJieru_01 } }
14. http uri 替换
1 2 3 4 5 6 7 For Example: Original HTTP Request https://www.yourdomain.test/public/page/login.html New HTTP Request https://www.yourdomain.test/private/page/login.html
方式一: Using String Map : 字符串映射会将 URI 中找到的键字符串的每个实例替换为新值。
1 2 3 4 5 6 when HTTP_REQUEST { if {[HTTP::uri] starts_with "/public/" } {HTTP::uri [string map {"/public/" "/private/" }[HTTP::uri]] pool pool_web } }
方式二:Using RegSub : (不带 -all 选项)将仅将 URI 中找到的密钥字符串的第一个实例替换为新值。
1 2 3 4 5 6 7 8 when HTTP_REQUEST { if {[HTTP::uri] starts_with "/public/" } {if { [regsub -nocase /public/ [HTTP::uri] /private/ new_uri] > 0 } {HTTP::uri $new_uri } pool pool_web } }
15、允许指定Host访问vs
方式一:指定 IP
1 2 3 4 5 when HTTP_REQUEST { if { [HTTP::host] != "192.168.10.96" } { reject } }
方式二:指定域名
1 2 3 4 5 when HTTP_REQUEST { if {not ([string tolower [HTTP::host]] starts_with "link.it.10086.cn" )}{ reject } }
方式三:使用data group
1 2 3 4 5 when HTTP_REQUEST { if {not [class match [HTTP::host] equals host_reject ]}{ reject } }
方式四:使用data group和正则匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 when HTTP_REQUEST { if {[string tolower [HTTP::host]] ends_with host_reject } { pool test_side_1 } elseif {[string tolower [HTTP::host]] matches_regex {^ec\.it\.10086\.cn$}} { pool test_side_1 } elseif {[class match [HTTP::host] equals host_reject1 ]} { pool test_side_1 } else { reject } }
16、根据edns客户端地址的最后一段奇偶性选择pool
1 2 3 4 5 6 7 8 9 10 11 when DNS_REQUEST { if { [DNS::edns0 exists] } { set endip [string tolower [getfield [DNS::edns0 subnet address] "." 4]] if { [expr $endip % 2] == 0}{ pool a.com } else { pool b.com } } }