Ilija Matoski

    ← Articles

    fail2ban for Wordpress and Plesk

    I’m hosting quite a bit of pages that run WordPress, and one of the biggest problem that I ran into is that people don’t keep their WordPress or plugin installations updated.

    I gave up on having everyone upgrade, because they all use different plugins, customized plugins, and a lot of other stuff that will break if they upgrade.

    So here comes fail2ban to the rescue, we can use it to go through the logs, to configure the system to ban the users when they fail to log in, or do some bad stuff, or try to brute force their way into the wordpress installation, either through the login form or through xmlrpc.

    You should install fail2ban if you haven’t already, on debian based you would just issue.

    apt-get install fail2ban

    If you use Plesk you can skip creation of the files, and just use the frontend to create the necessary jails and filters, also replace common.conf with apache-common.conf.

    The configuration is located in /etc/fail2ban on most systems.

    So firstly let’s create a filter.

    In /etc/fail2ban/filter.d, create a file called wordpress-login.conf, and put the following text inside.

    # Fail2Ban filter for WordPress Login
    #
    [INCLUDES]
    before = common.conf
    [Definition]
    _daemon = wordpress
    failregex = ^<HOST>.*].*POST.*/wp-login\.php HTTP.*
    ignoreregex =
    # DEV Notes:
    #
    # Rule Author: Ilija Matoski

    What this does it creates a filter to be used in the next step. Also let’s create one filter for XMLRPC for WordPress in the same directory named wordpress-xmlrpc.conf

    # Fail2Ban filter for WordPress XMLRPC
    #
    [INCLUDES]
    before = common.conf
    [Definition]
    _daemon = wordpress
    failregex = ^<HOST>.*].*/xmlrpc\.php.*
    ignoreregex =
    # DEV Notes:
    #
    # Rule Author: Ilija Matoski

    Now let’s create two new jails, that we gonna use to ban the people who are gonna abuse this.

    In the folder /etc/fail2ban/jail.d, wordpress.conf,

    [wordpress-xmlrpc]
    enabled = true
    filter = wordpress-xmlrpc
    action = iptables-multiport[name=WordPressXMLRPC, port="http,https"]
    logpath = /var/log/apache2/access_log
    maxretry = 10
    [wordpress-login]
    enabled = true
    filter = wordpress-login
    action = iptables-multiport[name=WordPressLogin, port="http,https"]
    logpath = /var/log/apache2/access_log
    maxretry = 10

    If you are running Plesk, then replace the logpath with

    logpath = /var/www/vhosts/system/*/logs/*access*log
    /var/log/apache2/*access.log

    So in Plesk, the action will look like.

    iptables-multiport[name="<NAME_OF_FILTER>", port="http,https"]

    This will read the data from all the hosts in Plesk

    So what happens if someone tries to POST to wp-login.php, or hit xmlrpc.php, 10 times in a 10 minute period he will be banned for a day, also there is a jail called recidive in fail2ban, which if you get jailed 5 times with the previous filters, the IP will get ban for a week.

    You can adjust the times in the configuration file, if you want to lower or increase them.

    Well this should work, now let it run for a while, and you can see what does your, after 15 minutes of running this is what was present in my logs.

    $ iptables -L fail2ban-WordPressLogin
    Chain fail2ban-WordPressLogin (1 references)
    target prot opt source destination
    REJECT all -- 189.1.169.141 anywhere reject-with icmp-port-unreachable
    REJECT all -- 181.140.198.180 anywhere reject-with icmp-port-unreachable
    REJECT all -- 117.21.191.227 anywhere reject-with icmp-port-unreachable
    RETURN all -- anywhere anywhere
    $ iptables -L fail2ban-WordPressXMLRPC
    Chain fail2ban-WordPressXMLRPC (1 references)
    target prot opt source destination
    REJECT all -- 117.21.191.227 anywhere reject-with icmp-port-unreachable
    RETURN all -- anywhere anywhere