Block wp-login and xmlrpc brute force attacks with CSF / cPanel

Another great counter attack to “flooders” on your WordPress installations. This time with CSF firewall. I had massive brute force attacks on WordPress installations on some cPanel server which were causing very high server loads.¬† Here is great way to block abusers with CSF firewall. Here is how.

First, create custom log from which CSF will be able to search for wp-login.php and xmlrpc.php requests. Edit your /etc/csf/csf.conf like bellow:

CUSTOM2_LOG = "/var/log/apache2/domlogs/*/*"

Because majority of those attacks are from some very well known country’s that are causing problems, you may want to white list country’s from which users shouldn’t be blocked. Add list of white list country’s in CC_IGNORE.

Then you must create custom functions for CSF so it will be able to block those attacks. Add this to your /usr/local/csf/bin/ file. If it’s not there, create one. Then add this:

if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /(\S+).*] "\w*(?:GET|POST) \/xmlrpc\.php.*" /)) {
return ("WP XMLPRC Attack",$1,"XMLRPC","5","80,443","1");

if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /(\S+).*] "\w*(?:GET|POST) \/wp-login\.php.*" /)) {
return ("WP Login Attack",$1,"WPLOGIN","5","80,443","1");

Restart CSF and check if LFD is doing his new job. On success you should see something like this:

May 10 11:33:16 cp lfd[589350]: (WPLOGIN) WP Login Attack (PL/Poland/ 5 in the last 600 secs - *Blocked in csf* [LF_CUSTOMTRIGGER]
May 10 11:33:36 cp lfd[589587]: (WPLOGIN) WP Login Attack (TR/Turkey/ 5 in the last 600 secs - *Blocked in csf* [LF_CUSTOMTRIGGER]
May 10 11:34:24 cp lfd[590012]: (WPLOGIN) WP Login Attack (DE/Germany/ 5 in the last 600 secs - *Blocked in csf* [LF_CUSTOMTRIGGER]83247]: (WPLOGIN) WP Login Attack (VN/Vietnam/-): 5 in the last 600 secs - *Blocked in csf* [LF_CUSTOMTRIGGER]

Requests for ignored country’s should look like this:

May 10 11:45:36 cp lfd[591718]: WP Login Attack - ignored
May 10 11:45:41 cp lfd[591718]: WP Login Attack - ignored

I hope this helps. ūüôā

Postfix – OpenDKIM not signing outgoing email (not authenticated)

I had this weird issue. On CentOS 7 I set up mail server with Postfix, Dovecot, ClamAV, rspamd and OpenDKIM. Everything was working fine except all of my outgoing emails weren’t signed by DKIM.

In mail log this message was shown:

Mar 2 14:02:16 vps opendkim[10810]: 6FD942E30BB: not authenticated
Mar 2 14:02:16 vps opendkim[10810]: 6FD942E30BB: no signature data

After a lot of trying different configs an options, I googled answer on this forum. Apparently, opendkim thought that user wasn’t authenticated, but in reality, it was. This was due to Postfix configuration. There was missing milter macro. I added {auth_type} macro to milter_mail_macros. Then restarted Opendkim and Postfix and it started to work properly.

Now my postfix configuration ( for milters looks like this:

milter_protocol = 6
milter_default_action = accept
milter_connect_macros = j {daemon_name} v {if_name} _
milter_mail_macros="i {mail_addr} {client_addr} {client_name} {auth_type} {auth_authen}"
smtpd_milters = inet:localhost:11332 inet:localhost:8891 unix:/var/spool/postfix/clamav/clamav-milter.socket
non_smtpd_milters = $smtpd_milters

And emails are getting signed correctly:

Mar 2 14:15:56 vps opendkim[11513]: 8C5213E36D: DKIM-Signature field added (s=mail,

CSF – whitelist user from SMTP_BLOCK

CSF features great option SMTP_BLOCK which block outgoing SMTP for all users except root, exim and mailman. I had a problem with one user which was using MailChimp as mass mailing within their application. Because of SMTP_BLOCK it wasn’t working. Disabling SMTP_BLOCK globally is not recommended, you can white list users for which you would like to allow sending.

Go to your CSF settings and find SMTP_ALLOWUSER. Then add user which should be allowed (users separated with coma). Don’t forget to restart CSF.

Get list of mass/multi domain redirects with CURL

I had large list of domains for which I had to check to which location are they pointing/redirecting. Curl is best option for this kind of work. To save some time, I wrote this simple one liner which will do that for you.

First, create txt file which will contain list of all domains that you want to check. For this example I will create domains.txt. 

Then, run this command – replace file name with yours.

> $ for i in `cat domains.txt`; do echo -n "$i -> "; curl -I -s -L -o /dev/null -w %{url_effective} -o /dev/null $i; echo "\t"; done

This will give you domain name with location to which it’s redirecting: -> -> -> -> -> https://www. ->

Password protect Netdata with NGINX / Permission denied while connecting to upstream error

Netdata is great free tool for generating server statistics. By default it’s open for entire world on port 19999 – It is not a good idea to leave this open so everyone can your system statistics.

One way to limit access from where it is accessible is by editing netdata.conf and specify IPS in “allow connections from” variable.

allow connections from = ip's that are allowed to access>

There is no option to password protect it. This can be done with NGINX. You can create reverse proxy, so that nginx will serve content from netdata application. To make netdata accessible on subfolder of your hostname, eg., then create nginx configuration like bellow.

First generate password file for nginx:

htpasswd -c /etc/nginx/.htpasswd "username"

Then create or edit existing nginx configuration to something like this:

upstream netdata {
        keepalive 64;

server {
     listen 443 ssl http2;
     location = /netdata {
         return 301 /netdata/;

    location ~ /netdata/(?.*) {

        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_redirect off;
        proxy_set_header Host $host;   

        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_pass_request_headers on;
        proxy_set_header Connection "keep-alive";
        proxy_store off;
        proxy_pass http://netdata/$ndpath$is_args$args;

        gzip on;
        gzip_proxied any;
        gzip_types *;

    error_log /var/log/nginx/error.log;
    access_log off;

Also, don’t forget to edit netdata.conf and change some variables. Make netdata accessible only from localhost (nginx):

bind to =
allow connections from = localhost
allow dashboard from = localhost

You should also allow connection to port 19999 only to local traffic (localhost).

Restart nginx and netdata, then try to access like: http(s)://

If you’re getting error like bellow in your nginx error log, than chances are that SELinux is active. Disable selinux or execute this command “setsebool -P httpd_can_network_connect true”.

[crit] 8411#0: *1 connect() to failed (13: Permission denied) while connecting to upstream, client:, server:, request: "GET /netdata/ HTTP/1.1", upstream: "", host: ""




NGINX: rewrite non-www to www for multi domain virtual hosts

If you have NGINX virtual host that has a multi different domains pointing to same document root (multi server_name), and you want to automatically redirect non-www to www, than bellow is simple solution. I also wanted to redirect to https with www.

If you don’t need https redirection, than you can simply use variable¬†$scheme instead of “https:”.¬†

if ( $host !~ ^www\. ) {
            return 302 https://www.$host$request_uri;

So virtual host should look something like this:

server {

      if ( $host !~ ^www\. ) {
           return 302 https://www.$host$request_uri;
      return 302 https://$host$request_uri;

You should also make this redirect in your https server definition. otherwise request for won’t redirect to www.

server {
      if ( $host !~ ^www\. ) {
              return 302 https://www.$host$request_uri;

      ssl on;
      ssl_certificate /etc/letsencrypt/live/;
      ssl_certificate_key /etc/letsencrypt/live/;

      .... //other nginx configuration ....

Find common/identical lines within two files without DIFF

Here is really simple trick how to search for strings that are the same within two different files.

For presenting purposes I created two files with some text in it. Some text is the same, some not.

File 1:

> $ cat file1.txt 


> $ cat file2.txt 

Here is how to find strings that are the same within both files:

> $ cat file1.txt file2.txt | sort | uniq -c | grep "2 " 
2 test3
2 test4

So, strings test3 and test4 occurring in both files.

Nice way to do HTTP to HTTPS redirection with Apache .htaccess

I had some sites on shared hosting environment for which I had to do http to https redirection with .htaccess file. I did 302 redirection intentionally so that in case of error, browser doesn’t cache redirection. You can aslo make permanent 301 redirect if needed.

This is nice and simple way to do it:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302]

Moodle – mysql/mariadb Antelope to Barracuda installation warning

I tried to install Moodle 3.5.2 on cPanel server and got this warning in installation process:

“Your database has tables using Antelope as the file format. You are recommended to convert the tables to the Barracuda file format. See the documentation Administration via command line for details of a tool for converting InnoDB tables to Barracuda.”

Because this was production hosting server, I was unable to just globally change mysql settings. To be able to proceed installation, open config.php file of your moodle and change variable dbcollation like this:

dbcollation' => 'utf8_unicode_ci'

© 2019
Hosted by Hosterdam

About author