Preface
Cloudways is a managed cloud hosting platform that makes it easy to host websites and applications across different cloud providers.
It gives you SSH access, but with limited permissions.
However, you can still run the Security Engine on Cloudways to enable behavior detection for your services (Nginx and Apache) and use our WordPress plugin to apply remediation, including the blocklist feature. This guide is more detailed than others because it covers the specific steps required for integrating CrowdSec with Cloudways.
We'll walk you through the following steps:
- Install CrowdSec using the static build
- Set up acquisition and detection collections
- Run behavior detection on your past logs to see what would have been flagged
- Make CrowdSec run as a user-level service
- Connect it to the WordPress plugin to block detected attackers
Install CrowdSec from the static build
In this section, we'll get the latest static build of CrowdSec, build the folder hierarchy with the slightly tweaked test_env script and create the necessary config for the Local API and Central API.
Setup CrowdSec static build
For this setup we'll put CrowdSec in the /home/master/crowdsec folder.
Get the static build
- Go to the latest release page
- Scroll down past the changelog, in the Assets section copy the link to the crowdsec-release.tgz file
- ensure you are within the
/home/master
folder
cd /home/master
- download it in your /home/master folder, example:
wget https://github.com/crowdsecurity/crowdsec/releases/download/v1.6.3/crowdsec-release.tgz
- Extract the archive:
tar -xvzf crowdsec-release.tgz
- Rename the extracted folder to crowdsec:
mv crowdsec-v1.6.3 crowdsec
Create the folder hierarchy
- cd into the crowdsec folder:
cd crowdsec
- Tweak the test_env script to create the necessary folders and config:
sed -i 's|BASE="./tests"|BASE="/home/master/crowdsec"|' test_env.sh
- Run the script:
./test_env.sh
- Check one config file symlink to make sure the tweak worked:
ls -la config/parsers/s00-raw/syslog-logs.yaml
Should output config/parsers/s00-raw/syslog-logs.yaml -> /home/master/crowdsec/config/hub/parsers/s00-raw/crowdsecurity/syslog-logs.yaml
Create the config
We'll take the template config, update a few ports to avoid conflicts and setup the Local API and Central API.
- We'll use the dev.yml template to create our config.yaml:
mv dev.yml config.yaml
Update the configuration
/home/master/crowdsec/config.yaml
We need to make alterations to the config file for this static install and to avoid conflicts and setup the Local API.
- First, replace all* ./ with /home/master/crowdsec/ *in the config.yaml file
sed -i 's|./|/home/master/crowdsec/|g' config.yaml
Open the /home/master/crowdsec/config.yaml
with your favourite terminal editor and make the following changes:
- Update log_media and add log dir
common:
log_media: file ## Alter this line from stdout to file
log_dir: ./logs ## Add this line, ensure it indented correctly
- Then uncomment and replace the hubdir with the correct path:
[...]
hub_dir: /home/master/crowdsec/config/hub
- Finally, change the local API port to 19443 in order to avoid conflicts
[...]
api:
server:
listen_uri: 127.0.0.1:19443
Create some quality of life aliases
In order to make the command line easier to use, we'll create some aliases for the CrowdSec CLI and crowdsec itself. This way you won't have to call it from the full path with the config param each time.
- Add the following to your* /home/master/.bash_aliases* file:
alias cscli="/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml"
alias crowdsec="/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml"
- Reload your bash profile:
source /home/master/.bashrc
Init CAPI (Central API) credentials
We can initilized the CAPI credentials with the following command:
cscli capi register
This will generate /home/master/crowdsec/config/online_api_credentials.yaml
make sure to keep this file safe.
The output will instruct you to restart the service, but we'll do that later.
Reset LAPI (Local API) credentials
- Remove the existing machine and create a new one in auto:
cscli machines list //ignore the warning it's normal for now
- You should see something like this
────────────────────────────────────────────────────────────────────────────────────────
Name IP Address Last Update Status Version OS Auth Type Last Heartbeat
────────────────────────────────────────────────────────────────────────────────────────
test 2024-09-12T10:04:52Z ✔️ ? password ⚠️ -
────────────────────────────────────────────────────────────────────────────────────────
- Delete the test machine
cscli machines delete test_env
- Create a new default one with --force to override the existing credentials file
cscli machines add my_logprocessor --auto --force
- C that the credential file has the proper port : cat ./config/local_api_credentials.yaml
url: http://127.0.0.1
login: my_logprocessor
password: 321QSd54QERG321sq54AZEqs45AZDQSd654z65fps
Setup acquisitions and detection collections
Acquisition configuration indicates to CrowdSec what log files it should look at.
The Detection collections include parsers config and bad behavior detection scenarios for given services.
In our case we'll look at the nginx logs and apache2 logs.
- We'll use wildcards to work with any application name of your application folder: ls /home/master/applications
- Replace the content of the config/acquis.yaml file (with you editor of choice) with the following:
filenames:
- /home/master/applications/**/logs/nginx_*.log
labels:
type: nginx
---
filenames:
- /home/master/applications/**/logs/apache_*.log
labels:
type: apache2
Getting collections
Now we'll install the collections for nginx and apache2.
You can find our catalog on our Hub.
- Run the following command to install the collections:
cscli collections install crowdsecurity/nginx crowdsecurity/apache2
Making the collections auto update
CrowdSec collection often get updated with the behavior detections.
CrowdSec teams create and currate community scenarios allowing its users to benefit from the latest vulnerabilities detection.
We'll allow hub auto-update with a cron:
- Create a hub_update.sh file in the crowdsec folder:
#!/bin/sh
test -x /home/master/crowdsec/cscli || exit 0
# splay hub upgrade and crowdsec reload
sleep "$(seq 1 300 | shuf -n 1)"
/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml --error hub update
upgraded=$(/home/master/crowdsec/cscli -c /home/master/crowdsec/config.yaml --error hub upgrade)
if [ -n "$upgraded" ]; then
systemctl --user reload crowdsec
fi
exit 0
- Add it to crontab, every day at 6 for example
0 6 * * * /home/master/crowdsec/hub_update.sh
Make sure log rotation not breaking acquisition
As CrowdSec is not running as root in our current context, there could be some race conditions with log rotation file creation making the acquisition fail. Future versions of CrowdSec might address this issue, but for now, we can use a simple script to ensure the acquisition is not broken.
- Create a script to ensure the acquisition is not broken
vi /home/master/crowdsec/check_rotation.sh
#!/bin/bash
# Set the path to your CrowdSec log file
LOG_FILE="/home/master/crowdsec/logs/crowdsec.log"
# Get today's date in the format used in the logs (UTC time)
TODAY=$(date -u +"%Y-%m-%d")
# Define the error pattern to search for
ERROR_PATTERN='level=warning .* died : Unable to open file .*: permission denied'
# Search for the error in today's logs
if grep "$TODAY" "$LOG_FILE" | grep -qE "$ERROR_PATTERN"; then
# Log the action
echo "$(date): Error found, restarting CrowdSec service" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log
# Restart the CrowdSec service
systemctl restart --user crowdsec
# Log the completion
echo "$(date): CrowdSec service restarted successfully" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log
else
# Log that no action was taken
echo "$(date): No error found, no action taken" >> /home/master/crowdsec/logs/crowdsec_rotation_fail.log
fi
Make the check run every day at 00:01
1 0 * * * /home/master/crowdsec/check_rotation.sh
Run a behavior detection on your past logs to see what it would have found
We can run the behavior detection on the past logs to catch alerts that happened in the past.
We'll run it on the nginx access logs and the first archive of nginx access logs (previous day)
- Run the behavior detection on the past logs:
./crowdsec -c config.yaml -dsn file:///home/master/applications/\*\*/logs/nginx_*.access.log --type nginx --no-api
- Note that dsn parameter take the file://*/ protocol and an absolute path
- After you ran the detection, detected alerts should be listed in:
cscli alerts list
Make CrowdSec service run at user level
We want CrowdSec to run in the background and start at boot.
For this we'll add a systemd service in the user level.
Create the systemd service for user
- At the time of writting (for v1.6.3) you can use the following content:
- Create and edit ~/.config/systemd/user/crowdsec.service
[Unit]
Description=Crowdsec agent
[Service]
WorkingDirectory=/home/master/crowdsec
Type=notify
Environment=LC_ALL=C LANG=C
ExecStartPre=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml -t -error
ExecStart=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml
#ExecStartPost=/bin/sleep 0.1
ExecReload=/home/master/crowdsec/crowdsec -c /home/master/crowdsec/config.yaml -t -error
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
- Note that if you want to do it yourself the process is:
- Get the service description file from https://github.com/crowdsecurity/crowdsec/blob/master/config/crowdsec.service
- Move it to the user systemd user folder
- Modify this file to have the proper path to crowdsec executable and config
Enable the service to run at boot
For a user level process to keep running after you close the connection we need to activate the "linger"
- Run the following command:
loginctl enable-linger
- Then have systemctl reload and run crowdsec
systemctl --user daemon-reload
systemctl --user enable --now crowdsec
- Check the status of the service
systemctl --user status crowdsec
- In the future you can systemctl --user start crowdsec or stop or restart
Checking that CrowdSec works
We ran a behavior detection on the past logs so we might already have acquisition and parsing metrics. But to check that its working, you can visit your website
- It should generate lines of logs
- As soon as new log lines arrive in any of those:
- You should see the acquisition metrics appear/update
- And the resulting parser acquisition and metrics
cscli metrics -c config.yaml
- looking something like
Acquisition Metrics:
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────╮
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/home/master/applications/abcdefghij/logs/apache_wordpress-1211499-4678369.cloudwaysapps.com.access.log │ 1 │ 1 │ - │ - │ - │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
[...]
Parser Metrics:
╭──────────────────────────────────┬──────┬────────┬──────────╮
│ Parsers │ Hits │ Parsed │ Unparsed │
├──────────────────────────────────┼──────┼────────┼──────────┤
│ child-crowdsecurity/apache2-logs │ 1 │ 1 │ - │
│ child-crowdsecurity/http-logs │ 3 │ 3 │ - │
│ crowdsecurity/apache2-logs │ 1 │ 1 │ - │
│ crowdsecurity/dateparse-enrich │ 1 │ 1 │ - │
│ crowdsecurity/geoip-enrich │ 1 │ 1 │ - │
│ crowdsecurity/http-logs │ 1 │ 1 │ - │
│ crowdsecurity/non-syslog │ 1 │ 1 │ - │
╰──────────────────────────────────┴──────┴────────┴──────────╯
Bind it to the WP plugin to block the detected attackers
Now that we have CrowdSec running and detecting bad behaviors.
Alerts are raised and decisions to block bad actors are stored in the local DB.
To actually apply a remediation and ban the attackers from your website you need:
- To create a bouncer API key:
cscli bouncers add my_wp_bouncer
- You should see something like this:
API key for 'my_wp_bouncer':
OI8BQQqMcasoeuxK2g5lMSHPLVkH1tARqLIW0HS3cIY
Please keep this key since you will not be able to retrieve it!
- Add those credentials to your WP bouncer plugin as described in the WP plugin documentation