Join the community today
Register Now

Featured Security CSF Firewall native fail2ban functionality

Discussion in 'System Administration' started by eva2000, Apr 12, 2018.

  1. rdan

    rdan Well-Known Member

    4,962
    1,183
    113
    May 25, 2014
    Ratings:
    +1,797
    Local Time:
    4:32 PM
    Mainline
    10.2
    Results nothing Sir.
     
  2. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    your own ISP ip if same as one used to install Centmin Mod, would have ISP ip whitelisted in CSF Firewall automatically too
     
  3. rdan

    rdan Well-Known Member

    4,962
    1,183
    113
    May 25, 2014
    Ratings:
    +1,797
    Local Time:
    4:32 PM
    Mainline
    10.2
    I remove it also as my ISP is dynamic :D.

    But the server IP I used to test attack was DigitalOcean droplet.
    Not whitelisted on my server also.
     
  4. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    I think i sorted it out for both main hostname and vhost error logs - problem wasn't getting the IP address correctly
    Code (Text):
    # /home/nginx/domains/*/log/error.log
    # https://community.centminmod.com/posts/74546/
    # Nginx connection limit rule trigger (Default: 10 errors bans for 15mins)
    if (($globlogs{CUSTOM2_LOG}{$lgfile}) and ($line =~ /.*limiting connections by zone .*, client: (\S+),(.*)/)) {
        return ("NGINX Security rule triggered from",$1,"nginx_conn_limit","10","80,443","900","0");
    }
    
    # /var/log/nginx/localhost.error.log
    # https://community.centminmod.com/posts/74546/
    # Nginx connection limit rule trigger (Default: 10 errors bans for 15mins)
    if (($globlogs{CUSTOM4_LOG}{$lgfile}) and ($line =~ /.*limiting connections by zone .*, client: (\S+),(.*)/)) {
        return ("NGINX Security rule triggered from",$1,"nginx_conn_limit_localhost","10","80,443","900","0");
    }
    


    test run checking temp banned ip = xxx.xxx.xxx.xxx
    Code (Text):
    csf -g xxx.xxx.xxx.xxx
    
    Table  Chain            num   pkts bytes target     prot opt in     out     source               destination         
    
    filter DENYIN           2        0     0 DROP       all  --  !lo    *       xxx.xxx.xxx.xxx       0.0.0.0/0
    
    filter DENYOUT          2        0     0 LOGDROPOUT  all  --  *      !lo     0.0.0.0/0            xxx.xxx.xxx.xxx
    
    IPSET: No matches found for xxx.xxx.xxx.xxx
    
    
    ip6tables:
    
    Table  Chain            num   pkts bytes target     prot opt in     out     source               destination         
    No matches found for xxx.xxx.xxx.xxx in ip6tables
    
    Temporary Blocks: IP:xxx.xxx.xxx.xxx Port: Dir:inout TTL:900 (lfd - (nginx_conn_limit_localhost) NGINX Security rule triggered from xxx.xxx.xxx.xxx (US/United States/-): 10 in the last 3600 secs)
    
     
  5. rdan

    rdan Well-Known Member

    4,962
    1,183
    113
    May 25, 2014
    Ratings:
    +1,797
    Local Time:
    4:32 PM
    Mainline
    10.2
    Thanks a lot!

    Works great now.
     
  6. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    Thanks for confirmation, might add it to default rules in 1st post eventually :)
     
  7. rdan

    rdan Well-Known Member

    4,962
    1,183
    113
    May 25, 2014
    Ratings:
    +1,797
    Local Time:
    4:32 PM
    Mainline
    10.2
    My regex config:
    Code (Text):
    # /home/nginx/domains/*/error.log
    # Nginx Connection Limit per IP errors (Default: 100 errors bans for 6 hours)
    if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /.*limiting connections by zone .*, client: (\S+),(.*)/)) {
        return ("Nginx Conn Limit per IP triggered from",$1,"nginx_limit_conn","100","80,443","21600","0");
    }
    


    Then I got this email notice:
    What is this Interval: 3600 seconds?

    Thanks!
     
  8. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    interval is time time it evaluates those hits, so 100 errors or hits over past 3600 seconds will ban for 6 hrs

    off top of my head, believe it's related to
    Code (Text):
    # Set the time interval to track login and other LF_ failures within (seconds),
    # i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds
    LF_INTERVAL = "3600"
    

    you can verify by changing value to 3601 and restarting csf firewall
    Code (Text):
    csf -ra

    and testing
     
  9. rdan

    rdan Well-Known Member

    4,962
    1,183
    113
    May 25, 2014
    Ratings:
    +1,797
    Local Time:
    4:32 PM
    Mainline
    10.2
    1 hour is perfectly fine to me, so I leave it as is for now.
    Thanks!
     
  10. pamamolf

    pamamolf Premium Member Premium Member

    3,826
    370
    83
    May 31, 2014
    Ratings:
    +712
    Local Time:
    11:32 AM
    Nginx-1.17.x
    MariaDB 10.3.x
    Very good :)
     
  11. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    FYI, just updated the default template in 1st post setup instructions with the connection rate limit native CSF Firewall ban rules - default is if more than 30 entries for connection rate limit detected in nginx error log, ban for 60 mins (3600 seconds).
     
  12. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    hey, thanks.
    I checked my log files that i'm also being targeted by these scans. Especially after i installed the pma addon
     
  13. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    To enable logging of user enumeration and spam control it is necessary, in addition to installing the plugin, to add some filters in functions.php thebrandonallen/wp-fail2ban-redux


    Code:
    // Block user enumeration attempts.
    add_filter( 'wp_fail2ban_redux_block_user_enumeration', '__return_true' );
    
    // Log spammed comments.
    add_filter( 'wp_fail2ban_redux_log_spam_comments', '__return_true' );
     
  14. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    it would be great to add a regex to block bruteforce attacks in wordpress login.

    Code:
    Jul 11 12:31:54 hostname wp(domain.org)[6343]: Authentication failure for admin from 123.123.123.123
     
  15. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    is that from wp-fail2ban-redux logging ?

    would be simple cause of making a copy of the below regex for admin user
    Code (Text):
    # Wordpress fail2ban plugin https://wordpress.org/plugins/wp-fail2ban-redux/
    # (Default: 2 errors bans for 24 hours)
    if (($globlogs{SYSLOG_LOG}{$lgfile}) and ($line =~ /.*Authentication attempt for unknown user .* from (.*)\n/)) {
      return ("Wordpress unknown user from",$1,"fail2ban_unknownuser","2","80,443","86400","0");
    }
    


    i.e.
    Code (Text):
    # Wordpress fail2ban plugin https://wordpress.org/plugins/wp-fail2ban-redux/
    # (Default: 2 errors bans for 24 hours)
    if (($globlogs{SYSLOG_LOG}{$lgfile}) and ($line =~ /.*Authentication failure for admin .* from (.*)\n/)) {
      return ("Wordpress admin user from",$1,"fail2ban_adminuser","2","80,443","86400","0");
    }
    
     
  16. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    if I understood correctly, does this only work for the user "admin"?

    because here when I replace the real username with admin

    Code:
    Jul 11 12:31:54 hostname wp(domain.org)[6343]: Authentication failure for USERNAME from 123.123.123.123
    
    Jul 11 12:31:54 hostname wp(domain.org)[6343]: Authentication failure for eva from 123.123.123.123
    
     
  17. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    removing reference to admin should work for all users
    Code (Text):
    # Wordpress fail2ban plugin https://wordpress.org/plugins/wp-fail2ban-redux/
    # (Default: 2 errors bans for 24 hours)
    if (($globlogs{SYSLOG_LOG}{$lgfile}) and ($line =~ /.*Authentication failure for .* from (.*)\n/)) {
      return ("Wordpress admin user from",$1,"fail2ban_adminuser","2","80,443","86400","0");
    }
    
     
  18. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    thank you eva! you are the master!
     
  19. fabianski

    fabianski Member

    102
    14
    18
    Feb 20, 2019
    Brazil
    Ratings:
    +36
    Local Time:
    5:32 AM
    The rule for nginx 444 of the logs in /home/nginx/domains/*/log/access.log is not working correctly.

    If the file name or url has the number 444 the user who accessed it will be banned (after five times, of course)

    Example:
    The autoptimize generates the cache files with a random name with multiple numbers, so when one is generated with 444 the current rule will consider it to be an nginx error.

    Today autoptimize generated a file under these conditions, and I received several banned ips alerts in the e-mail.

    Code:
    https://domain.org/wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css
    The alerts were like these:

    Code:
    Time: Sat Jul 13 21:10:16 2019 -0300
    IP: 123.123.123.123
    Failures: 5 (nginx_444)
    Interval: 3600 seconds
    Blocked: Temporary Block for 86400 seconds [LF_CUSTOMTRIGGER]
    
    Log entries:
    
    123.123.123.123 - - [13/Jul/2019:21:05:41 -0300] "GET /wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css HTTP/2.0" 200 5860 "https://domain.org/some-thing/?v=19d3326f3137" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
    123.123.123.123 - - [13/Jul/2019:21:05:42 -0300] "GET /wp-content/uploads/2019/05/books-mockup-lying-on-a-white-surface-a17401bcdef.png HTTP/2.0" 200 25060 "https://domain.org/wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
    123.123.123.123 - - [13/Jul/2019:21:05:42 -0300] "GET /wp-content/uploads/2019/06/fundo-de-madeira-velho-grunge-textured-escuro-a-superficie-da-textura-de-madeira-marrom-velha_7182-333.jpg HTTP/2.0" 200 21206 "https://domain.org/wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
    123.123.123.123 - - [13/Jul/2019:21:05:42 -0300] "GET /wp-content/uploads/2019/06/istockphoto-698791078-612x612.jpg HTTP/2.0" 200 16836 "https://domain.org/wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
    123.123.123.123 - - [13/Jul/2019:21:05:42 -0300] "GET /wp-content/uploads/2019/06/background-white.jpg HTTP/2.0" 200 29068 "https://domain.org/wp-content/cache/autoptimize/css/autoptimize_single_4444afe7b4ee6787f32ca4602da6f308.css" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" 
    It also happened when there was a 444 before the url (I do not know what this 39444 means)

    Code:
    123.123.123.123 - - [13/Jul/2019:20:27:47 -0300] "GET /wp-content/themes/buddyboss-theme/assets/icons/bb-icons.woff2?47177912 HTTP/2.0" 200 39444 "https://domain.org/wp-content/cache/autoptimize/css/autoptimize_6d18e1013b9f0cf82f5d654018eef799.css" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" 
     
  20. eva2000

    eva2000 Administrator Staff Member

    44,743
    10,200
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +15,809
    Local Time:
    6:32 PM
    Nginx 1.17.x
    MariaDB 5.5/10.x
    thanks for heads up

    try changing the 444 regex from
    Code (Text):
    # /home/nginx/domains/*/log/access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*(444)/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }
    
    # /var/log/nginx/localhost.access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM3_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*(444)/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }
    

    to
    Code (Text):
    # /home/nginx/domains/*/log/access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*( 444 )/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }
    
    # /var/log/nginx/localhost.access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM3_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*( 444 )/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }
    

    or
    Code (Text):
    # /home/nginx/domains/*/log/access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*(\s444\s)/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }
    
    # /var/log/nginx/localhost.access.log
    # Nginx 444  (Default: 5 errors bans for 24 hours)
    if (($globlogs{CUSTOM3_LOG}{$lgfile}) and ($line =~ /(\S+) -.*[GET|POST|HEAD].*(\s444\s)/)) {
       return ("Nginx 444",$1,"nginx_444","5","80,443","86400","0");
    }