ALB使用可编程脚本AScript实现精细化流量管理

可编程脚本AScript是阿里云应用型负载均衡ALB (Application Load Balancer) 推出的突出灵活性和功能性的脚本语言,使得ALB实例能够突破传统负载均衡的局限,以自定义脚本的方式精确地控制和调整流量管理策略。本文通过异常请求识别、自定义鉴权、定制化请求头和响应头控制,三个常用场景来对AScript做进一步的介绍。

AScript介绍

AScript支持自定义规则的执行,这些规则在处理客户端请求的不同阶段自动触发,确保实现高度自定义化的流量管理。通过这种机制,您可以在请求和响应环节灵活地应用自定义脚本,从而实现精细的业务逻辑管理。

AScript为ALB赋予了卓越的可编程能力,助您在复杂多变的业务环境中持续优化服务性能和用户体验。无论是内容交付、安全性增强,还是性能优化,AScript都能灵活应对,实现负载均衡的智能化和个性化。

关键特性

  • 业务功能隔离:AScript规则将不同的业务功能和需求隔离在独立的脚本中,避免规则之间相互干扰。

  • 控制规则的执行流:按照实际业务场景安排规则的优先级和触发时机。

  • 规则的执行位置:在不同的执行位置配置规则。

    • 请求方向规则执行前:适用于对请求路径进行预处理的场景,例如URI自动重写、添加URI前缀、文件后缀统一转为小写等场景。

    • 请求方向规则执行后:适用于在标准转发规则处理后进一步对请求进行处理的场景,例如对文件名和类型进行改写等场景。

    • 响应方向规则执行前:适用于在响应被发送回客户端前做最后的处理的场景,例如修改HTTP头部信息或响应体的内容。

  • 监听维度的设计:AScript规则以监听级别进行设计,确保规则紧密贴合实际的监听流量模式。

使用限制

  • 仅标准版和WAF增强版的ALB实例支持AScript,基础版不支持。

  • AScript可编程脚本行数默认免费额度为25行,超过免费额度的部分会被收费,具体计费规则可参考ALB计费规则

前提条件

  • 您已创建标准版或WAF增强版公网ALB实例,并为该ALB实例创建了服务器组。请参见创建应用型负载均衡创建和管理服务器组

  • 您已为该ALB实例配置了HTTP监听并关联该服务器组。请参见添加HTTP监听

  • 您已在服务器组中分别添加ECS01和ECS02实例,并在ECS01和ECS02中均部署了应用服务。

    ECS01服务部署测试应用

    yum install -y nginx
    systemctl start nginx.service
    cd /usr/share/nginx/html/
    echo "Hello World ! This is ECS01." > index.html

    ECS02服务部署测试应用

    yum install -y nginx
    systemctl start nginx.service
    cd /usr/share/nginx/html/
    echo "Hello World ! This is ECS02." > index.html
  • 您已经注册域名并完成备案。请参见注册阿里云域名ICP备案

场景示例

AScript的强大自定义能力可以在各种场景下展现出关键优势。无论是复杂的流量分发逻辑、特定的鉴权机制,还是对请求头和响应头的定制化控制,AScript都能提供高效的解决方案,使ALB的功能扩展和优化更加迅速便捷。本文通过以下三种场景来说明AScript可编程脚本规则的功能。

场景一:异常请求识别

某企业在阿里云某地域使用ALB部署了业务,该企业发现频繁遇到异常请求的问题。具体表现为大量的恶意请求和不明来源的流量对后端服务器造成了较大的负担,影响了正常业务的访问速度和用户体验。

为了解决这个问题,该企业选择利用ALB的能力来拦截异常请求。尽管ALB的标准转发规则可以根据域名和路径进行请求的路由,但在需要进行更深层次的用户行为分析,例如检测HTTP_User_Agent时,其判断能力较为有限。为此,企业选择了AScript来增强ALB的功能。

AScript 的自定义能力显著增强了ALB的精细化处理能力,使其能够深入匹配和分析HTTP请求头部的User-Agent字段。通过编写AScript规则,企业可以对请求中的User-Agent进行具体的逻辑判断,从而识别异常或恶意行为(例如机器人或自动化脚本的访问)。如果请求被认定为异常,AScript可以返回自定义的错误信息,从而阻断潜在的安全威胁,保障服务的稳定性与数据的安全性。

