The fundamentals of 0x00 cc attacks
cc attack uses proxy server to send a large number of URL requests that require longer computation time, such as database query, which causes the server to do a lot of computing and quickly achieve its own processing capacity to form a DOS. An attacker who sends a request to an agent is actively disconnected, because the agent does not connect to the target server because the client side of the connection is disconnected. Therefore, the resource consumption of the attack aircraft is relatively small, and from the target server, the request from the agent is legal.
Previous methods to prevent CC attacks
To prevent CC, the previous approach is to limit the number of connections per IP, which is difficult to implement in the case of a wide range of addresses; the second is to restrict the access of the proxy, because the general agent takes the X_forwarded_for field in the HTTP header, but there are limitations, Some agents do not have the field in the request, and other clients do need agents to connect to the target server, this restriction will deny some normal user access.
CC attacks are hard to defend against.
CC attacks are more frightening than DDoS attacks, where CC attacks are generally hard to prevent.
There are three reasons for personal analysis:
First, because the CC attacks to the IP is true, decentralized;
Second, the CC attack data packets are normal packets;
Third, the CC attack requests, all are valid requests, cannot reject the request.
Anti-CC attack ideas
Anti-CC effectiveness is that the attacker does not accept the server response data, send the request after the active disconnect, so to confirm the connection is CC, the server side does not immediately execute the URL request command, but simply return a page to turn the response, the response contains a new URL request address. If it is normal access, the client will be actively connected to the turn page again, transparent to the user, and for CC attackers, because do not receive the response data, so will not reconnect, the server does not need to continue to operate.
0x01 Verify Browser behavior
Simple version
Let's make a metaphor first.
The community is doing welfare and distributing red envelopes to everyone in the square. And the bad guys sent a bunch of humanoid robots (no language modules) to claim red envelopes, and smart workers need to figure out ways to prevent them from being falsely accused.
So the staff in the red envelopes, will give the recipient a piece of paper, which says "red envelopes", if the person can read the word on paper, then is the person, give red envelopes, if you can not read out, then consciously. So the robot was found, and returned in a dingy way.
Yes, in this analogy, people are browsers, robots are attackers, and we can identify them by identifying the cookie function (read the word on paper). The following is the Nginx configuration file notation.
if ($cookie _say!= "HBNL") {
add_header Set-cookie "SAY=HBNL";
Rewrite. * "$scheme://$host $uri" REDIRECT;
}
Let's see what these lines mean. When say is empty in the cookie, give a 302 redirect packet that sets the cookie say to HBNL, if the visitor can carry the cookie value in the second package, then can visit the website normally, if cannot, that he lives in 302 forever. You can also test, using CC attackers or webbench or direct curl to test the contract, they live in the 302 world.
Of course, it's so easy to stop. Of course it's not that simple.
Enhanced version
Be careful you will find that the configuration file is still flawed. If the attacker sets the cookie to SAY=HBNL (this can be set on the CC attacker), then the defense is not in the same place. Let's continue to illustrate the problem with the analogy we just took.
The villain found this rule, to each robot installed the speaker, has been repeated "red envelopes, red envelopes to bring", mighty again to get red envelopes.
At this time, the staff's response is to do so, ask the recipient to show their own name of the hukou, and read out their own name, "I am xxx, red envelopes to bring." So a group of "red envelopes" of the robot was sent back.
Of course, in order to cooperate with the explanation of the problem, each robot is a hukou, the reason to be driven back is not read their own name, although this is a bit absurd, alas.
And then, let's look at the way the configuration file is written
if ($cookie _say!= "Hbnl$remote_addr") {
add_header Set-cookie "say=hbnl$remote_addr";
Rewrite. * "$scheme://$host $uri" REDIRECT;
}
This writing and the previous difference is that the different IP request cookie value is not the same, such as IP is 1.2.3.4, then the need to set the cookie is say=hbnl1.2.3.4. The attacker would then be unable to circumvent the restriction by setting the same cookie, such as the CC attacker. You can continue to test with the CC attacker, and you'll find that the CC attacker's traffic has all gone into the 302 world.
But you can also feel that this does not seem like a foolproof idea, because if an attacker studies the mechanism of a Web site, there is always a way to detect and pre-empt the setting of cookie values. Because we do differentiated data sources are some of their own information (IP, user agent, etc.). It is also possible for an attacker to make an attack script specifically for a Web site.
Perfect version
So how do they get their own information and they come up with a value they can't figure out?
I think you must have guessed the smart one, and hash it out with salt. For example, MD5 ("OPENCDN$REMOTE_ADDR"), although the attacker knew he could own IP, but he could not know how to use his IP to calculate the hash, because he is not the inverse of this hash. Of course, if you are not at ease, afraid of cmd5.com in case you can find out, you can add some special characters, and then more scattered several times.
Unfortunately, nginx default is unable to do string hashing, so we use the Nginx_lua module to implement.
Rewrite_by_lua ' local
say = Ngx.md5 ("Opencdn" ... ngx.var.remote_addr)
if (Ngx.var.cookie_say ~=) say
ngx.header["Set-cookie"] = "say=". Say return
Ngx.redirect (ngx.var.scheme. "://" .. Ngx.var.host.. Ngx.var.uri)
end
';
With such a configuration, the attacker would not be able to calculate the say value in the cookie beforehand, so the attack traffic (proxy cc and lower-level contract cc) would be out of 302 hell.
As you can see, in addition to borrowing the MD5 function, other logic is exactly the same as the above. So if you can, you can install a Nginx third-party module to do it, and it may be more efficient.
This configuration can be placed in any location inside, if your site has external API functionality, the recommended API must not join this paragraph, because the API calls are not browser behavior, will be treated as attack traffic. Also, some of the weaker reptiles will be trapped in the 302, which should be noted.
At the same time, if you think set-cookie this action seems to be an attacker may also be through the parse string simulation, you can put the above through the header to set the cookie operation, into the high-end atmosphere of JS completed, send back a containing doument.cookie= ... The text can be.
So, is the attack completely blocked? Can only say that those low-level attacks have been blocked, if the attacker must pay a large price for each attacker to add WebKit module to parse JS and execute Set-cookie, then he can escape 302 hell, in Nginx, it is true that the attack flow and normal browsing traffic is the same. So how to defend it? The next section will tell you the answer.
0x02 Request Frequency limit
Have to say, many of the measures to prevent CC is directly in the frequency of the request to do a limit to achieve, but, many have a certain problem.
So what are the problems?
First of all, if the IP to limit the frequency of requests, easily lead to some manslaughter, such as I am a place to export IP so a few, and a lot of visitors, the request frequency is very easy to the upper limit, then that place users will not be able to access your site.
So you would say, I use the session to limit the problem. Well, your session opens a door for attackers. Why, then? You probably already know that, because like the "red envelope" speakers, many languages or frames of the session can be forged. In PHP, for example, you can see Phpsessionid in the browser cookie, this ID is different, the session will be different, and then if you make up a phpsessionid past, you will find that the server also recognized this ID, A session was initialized for this ID. In that case, an attacker would be able to easily evade the limit on the number of requests on the session by constructing a new SessionID each time the package was sent.
So how do we make this request-frequency limit?
First, we need a sessionid that an attacker cannot fabricate, one way is to use a pool to record each given ID, then make a query when the request comes, and if not, reject the request. This way we do not recommend, first of all, a Web site already has a session pool, so it is no doubt a bit wasteful, but also need to go through the pool traversal comparison query, too consuming performance. What we want is a sessionid that can be stateless. OK.
Rewrite_by_lua ' local
random = Ngx.var.cookie_random
if (random = = nil) then random
= Math.random (999999) C4/>end local
token = NGX.MD5 ("Opencdn" ... ngx.var.remote_addr)
if (random Ngx.var.cookie_token ~=) token
ngx.header["Set-cookie"] = {"Token=" ... token, "random=".. random} return
Ngx.redirect (ngx.var.scheme. "://" .. Ngx.var.host.. Ngx.var.uri)
end
';
Do you think it looks familiar? Yes, this is the last section of the perfect version of the configuration and add a random number, so that the same IP users can have different token. Similarly, as long as there are nginx Third-party modules that provide hashing and random number functions, this configuration can be done without LUA directly using a pure configuration file.
With this token, the equivalent of each visitor has a token that cannot be forged and unique, in which case the request restriction makes sense.
As a result of token do bedding, we can not do what white list, blacklist, directly through the limit module to complete.
http{...
Limit_req_zone $cookie _token zone=session_limit:3m rate=1r/s;
}
And then we just need to add the following token configuration.
Limit_req Zone=session_limit burst=5;
As a result, the two-line configuration allows Nginx to resolve the request frequency limit at the session level. There seems to be a flaw, however, because an attacker can break the request frequency limit by always acquiring token, and it is even more perfect to limit the frequency at which an IP acquires token. Can you do that? OK.
http{limit_req_zone $cookie _token zone=session_limit:3m rate=1r/s;
Limit_req_zone $binary _remote_addr $uri zone=auth_limit:3m rate=1r/m;
} location/{limit_req zone=session_limit burst=5; Rewrite_by_lua ' local random = Ngx.var.cookie_random if (random = = nil) then return Ngx.redirect ("/auth?url=" .. Ngx.var.request_uri) End Local token = NGX.MD5 ("Opencdn" ... ngx.var.remote_addr) if (random
En ~= token) then return ngx.redirect ("/auth?url=" ... ngx.var.request_uri) end ';
} location/auth {limit_req zone=auth_limit burst=1;
if ($arg _url = "") {return403; } Access_by_lua ' Local random = math.random (9999) Local token = NGX.MD5 ("Opencdn" ... Random) if (Ngx.var.cookie_token ~= token) then ngx.header["Set-cookie"] = {"Token=" ... token, "random=".. R
Andom} return to Ngx.redirect (Ngx.var.arg_url) end; }
I think we should have guessed that the principle of this configuration file is: to separate the original token function to a auth page, and then use limit to this auth page frequency limit can be. Here the frequency is 1 IP per minute authorized 1 token. Of course, this quantity can be adjusted according to the business needs.
It should be noted that this auth part of my LUA employs Access_by_lua because limit modules are executed after the rewrite phase, and rewrite will fail if the limit phase 302. Therefore, this LUA configuration I can not guarantee the use of the original configuration file, because I do not know how to use the configuration file in the rewrite phase after the 302 jump, also ask Daniel can enlighten ah.
Of course, if you are not satisfied with this limit, if you want to achieve a certain IP if the limit of more than a few days after the direct IP, it is also possible, you can use similar ideas to make a wrong page, and then reached the upper limit does not return 503 but jump to the wrong page, Then the error page also makes a request limit, such as only 100 visits a day, then when more than 100 errors (Request error page 100), the day the IP can no longer visit this site.
Thus, through these configurations we have achieved a website access frequency limit. However, such a configuration is not to say that you can completely prevent the attack, can only say that the cost of the attacker to become high, so that the site's ability to carry the attack strong, of course, the premise is nginx can carry these flows, and then bandwidth is not blocked dead. If your door is blocked and you want to open the door, there is no way.
Then, after the traffic protection, let's look at the defense of attacks like scanners.
0X03 Anti-Scan
NGX_LUA_WAF Module
This is a good WAF module, we will not repeat the wheel. Can directly use this module to do protection, of course, can also be fully coupled with the limit module, with the above ideas to do an IP or sealed session effect.
0X04 Summary
This article is intended to serve as a trigger, and we do not want you to simply duplicate the configuration of our examples, but rather to write a profile that suits your own site, depending on your business needs.