F5利用irule来防止Ddos的方法

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

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

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

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

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

详细的大家可以去看:

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

阻止GET的irule:

 1when RULE_INIT {  
 2  set static::windowSecs 30
 3}
 4
 5
 6when HTTP_REQUEST {  
 7    if { ( [HTTP::method] equals "GET" ) && ( [HTTP::uri] starts_with "/sendsms.do" ) } {
 8            set myUserId [IP::client_addr]
 9            set myMaxRate 5
10            if { $myMaxRate ne "" } {
11                set reqnum [table incr "req:$myUserId"]
12                set tbl "countpost:$myUserId"
13                table set -subtable $tbl $reqnum "ignored" indef $static::windowSecs
14                if { [table keys -subtable $tbl -count] > $myMaxRate } {
15                    HTTP::respond 403 "Block"
16                    return
17                }
18            }
19    }
20}

来个更加复杂的例子:

POST的请求如下:

1POST /api/sendMessage.htm HTTP/1.1  
2Content-Length: 203  
3Content-Type: application/x-www-form-urlencoded; charset=UTF-8  
4Host: 172.8.2.23  
5Connection: Keep-Alive  
6User-Agent: Apache-HttpClient/4.5 (Java/1.7.0_51)  
7Accept-Encoding: gzip,deflate
8
9action=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=的内容:

 1when RULE_INIT {  
 2  set static::windowSecs 10
 3}
 4
 5
 6when HTTP_REQUEST { 
 7
 8    if { ( [HTTP::method] equals "POST" ) && ( [HTTP::uri] equals "/api/sendMessage.htm" ) && ([HTTP::header "Content-Length"] <= 2048) } {
 9        HTTP::collect [HTTP::header Content-Length]
10    }
11}
12
13when HTTP_REQUEST_DATA {
14
15    set myUserId [IP::client_addr]
16    set mymethod "unknown"
17
18    foreach x [split [string tolower [HTTP::payload]] "&"] {
19        if { $x starts_with "action=" } {
20            set mymethod [lindex [split $x "="] 1]
21        }
22    }
23
24    if { $mymethod equals "order.submit.order" }
25    {
26        set myMaxRate 5
27        if { $myMaxRate ne "" } {
28            set reqnum [table incr "req:$myUserId"]
29            set tbl "countpost:$myUserId"
30            table set -subtable $tbl $reqnum "ignored" indef $static::windowSecs
31            if { [table keys -subtable $tbl -count] > $myMaxRate } {
32                HTTP::respond 403 "Block"
33                return
34            }
35        }
36    }
37}

用openssh的tunnel建立隧道翻墙
Keepalived与iptables Mark的联动
comments powered by Disqus