本文以如下场景为例,企业通过AScript配置了特定的业务逻辑:当请求访问ALB实例时,ALB会根据配置的AScript规则检查请求中的以下信息:

  • 来自特定的主机名example.com

  • URI以/order/create开头。

  • HTTP请求头部的User-Agent中不包含trusted字符串。

如果以上条件均满足,AScript将设置状态码为403,并返回自定义响应消息The order data is abnormal。否则ALB将正常转发请求到后端服务。

对应的AScript规则

if and(eq($host,'example.com'),eq(get(split($request_uri, '?'),1),'/order/create')){
    if not(match_re($http_user_agent,'.*trusted.*')){
        exit(403,'{"code":10063,"msg":"The order data is abnormal","data":{}}')
    }
}
image

操作步骤

步骤一:添加AScript可编程脚本定义的转发规则

  1. 登录应用型负载均衡ALB控制台

  2. 实例页面,单击目标实例ID。

  3. 单击监听页签,然后单击已创建的目标监听ID。

  4. 单击转发规则页签,在请求方向转发规则页签,单击在规则执行前添加可编程脚本

    说明

    选择响应方向转发规则时,只允许在规则执行前添加可编程脚本

  5. 添加可编程脚本页面添加规则,然后单击确定

    参数

    描述

    规则名称

    输入自定义规则名称。

    规则代码

    输入规则代码。本文输入以下代码示例。

    if and(eq($host,'example.com'),eq(get(split($request_uri, '?'),1),'/order/create')){
        if not(match_re($http_user_agent,'.*trusted.*')){
            exit(403,'{"code":10063,"msg":"The order data is abnormal","data":{}}')
        }
    }

    执行位置

    规则执行位置,不可更改。本文为请求方向规则执行前

    启用状态

    规则启用状态。本文使用默认开启。

    高级配置

    本文选择默认不选择。

步骤二:设置域名解析

复制ALB实例对应的DNS名称,完成以下步骤,为您的自有域名添加1条指向ALB实例DNS名称的CNAME记录。

  1. 登录域名解析控制台

  2. 域名解析页面单击添加域名

  3. 添加域名对话框输入您的主机域名,然后单击确认

    重要

    您的主机域名需已通过TXT记录验证。

  4. 在目标域名的操作列单击解析设置

  5. 解析设置页面,单击添加记录

  6. 添加记录面板,配置以下信息完成CNAME解析配置,然后单击确认

    配置

    说明

    记录类型

    在下拉列表中选择CNAME

    主机记录

    您的域名的前缀。

    解析请求来源

    选择默认。

    记录值

    输入域名对应的CNAME地址,即您复制的ALB实例的DNS名称。

    TTL

    全称Time To Live,表示DNS记录在DNS服务器上的缓存时间,本文使用默认值。

步骤三:结果验证

  1. 测试正常网络请求。

    以任意一台可以访问公网的客户端为例。

    1. 浏览器访问http://<访问地址>可以正常访问后端服务。多次刷新浏览器,返回内容可以在ECS01和ECS02之间切换。

    2. 打开客户端的cmd窗口,多次执行以下命令,响应报文在ECS01和ECS02之间切换。

      curl http://<访问地址>

      image

  2. 测试异常网络请求。

    执行以下命令,响应报文为{"code":10063,"msg":"The order data is abnormal","data":{}},表明添加AScript可编程脚本定义的转发规则已生效。

    curl -v  -H "Host:example.com" -H "User-Agent:suspicious test" http://<访问地址>/order/create

    image

场景二:自定义鉴权

某企业在阿里云某地域使用ALB部署了业务,后端服务器组包含了多台已部署应用的服务器。该企业遇到了一个挑战:用户在访问多个应用时需要多次登录,这不仅降低了用户体验,还增加了管理的复杂性。因此,该企业希望能够在访问应用时使用统一的身份鉴权凭证,从而实现单点登录(Single Sign-On,SSO)。

