公司的服务器遭受了攻击,某些人不停调用公司服务器发送短信的api,真是有够无聊的。

由于我们的架构是前面F5-Big-ip,后面接了N个Tomcat,那就直接写个F5的irule来阻止它。

阻止GET请求的频率,30秒只允许单个ip发5次

假设GET的模式是
GET /seendsms.do?mobile=13800000000&msg=aaaaaaaa  

irule里有个非常神奇的东西,table,大家可以理解为是一个会话表,基本操作是key-value型,有生存时间,这点最重要。

详细的大家可以去看:

https://devcentral.f5.com/wiki/iRules.table.ashx

阻止GET的irule:

when RULE_INIT {  
  set static::windowSecs 30
}


when HTTP_REQUEST {  
    if { ( [HTTP::method] equals "GET" ) && ( [HTTP::uri] starts_with "/sendsms.do" ) } {
            set myUserId [IP::client_addr]
            set myMaxRate 5
            if { $myMaxRate ne "" } {
                set reqnum [table incr "req:$myUserId"]
                set tbl "countpost:$myUserId"
                table set -subtable $tbl $reqnum "ignored" indef $static::windowSecs
                if { [table keys -subtable $tbl -count] > $myMaxRate } {
                    HTTP::respond 403 "Block"
                    return
                }
            }
    }
}

来个复杂的例子:

假如POST的请求如下:

POST /api/sendMessage.htm HTTP/1.1  
Content-Length: 203  
Content-Type: application/x-www-form-urlencoded; charset=UTF-8  
Host: 172.8.2.23  
Connection: Keep-Alive  
User-Agent: Apache-HttpClient/4.5 (Java/1.7.0_51)  
Accept-Encoding: gzip,deflate

action=order.sumit.order&jsonData=%7B%22channelCode%22%3A%22%22%2C%22mobiles%22%3A%5B%2215176989787%22%5D%2C%22source%22%3A%22pop%22%2C%22tempParameters%22%3A%5B%22480827%22%2C%2291%22%5D%2C%22templateId%22%3A2%7D  

如果我们要组织post /api/sendMessage.htm,action=sendmsg的话,就比较复杂一些,我们判断uri满足条件后,还要进一步判断content的内容:

when RULE_INIT {  
  set static::windowSecs 10
}


when HTTP_REQUEST { 

    if { ( [HTTP::method] equals "POST" ) && ( [HTTP::uri] equals "/api/sendMessage.htm" ) && ([HTTP::header "Content-Length"] <= 2048) } {
        HTTP::collect [HTTP::header Content-Length]
    }
}

when HTTP_REQUEST_DATA {

    set myUserId [IP::client_addr]
    set mymethod "unknown"

    foreach x [split [string tolower [HTTP::payload]] "&"] {
        if { $x starts_with "action=" } {
            set mymethod [lindex [split $x "="] 1]
        }
    }

    if { $mymethod equals "order.submit.order" }
    {
        set myMaxRate 5
        if { $myMaxRate ne "" } {
            set reqnum [table incr "req:$myUserId"]
            set tbl "countpost:$myUserId"
            table set -subtable $tbl $reqnum "ignored" indef $static::windowSecs
            if { [table keys -subtable $tbl -count] > $myMaxRate } {
                HTTP::respond 403 "Block"
                return
            }
        }
    }
}
comments powered by Disqus