Skip to main content
Version: v1.2.2

Wordpress Bouncer

CrowdSec

How does it work ?

This wordpress plugin allows you to apply decisions from crowdsec directly within the wordpress application.

It relies on the associated php library and provides the ability to not only block users, but challenge them with captchas.

Installation

The bouncer itself can be installed from the marketplace in wordpress back-office :

CrowdSec

Configuration

You only need to configure your local API endpoint and API key so the bouncer can get its decisions from crowdsec :

CrowdSec

A key point of the bouncer is to allow not only to block users, but as well to present them with captchas :

CrowdSec

Resources

Feel free to look at the associated article for more configuration options and tweaks.

WordPress Marketplace

You can find this plugin on the WordPress Plugins Marketplace.

Developer resources

Install with docker-compose

Install the wordpress and the plugin locally using docker-compose

Follow this guide to get the development stack installed locally.

Prerequises:

Install the stack for development purpose

Before all, create a .env file, using:

cp .env.example .env

Note about PHP 8.0: WordPress official docker image does not officially supports PHP 8.0 at this time. However, as the CrowdSec PHP Library does support PHP 8.0, there is a good chance that the plugin will work fine with PHP 8.0, but we can not currently test it.

Configure WordPress and the CrowdSec Plugin

Now there are two options, you can fill the Wordpress installation wizard manually OR use let the e2e tests to do it for you.

A) Automatic configuration

Install Wordpress instance and activate plugin launching the e2e tests (limited to the installation steps):

SETUP_ONLY=1 ./run-tests.sh
B) Manual comfiguration

Alternatively, you can install wordpress and the plugin manually with:

docker-compose up -d wordpress crowdsec mysql redis memcached

Then visit the wordpress instance here: http://localhost and install the wordpress instance.

Infos to setup the plugin
Get a bouncer key
docker-compose exec crowdsec cscli bouncers add wordpress-bouncer
LAPI URL
http://crowdsec:8080
Try the plugin behavior
InfoValue
Public blog URLhttp://localhost
Blog admin URLhttp://localhost/wp-admin
Admin usernameadmin
Paswordmy_very_very_secret_admin_password

Demo guide

Full guide

This guide exposes you the main features of the plugin.

Let's get started!

We will start using "live" mode. You'll understand what it is after try the stream mode.

docker-compose logs -f crowdsec
Discover the cache system
  • In a tab, visit the public home. You're allowed because LAPI said your IP is clean.

To avoid latencies when the clean IP browse the website, the bouncer will keep this information in cache for 30 seconds (you can change this value in the avdanced settings page). In other words, LAPI will not be requested to check this IP for the next 30 seconds.

  • You can call the website as many times as you want, the cache system will take relay during the ban period and so LAPI will not be disturbed. The ban decision will stay in cache for the full ban duration. Then the public home should be available again.

    Try ban remediation
  • If you want to skip this delay, feel free to clear the cache in the wp-admin.

The DOCKER_HOST_IP environnement variable is initialized via a call to:

source ./load-env-vars.sh
  • In a terminal, ban your own IP for 4 hours:

# Ban your own IP for 4 hours:
docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 4h --type ban
  • Immediately, the public home is now locked with a short message to explain you that you are banned.
Try "captcha" remediation
  • Now, request captcha for your own IP for 15m:

# Clear all existing decisions
docker-compose exec crowdsec cscli decisions delete --all

# Add a captcha
docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 15m --type captcha
  • The public home now request you to fill a captcha.

  • Unless you manage to solve the captcha, you'll not be able to access the website.

Note: when you resolve the captcha in your browser, the associated PHP session is considered as sure. If you remove the captcha decision with cscli, then you add a new captcha decision for your IP, you'll not be prompted for the current PHP session. To view the captcha page, You can force using a new PHP session opening the front page with incognito mode.

Stream mode, for the high traffic websites

With live mode, as you tried it just before, each time a user arrives to the website for the first time, a call is made to LAPI. If the traffic on your website is high, the bouncer will call LAPI very often.

To avoid this, LAPI offers a "stream" mode. The decisions list is updated at a predefined frequency and kept in cache. Let's try it!

This bouncer uses the WordPress cron system. For demo purposes, we encourage you to install the WP-Control plugin, a plugin to view and control each Wordpress Cron task jobs.

First, clear the previous decisions:

# Clear all existing decisions
docker-compose exec crowdsec cscli decisions delete --all
  • Then enable "stream" mode right here and set the resync frequency to 30 seconds. If you installed WP-Control plugin, you can see that a new cron tak has just been added here http://localhost/wp-admin/tools.php?page=crontrol_admin_manage_page.

  • As the whole blocklist has just been loaded in cache (0 decision!), your IP is allowed. The public home is available.

  • Now, if you ban your IP for 4h:

docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 4h --type ban
  • In less than 30 seconds your IP will be banned and the public home will be locked.

Conclusion: with the stream mode, LAPI decisions are fetched on a regular basis rather than being called when user arrives for the first time.

Try Redis or Memcached

In order to get better performances, you can switch the cache technology.

The docker-compose file started 2 unused containers, redis and memcached.

Let's try Redis!

  • Just go to the advanced settings page
  • select the Caching technology named "Redis" and
  • type redis://redis:6379 in the "Redis DSN" field.

Very similar with Memcached!

  • Just go to the advanced settings page
  • select the Caching technology named "Memcached" and
  • type memcached://memcached:11211 in the "Memcached DSN" field.