为了实现该功能,企业决定利用AScript的自定义能力。通过AScript编写自定义规则,对Authorization和Cookie等请求头进行详细的检查和操作,通过这种方式,可以将Cookie中的SSO令牌转化为统一的鉴权凭证。此外,AScript还可以在响应头中注入详细的日志信息,为调试和跟踪认证流程提供便利。这种可编程的日志功能超越了传统负载均衡器,显著提升了ALB在维护系统安全性方面的能力。

本文以如下场景为例,企业通过AScript配置了特定的业务逻辑:当请求访问ALB实例时,ALB会根据配置的AScript规则检查请求头中是否存在Authorization:

  • 如果存在,使用日志记录Authorization的长度和相关场景。

  • 如果不存在,接着检查Cookie中是否存在SSO_token。

    • 如果存在,记录其长度,并将其作为Bearer Token注入到Authorization请求头中,同时记录该场景。

    • 如果SSO_token也不存在,则仅记录该场景。

对应的AScript规则

#判定给定的值是否缺失
def is_missing(val){
    if val{
        return or(null(val),le(len(val),1))
    }else{
        return true
    }
}
#在HTTP响应头中添加一条日志信息,键由参数key指定,消息内容由参数msg提供
def log_on_rsp_header(key, msg) {
    add_rsp_header(concat('ascript-log_', key), msg) 
}
#主体判断逻辑
#判断请求头中是否存在Authorization,如果存在,记录其长度
if $http_authorization {
    log_on_rsp_header('authorization', concat('len=', len($http_authorization)))
}
#判断请求的Cookie中是否存在SSO_token,如果存在,记录其长度
if $cookie_sso_token {
    log_on_rsp_header('sso_token', concat('len=', len($cookie_sso_token)))  
}
if is_missing($http_authorization) {
    if not(is_missing($cookie_sso_token)) {
       #请求头中Authorization不存在且Cookie中SSO_token存在时,将SSO_token作为Bearer Token注入到Authorization请求头中,并记录该场景
       add_req_header('authorization', concat('Bearer ',$cookie_sso_token))      
       add_rsp_header('ascript-log', 'use sso_token as authorization in request header') 
    } else {
       #请求头中Authorization不存在且Cookie中SSO_token不存在时,记录该场景
       add_rsp_header('ascript-log', 'authorization is missing and cookie sso_token is missing too')         
    }  
} else {
    #如果请求头中Authorization存在时,记录该场景
    log_on_rsp_header('miss-authorization', 'val = false')
}
image

操作步骤

步骤一:添加AScript可编程脚本定义的转发规则

  1. 登录应用型负载均衡ALB控制台

  2. 实例页面,单击目标实例ID。

  3. 单击监听页签,然后单击已创建的目标监听ID。

  4. 单击转发规则页签,在请求方向转发规则页签,单击在规则执行前添加可编程脚本

    说明

    选择响应方向转发规则时,只允许在规则执行前添加可编程脚本

  5. 添加可编程脚本页面添加规则,然后单击确定

    参数

    描述

    规则名称

    输入自定义规则名称。

    规则代码

    输入规则代码。本文输入以下代码示例。

    def is_missing(val){
        if val{
            return or(null(val),le(len(val),1))
        }else{
            return true
        }
    }
    def log_on_rsp_header(key, msg) {
        add_rsp_header(concat('ascript-log_', key), msg) 
    }
    
    if $http_authorization {
        log_on_rsp_header('authorization', concat('len=', len($http_authorization)))
    }
    if $cookie_sso_token {
        log_on_rsp_header('sso_token', concat('len=', len($cookie_sso_token)))  
    }
    
    if is_missing($http_authorization) {
        if not(is_missing($cookie_sso_token)) {
           add_req_header('authorization', concat('Bearer ',$cookie_sso_token))      
           add_rsp_header('ascript-log', 'use sso_token as authorization in request header') 
        } else {
           add_rsp_header('ascript-log', 'authorization is missing and cookie sso_token is missing too')         
        }  
    } else {
        log_on_rsp_header('miss-authorization', 'val = false')
    }

    执行位置

    规则执行位置,不可更改。本文为请求方向规则执行前

    启用状态

    规则启用状态。本文使用默认开启。

    高级配置

    本文选择默认不开启。

