Wordpress Bouncer
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 :
Configuration
You only need to configure your local API endpoint and API key so the bouncer can get its decisions from crowdsec :
A key point of the bouncer is to allow not only to block users, but as well to present them with captchas :
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:
- you should have
docker
installeddocker
should berunnable without sudo
.docker-compose
installed locally.- IPv6 should be enable in your docker configuration. Enabled it following this guide. (Note that you'll may have to create the file
/etc/docker/daemon.json
).- If your develop environnment is MacOS, please refer to the MacOS host installation guide.
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
Info | Value |
---|---|
Public blog URL | http://localhost |
Blog admin URL | http://localhost/wp-admin |
Admin username | admin |
Pasword | my_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.
First, be sure to get the stack installed using the docker-compose guide.
open a terminal to display LAPI logs in realtime:
docker-compose logs -f crowdsec
- In wp-admin, ensure the bouncer is configured with live mode (stream mode disabled).
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 viasource ./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 viasource ./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