公司的服务器遭受了攻击,某些人不停调用公司服务器发送短信的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}