Statistics

The bouncer has a stats page indicating each time :

  • an IP has been banned by your website, or
  • when a captcha has been presented to an IP visiting your website
  • when a captcha has been solved or not.

How to contribute?

Contribute to this plugin

First, be sure to get the stack installed using the docker-compose guide.

Play with crowdsec state


#### Add captcha your own IP for 15m:
docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 15m --type captcha

#### Ban your own IP for 15 sec:
docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 15s --type ban

#### Remove all decisions:
docker-compose exec crowdsec cscli decisions delete --all

#### View CrowdSec logs:
docker-compose logs crowdsec

Note: The DOCKER_HOST_IP environnment variable is initialized via source ./load-env-vars.sh.

WP Scan pass

docker-compose run --rm wpscan --url http://wordpress5-6/
Reinstall composer dependencies
docker-compose exec wordpress5-6 composer install --working-dir /var/www/html/wp-content/plugins/cs-wordpress-bouncer --prefer-source

In this dev environment, we use --prefer-source to be able to develop the bouncer library at the same time. Composer may ask you for your own Github token to download sources instead of using dist packages.

Quick docker-compose cheet sheet
docker-compose run wordpress sh # run sh on wordpress container
docker-compose ps # list running containers
docker-compose stop # stop
docker-compose rm # destroy
Try the plugin with another PHP version
docker-compose down
docker images | grep wordpress-bouncer_wordpress # to get the container id
docker rmi <container-id>

Then, in the .env file, replace:

CS_WORDPRESS_BOUNCER_PHP_VERSION=7.2

with :

CS_WORDPRESS_BOUNCER_PHP_VERSION=<the-new-php-version>

Then re-run the stack.

Try the plugin with another WordPress version

The plugin is tested under each of these WordPress versions: 5.6, 5.5, 5.4, 5.3, 5.2, 5.1, 5.0, 4.9. (Representing more than 90% of the wordpress websites)

Add support for a new WordPress version

This is a cheat sheet to help testing briefly the support:


# To install a specific version
docker-compose up -d wordpress<X.X> crowdsec mysql redis memcached && docker-compose exec crowdsec cscli bouncers add wordpress-bouncer

# To display the captcha wall

docker-compose exec crowdsec cscli decisions add --ip ${DOCKER_HOST_IP} --duration 15m --type captcha

# To delete the image in order to rebuild it

docker-compose down && docker rmi wordpress-bouncer_wordpress<X.X>

# To debug inside the container

docker-compose run wordpress<X.X> bash

Note: The DOCKER_HOST_IP environnement variable is initialized via source ./load-env-vars.sh.

Plugin debug mode VS production mode

The debug mode throws verbose errors. The production mode hides every error to let users navigate in every edge cases.

This plugin goes in debug mode when Wordpress debug mode is enabled.

To try the production mode of this plugin, just disable the wordpress debug mode: in docker-compose.yml, comment the line:

    WORDPRESS_DEBUG: 1 # Comment this line the simulate the production mode
Display the plugin logs
tail -f logs/debug-*

FAQ

How to use system CRON instead of wp-cron?

Add define('DISABLE_WP_CRON', true); in wp-config.php then enter this command line on the wordpress host command line:

(crontab -l && echo "* * * * * wget -q -O - htt://<host>:<port>/wp-cron.php?doing_wp_cron >/dev/null 2>&1") | crontab -

Note: replace [host]:[port] with the local url of your website

More info here.

Contribute to this plugin from a MacOS host

You can test the Linux behavior of this project using Vagrant.

One time setup

Run the VM and initialize it
vagrant up
vagrant ssh
sudo usermod -aG docker vagrant
sudo systemctl restart docker

You have to log out and log back for permission to be updated:

exit
vagrant ssh
Enabled Docker IPV6 support inside the Linux VM

follow this guide. (Note that you'll have to create the file /etc/docker/daemon.json).

Install NodeJS

Follow this guide/

Install Yarn

Follow this guide.

Add deps to run playwright
sudo apt-get install libnss3\
libnspr4\
libatk1.0-0\
libatk-bridge2.0-0\
libxcb1\
libxkbcommon0\
libx11-6\
libxcomposite1\
libxdamage1\
libxext6\
libxfixes3\
libxrandr2\
libgbm1\
libgtk-3-0\
libpango-1.0-0\
libcairo2\
libgdk-pixbuf2.0-0\
libasound2\
libatspi2.0-0
Edit you local host file:

Type sudo vim /etc/hosts and add:

# select the one you want to try by uncommenting only ont of the two
# 172.16.0.50 wordpress5-6 # Uncomment to use IPV4
fde4:8dba:82e1::c4 wordpress5-6 # Uncomment to use IPV6
Configure your .env file
cd /vagrant
cp .env.example .env

Update the created .env file with:

DEBUG=0
DOCKER_HOST_IP=172.16.238.1 # OR IF YOU WANT TO TEST WITH IPV6 USE: 2001:3200:3200::1
Run "plugin auto setup" via e2e tests (limited to setup steps)
SETUP_ONLY=1 ./run-tests.sh
Browse the WordPress website admin

Visit http://wordpress5-6/wp-admin.

Run tests
SETUP_ONLY=1 ./run-tests.sh
Stop the Virtal Machine
vagrant stop # vagrant up to start after
Clean up environnement

To destroy the vagrant instance:

vagrant destroy

Licence

MIT License