步骤二:设置域名解析

复制ALB实例对应的DNS名称,完成以下步骤,为您的自有域名添加1条指向ALB实例DNS名称的CNAME记录。

  1. 登录域名解析控制台

  2. 域名解析页面单击添加域名

  3. 添加域名对话框输入您的主机域名,然后单击确认

    重要

    您的主机域名需已通过TXT记录验证。

  4. 在目标域名的操作列单击解析设置

  5. 解析设置页面,单击添加记录

  6. 添加记录面板,配置以下信息完成CNAME解析配置,然后单击确认

    配置

    说明

    记录类型

    在下拉列表中选择CNAME

    主机记录

    您的域名的前缀。

    解析请求来源

    选择默认。

    记录值

    输入域名对应的CNAME地址,即您复制的ALB实例的DNS名称。

    TTL

    全称Time To Live,表示DNS记录在DNS服务器上的缓存时间,本文使用默认值。

步骤三:结果验证

  1. 测试网络请求。

    以任意一台可以访问公网的客户端为例。打开客户端的cmd窗口,执行以下命令。由于请求头中不存在Authorization,Cookie中不存在SSO_token,可以看到响应头输出日志为authorization is missing and cookie sso_token is missing too

    curl -v http://<访问地址>

    image

  2. 测试Cookie中携带SSO_token发送请求。

    执行以下命令,向请求头中Cookie中添加SSO_token。可以看到响应头中输出日志为ascript-log_sso_token: len=13use sso_token as authorization in request header

    curl -v -b "sso_token=ah$sgdj#sgava" http://<访问地址>

    image

  3. 测试请求头中携带Authorization发送请求。

    执行以下命令,向请求头中添加Authorization。可以看到响应头输出日志ascript-log_authorization: len=20ascript-log_miss-authorization: val = false

    curl -v -H "authorization: Bearer ah$sgdj#sgava" http://<访问地址>

    image

根据以上测试结果表明:鉴权凭证的内容、格式,以及如何替换或增强这些凭证,都能通过AScript来完成。您可以根据实际场景编写自定义的鉴权规则。

场景三:定制化请求头和响应头控制

某企业在阿里云某地域使用ALB部署了业务,后端服务器组包含了多台已部署应用的服务器。改企业因业务发展,现在需要实现跨域资源共享(CORS)。具体来说,不同域名的前端应用需要访问这些服务器上托管的资源和服务。由于同源策略的限制,跨域请求被默认阻止,导致资源无法正常加载,从而影响了用户体验和业务流程的流畅性。此外,企业还需要根据不同请求头实现灵活的跨域策略,以满足多种跨域访问需求。

ALB的标准转发规则在处理复杂的跨域策略时显得不够灵活,无法在同一条转发规则中针对不同请求头实现有效的跨域策略。为解决这一问题,企业利用AScript的强大自定义能力来增强ALB的灵活性。

通过AScript,企业能够实现以下功能:

  • 判断请求是否来自合法的跨域请求头。

  • 识别请求源 (Origin 或 Referer),确定请求是否来自被允许的域。

  • 动态地添加Access-Control-Allow-Origin和其他相关的跨域资源共享响应头,以允许来自特定域的跨域请求。

  • 提供更精细的控制,诸如限制可用的HTTP头部和帧选项。

本文以如下场景为例,企业通过AScript配置了特定的业务逻辑:当请求访问ALB实例时,ALB会根据配置的AScript规则检查请求源是否来自特定域(例如example.com,example.org或test.com)。如果匹配成功,ALB将动态添加与跨域资源共享相关的响应头,从而支持合法请求的跨域交互。

对应的AScript规则

h = $http_origin
if not(h) {
    h = $http_referer
}

pcs = capture_re(h, '^(.*?)(\.example\.com|\.example\.org|\.test\.com)(:\d+)?')
sec1 = get(pcs, 1)
sec2 = get(pcs, 2)
sec3 = get(pcs, 3)

