1

F5利用irule来防止Ddos的方法

 5 months ago
source link: https://bajie.dev/posts/20240111-f5_irule_ddos/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

F5利用irule来防止Ddos的方法

2024-01-11 2 分钟阅读

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

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

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

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

irule里有个非常神奇的东西,table,是session会话表的超表,基本操作是key-value型,带有生存时间,这点最重要。

详细的大家可以去看:

https://clouddocs.f5.com/api/irules/table.html

阻止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中action=的内容:

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
            }
        }
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK