📜 ⬆️ ⬇️

A simple way to protect against distributed brute-force access to the CMS

Good day everyone.
The Rusonix team solved problems with electricity and wrote a beautiful post with beautiful pictures about “Distributed brute force attack on CMS from the point of view of the hoster”.
However, there is not enough of one - the actual implementation.

So the goals of this post are:

If it is interesting, I ask under habrakat.

Let's repeat just in case the goals of the struggle:


Logics:
0. Nginx works like the most common front. Apache and everything else behind.
1. When a certain limit is exceeded, we show the user a mold where you need to do something (in my case - just press the button), thereby proving that he is a human being.
2. In the future, skip a person without delay.
')
The decision was simple, all the comments on the go.

#  .  limit_req_zone $binary_remote_addr zone=one:10m rate=5r/m; server { # ... root /var/wl-web; recursive_error_pages on; #     error_page   @limit -> @wlgui; location / { #...       } #      . location @wlgui { #   fpm,      . internal; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/wlgui.php; fastcgi_intercept_errors on; include fastcgi_params; } #  .     ""   location ~* /(i|i2)\.html$ { #     "" 503 (c 1.3.15      ) #limit_req_status 516; error_page 503 = @limit; #  .      @limit limit_req zone=one nodelay; #  ,     . # .     URI,   . proxy_pass http://127.0.0.1:8080$request_uri; proxy_set_header Host $host; #      } #    location @limit { internal; #     ,          . if ($cookie_wlsid ~* [^af\d]) { return 503; } #   ,      =( #error_page 516 @backend; #try_files /wl/$cookie_wlsid.cookie /wl/$remote_addr.ip /wl/$remote_addr-$host.iph @wlgui; #if ($uri ~* /wl/[az\d]+\.cookie ) {return 516;} #         .. "". #    (.     ),  . If is Evil, i know.... error_page 516 = @wlgui; if ( !-f $document_root/wl/$cookie_wlsid.cookie) {return 516;} #  !  . proxy_pass http://127.0.0.1:8080$request_uri; proxy_set_header Host $host; #      } } 


and a very simple wlgui.php, which “authorizes” cookies by creating an empty file with a name equal to the value of the cookie.
(It is important to remember to create a wl folder in / var / wl-web and put the corresponding rights on it)
 <?php if (!empty($_POST['wlsec'])){ #   ,       . $cookie=md5(uniqid()); setcookie('wlsid',$cookie,time()+3600*24*90/*90d*/); touch ('/var/wl-web/wl/'.$cookie.'.cookie'); echo "Done! Please, refresh the page! (setting {$cookie})"; } else { ?> <form method="POST"> <input name="wlsec" value="GetAccess" type="submit"> </form> <?php echo "<br> Your cookie:".(isset($_COOKIE['wlsid'])?htmlspecialchars($_COOKIE['wlsid']):'(not set)'); } 


Possible improvements:


Well, as usual: typos in a personal, questions / additions / improvements in the comments.
Links: Nginx limit_req_module , basic things for the kernel and proxy .

Thank you for reading to the end!
- Respectfully,
Lazutov Alexander

PS
By the nature of my activity, I’m not very closely involved in setting up server software and other sysadmins, so I think this solution is conceptual, although it worked in production for some time (then I just got around to rename the admins).

Source: https://habr.com/ru/post/190112/


All Articles