if (sec2) {
    add_rsp_header('cross-origin-resource-policy', 'cross-origin')
    add_rsp_header('access-control-allow-methods', 'GET,PUT,POST,DELETE,UPDATE,OPTIONS')
    add_rsp_header('access-control-allow-credentials', 'true')
    add_rsp_header('access-control-allow-headers', 'Cookie,Set-Cookie,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Host,Origin,csrf-token-fe1a2a3s12,xhrFields')
    if not(sec3) {
        add_rsp_header('access-control-allow-origin', concat(sec1, sec2))
        add_rsp_header('x-frame-options', concat('ALLOW-FROM ', sec1, sec2))
    } else {
        add_rsp_header('access-control-allow-origin', concat(sec1, sec2, sec3))
    }
}
image

操作步骤

步骤一:添加AScript可编程脚本定义的转发规则

  1. 登录应用型负载均衡ALB控制台

  2. 实例页面,单击目标实例ID。

  3. 单击监听页签,然后单击已创建的目标监听ID。

  4. 单击转发规则页签,在请求方向转发规则页签,单击在规则执行前添加可编程脚本

    说明

    选择响应方向转发规则时,只允许在规则执行前添加可编程脚本

  5. 添加可编程脚本页面添加规则,然后单击确定

    参数

    描述

    规则名称

    输入自定义规则名称。

    规则代码

    输入规则代码。本文输入以下代码示例。

    h = $http_origin
    if not(h) {
        h = $http_referer
    }
    
    pcs = capture_re(h, '^(.*?)(\.example\.com|\.example\.org|\.test\.com)(:\d+)?')
    sec1 = get(pcs, 1)
    sec2 = get(pcs, 2)
    sec3 = get(pcs, 3)
    
    if (sec2) {
        add_rsp_header('cross-origin-resource-policy', 'cross-origin')
        add_rsp_header('access-control-allow-methods', 'GET,PUT,POST,DELETE,UPDATE,OPTIONS')
        add_rsp_header('access-control-allow-credentials', 'true')
        add_rsp_header('access-control-allow-headers', 'Cookie,Set-Cookie,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Host,Origin,csrf-token-fe1a2a3s12,xhrFields')
        if not(sec3) {
            add_rsp_header('access-control-allow-origin', concat(sec1, sec2))
            add_rsp_header('x-frame-options', concat('ALLOW-FROM ', sec1, sec2))
        } else {
            add_rsp_header('access-control-allow-origin', concat(sec1, sec2, sec3))
        }
    }

    执行位置

    规则执行位置,不可更改。本文为请求方向规则执行前

    启用状态

    规则启用状态。本文使用默认开启。

    高级配置

    本文选择默认不选择。

步骤二:设置域名解析

复制ALB实例对应的DNS名称,完成以下步骤,为您的自有域名添加1条指向ALB实例DNS名称的CNAME记录。

  1. 登录域名解析控制台

  2. 域名解析页面单击添加域名

  3. 添加域名对话框输入您的主机域名,然后单击确认

    重要

    您的主机域名需已通过TXT记录验证。

  4. 在目标域名的操作列单击解析设置

  5. 解析设置页面,单击添加记录

  6. 添加记录面板,配置以下信息完成CNAME解析配置,然后单击确认

    配置

    说明

    记录类型

    在下拉列表中选择CNAME

    主机记录

    您的域名的前缀。

    解析请求来源

    选择默认。

    记录值

    输入域名对应的CNAME地址,即您复制的ALB实例的DNS名称。

    TTL

    全称Time To Live,表示DNS记录在DNS服务器上的缓存时间,本文使用默认值。

步骤三:结果验证

  1. 使用没有被允许的请求源进行测试。

    以任意一台可以访问公网的客户端为例。打开客户端的cmd窗口,执行以下命令。设置请求源为http://www.example.cn,可以看到响应头中未添加Access-Control-Allow-Origin 和其他相关的 CORS 响应头。

    curl -H "Origin: http://www.example.cn" -v http://<访问地址>

    image

  2. 使用被允许的请求源进行测试。

    执行以下命令,将请求源设置为http://www.example.com,可以看到响应头已添加了与跨域相关的响应头。

    curl -H "Origin: http://example.com" -v http://<访问地址>

    image

相关文档