学完前面三篇你已经能完成 VIP 上线、配 Monitor 保障后端可用、配 SSL 卸载处理 HTTPS。但如果要自定义流量处理逻辑——比如 URL 改写、按路径分发到不同 Pool、IP 白名单——靠标准配置就不够了。这就是 iRules 的用武之地。一、iRules 是什么iRules 是 F5 上的TCL 脚本引擎在流量经过 VS 时拦截让你能写代码自定义处理逻辑。客户端请求 → VS │ ├── Profile 栈TCP/HTTP/SSL 正常处理 │ └── iRules 在 Profile 处理中插入自定义逻辑 ├── 请求到达时 → 改 URL、插头、选 Pool ├── 响应返回时 → 改响应头、隐藏后端信息 └── 连接建立时 → IP 白名单过滤二、TCL 基础语法够用就行iRules 用 TCL 语言但你不需要精通记住 5 个核心语法就能覆盖 70% 场景变量set my_var hello # 定义变量 log local0. 值是 $my_var # 使用变量 set full_name user_${my_var} # 变量嵌套用 ${}条件判断if { [条件表达式] } { # 条件为真 } elseif { [另一个条件] } { # 另一个条件 } else { # 都不满足 }字符串操作if { [string equal $uri /health] } { ... } # 精确匹配 if { [string match /api/* $uri] } { ... } # 通配符匹配 set ext [string range $uri 0 3] # 取子串 set new_uri [string map {/old/ /new/} $uri] # 替换列表操作set allowed_ips [list 10.0.0.1 10.0.0.2] foreach ip $allowed_ips { ... } # 遍历 if { [lsearch -exact $list $item] 0 } { ... } # 查找正则if { [regexp {^/api/v[0-9]/} $uri] } { ... } # 匹配 regexp {user_id([0-9])} $uri match user_id # 提取分组三、iRules 事件模型——理解触发时机iRules 是事件驱动的在不同的时机挂不同的代码。核心事件CLIENT_ACCEPTED ← TCP 连接建立成功做 IP 过滤 │ HTTP_REQUEST ← 收到完整 HTTP 请求头90% 用这个 │ HTTP_REQUEST_DATA ← 收到请求体 │ [ 流量发往后端 ] │ HTTP_RESPONSE ← 收到后端返回的响应头改写响应头 │ HTTP_RESPONSE_DATA ← 收到响应体怎么选事件你想什么时候处理流量 │ ├── TCP 连接建立时 → CLIENT_ACCEPTED ├── 请求头到达时 → HTTP_REQUEST90% 的场景 ├── 响应头返回时 → HTTP_RESPONSE └── 响应体到达时 → HTTP_RESPONSE_DATA四、9 个实战场景从易到难场景 1HTTP → HTTPS 跳转when HTTP_REQUEST { if { [HTTP::header X-Forwarded-Proto] ne https } { HTTP::redirect https://[HTTP::host][HTTP::uri] } }触发事件HTTP_REQUEST效果用户访问http://example.com/page→ 自动 301 到https://example.com/page场景 2插入真实客户端 IPwhen HTTP_REQUEST { HTTP::header remove X-Forwarded-For # 删除伪造头 HTTP::header insert X-Forwarded-For [IP::client_addr] HTTP::header insert X-Real-IP [IP::client_addr] }触发事件HTTP_REQUEST效果后端收到X-Forwarded-For: 客户端真实 IP不再是 F5 的 IP场景 3URL 路径重写去掉前缀when HTTP_REQUEST { if { [string match /api/v1/* [HTTP::uri]] } { # 把 /api/v1/user → /user set new_uri [string range [HTTP::uri] 7 end] HTTP::uri $new_uri } }触发事件HTTP_REQUEST效果客户端请求/api/v1/user→ 后端实际收到/user场景 4按 URI 分发到不同 Poolwhen HTTP_REQUEST { set uri [HTTP::uri] ​ if { [string match /api/* $uri] } { pool api-pool # API → API 池 } elseif { [string match /static/* $uri] } { pool static-pool # 静态资源 → 静态池 } else { pool web-pool # 其他 → 默认池 } }触发事件HTTP_REQUEST效果一个 VIP 根据 URL 路径分发到不同后端集群场景 5按 User-Agent 分流移动端 vs PCwhen HTTP_REQUEST { set ua [string tolower [HTTP::header User-Agent]] ​ if { [string match *mobile* $ua] || [string match *iphone* $ua] } { pool mobile-pool } else { pool pc-pool } }触发事件HTTP_REQUEST效果手机用户和 PC 用户走不同的后端集群场景 6IP 白名单when CLIENT_ACCEPTED { set allowed_subnets [list 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] set client_ip [IP::client_addr] set allowed false ​ foreach subnet $allowed_subnets { if { [IP::addr $client_ip equals $subnet] } { set allowed true break } } ​ if { !$allowed } { log local0. 拒绝非内网访问: $client_ip reject } }触发事件CLIENT_ACCEPTED效果非内网 IP 在 TCP 连接阶段直接断开不给 HTTP 握手机会场景 7隐藏后端服务信息when HTTP_RESPONSE { HTTP::header remove Server HTTP::header remove X-Powered-By HTTP::header remove X-AspNet-Version HTTP::header insert Server F5 BIG-IP }触发事件HTTP_RESPONSE效果客户端看不到后端是 Nginx 还是 Tomcat场景 8IP 级速率限制when HTTP_REQUEST { # 每 10 秒超过 100 次请求 → 429 if { [table lookup -subtable rate_limit [IP::client_addr]] 100 } { HTTP::respond 429 content Rate limit exceeded \ Content-Type text/plain return } table incr -subtable rate_limit -timeout 10 [IP::client_addr] }触发事件HTTP_REQUEST效果单个 IP 在 10 秒内超过 100 次请求返回 429 Too Many Requests场景 9Cookie 会话保持when HTTP_REQUEST { if { [HTTP::cookie exists MY_SESSION] } { set session_id [HTTP::cookie value MY_SESSION] persist uie $session_id # 固定到同一台后端 } } ​ when HTTP_RESPONSE { if { [HTTP::cookie exists MY_SESSION] } { persist uie [HTTP::cookie value MY_SESSION] } }触发事件HTTP_REQUESTHTTP_RESPONSE效果同一个 session 的请求始终发到同一台后端五、创建和绑定 iRules创建# 方式一从文件导入推荐 tmsh create ltm rule my-url-rewrite from-local-file /shared/tmp/irule.tcl ​ # 方式二直接创建 tmsh create ltm rule my-simple-rule # 进入交互模式粘贴脚本后 CtrlC 退出查看和修改# 查看内容 tmsh list ltm rule my-url-rewrite ​ # 修改重新导入 tmsh modify ltm rule my-url-rewrite from-local-file /shared/tmp/new-irule.tcl绑定到 VS# 创建 VS 时绑定 tmsh create ltm virtual myapp-vip-443 \ destination 10.0.0.100:443 \ pool myapp-pool \ rules { my-url-rewrite } ​ # 已有 VS 添加 tmsh modify ltm virtual myapp-vip-443 rules add { my-url-rewrite } ​ # 删除 tmsh modify ltm virtual myapp-vip-443 rules delete { my-url-rewrite } ​ # 查看绑了哪些 tmsh list ltm virtual myapp-vip-443 rules删除 iRules# 先从所有 VS 解绑 tmsh modify ltm virtual myapp-vip-443 rules delete { my-url-rewrite } ​ # 再删除规则 tmsh delete ltm rule my-url-rewrite多个 iRules 的执行顺序# iRules 按绑定顺序执行 tmsh modify ltm virtual myapp-vip-443 \ rules { ip-whitelist url-rewrite header-insert } ​ # 执行顺序 # 1. ip-whitelist 先执行IP 过滤 # 2. url-rewrite 后执行URL 改写 # 3. header-insert 最后执行插请求头 # 任一规则 return 或 reject后续规则不再执行六、调试 iRules写日志when HTTP_REQUEST { log local0. 收到请求: [HTTP::uri] log local0. 客户端 IP: [IP::client_addr] }看日志# 实时查看 tmsh tail -f /var/log/ltm | grep -i irule\|myapp ​ # 打印所有请求头排查用 when HTTP_REQUEST { foreach header [HTTP::header names] { log local0. $header: [HTTP::header value $header] } }七、常见 iRules 错误1. 没有事件声明# ❌ 错误 set my_var hello HTTP::header insert X-Test $my_var ​ # ✅ 正确 when HTTP_REQUEST { set my_var hello HTTP::header insert X-Test $my_var }2. 错误的事件中调用不支持的函数# ❌ 错误CLIENT_ACCEPTED 时还没有 HTTP 请求 when CLIENT_ACCEPTED { HTTP::header insert X-Test test } ​ # ✅ 正确HTTP_REQUEST 时才能操作 HTTP 头 when HTTP_REQUEST { HTTP::header insert X-Test test }3. reject 后没有 return# ❌ 错误reject 后代码继续执行 when HTTP_REQUEST { if { [IP::client_addr] eq bad.ip } { reject } pool special-pool # 即使 reject 了也会执行 } ​ # ✅ 正确 when HTTP_REQUEST { if { [IP::client_addr] eq bad.ip } { reject return } pool special-pool }4. 变量嵌套错误# ❌ 错误 set prefix api if { [string match /$prefix/* $uri] } { } # $p 被当成了变量 ​ # ✅ 正确用 ${} 明确边界 if { [string match /${prefix}/* $uri] } { }八、iRules 命令速查请求处理命令作用可用事件HTTP::uri获取/设置请求 URIHTTP_REQUESTHTTP::host获取请求的 HostHTTP_REQUESTHTTP::header获取/设置/删除请求头HTTP_REQUESTHTTP::cookie获取/设置 CookieHTTP_REQUESTHTTP::redirect返回 301 跳转HTTP_REQUESTHTTP::respond直接返回响应不经过后端HTTP_REQUESTHTTP::status获取响应状态码HTTP_RESPONSEIP::client_addr客户端 IP所有事件IP::local_addrF5 自身 IP所有事件reject拒绝连接CLIENT_ACCEPTEDpool选择后端 PoolHTTP_REQUEST九、学习路径建议阶段 1读懂 → 能看懂别人写的 iRules → 知道 when HTTP_REQUEST 是什么意思 ​ 阶段 2改 → 在现有 iRules 基础上改参数 → 改 URL 匹配规则、改 Pool 名称 ​ 阶段 3写 → 独立写 10 行以内的简单 iRules → URL 重写、请求头插入、IP 白名单 ​ 阶段 4组合 → 多个 iRules 组合使用 → 理解执行顺序和冲突你现在看完这篇大概在阶段 1~2 之间。把上面 9 个场景在测试环境跑一遍就进入阶段 3 了。十、小结iRules 是 F5 最灵活、威力最大的功能之一。不需要精通 TCL 语言记住 5 个基础语法 事件模型 9 个场景模板就能应对日常工作中 80% 的流量控制需求。相关阅读F5 VIP 上线全流程Pool / VS / Profile 三板斧F5 健康检查 Monitor 深入篇F5 SSL Profile 证书卸载