Here's a new article on Roundcube, this time I will deal with security. Here I'll show how to set up fail2ban to block brute-force attacks. In addition, we'll explore the integration of a 2FA (Two-Factor Authentication) plugin, created by alexandregz, to improve overall authentication security.
Although I've already covered the subject of enabling HTTPS in Roundcube here, I'll once again show you the steps you need to enable HTTPS for an extra layer of protection.
- Configuration:
- debian: 12 bookworm
- php: 8.2
- roundcube: 1.6.5
Enable fail2ban
Fail2ban is a powerful software designed to monitor authentication errors in log files and temporarily block remote addresses responsible for repeated failed attempts. It is a versatile tool applicable to various services such as sshd, apache, dovecot etc…
Install and Configure
- Install fail2ban:
root@host:~# apt update && apt install fail2ban
- Start and enable nftables service:
root@host:~# systemctl start nftables
root@host:~# systemctl enable nftables
- Edit the /etc/fail2ban/jail.conf file:
banaction = nftables-multiport
banaction_allports = nftables-allports
- Edit the /etc/fail2ban/jail.d/defaults-debian.conf file:
[sshd]
enabled = true
backend = systemd
[roundcube-auth]
enabled = true
logpath = /var/log/roundcube/errors.log
- Restart the fail2ban service to take the changes into account:
root@host:~# systemctl restart fail2ban
- Check the status of the roundcube-auth jail:
root@host:~# fail2ban-client status roundcube-auth
Status for the jail: roundcube-auth
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/roundcube/errors.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
Unblock an IP address
- List blocked ip addresses:
root@host:~# nft -a list ruleset
table inet filter { # handle 1
chain input { # handle 1
type filter hook input priority filter; policy accept;
}
chain forward { # handle 2
type filter hook forward priority filter; policy accept;
}
chain output { # handle 3
type filter hook output priority filter; policy accept;
}
}
table inet f2b-table { # handle 2
set addr-set-roundcube-auth { # handle 2
type ipv4_addr
elements = { 192.168.10.36 }
}
chain f2b-chain { # handle 1
type filter hook input priority filter - 1; policy accept;
tcp dport { 80, 443 } ip saddr @addr-set-roundcube-auth reject with icmp port-unreachable # handle 6
}
}
- If necessary, we can temporarily unblock ip addresses:
root@host:~# fail2ban-client set roundcube-auth unbanip 192.168.10.36
- Or we can permanently whitelist IP addresses by editing /etc/fail2ban/jail.conf:
ignoreip = 127.0.0.1/8 ::1 192.168.10.36
- Then restart the fail2ban service:
root@host:~# systemctl restart fail2ban
Add the twofactor_gauthenticator plugin
We should use an application compatible with Google Authenticator on a smartphone. I personnaly use the andOTP application which is not longer maintained: https://github.com/andOTP/andOTP but still works. And I haven't tested the FreeOTP application.
The official GitHub project can be found here: https://github.com/alexandregz/twofactor_gauthenticator
Enable the 2FA plugin
- Install git and download the plugin:
root@host:~# apt update && apt install git
root@host:~# git clone https://github.com/alexandregz/twofactor_gauthenticator.git
- Move the twofactor_gauthenticator folder to the Roundcube plugins directory:
root@host:~# mv twofactor_gauthenticator /var/lib/roundcube/plugins/
- Edit /etc/roundcube/config.inc.php to activate the plugin:
$config['plugins'] = [
'twofactor_gauthenticator',
];
- From the Roundcube web interface, go to Settings > 2-Factor Authentication:
- Check the Activate box and click on Fill all fields:
- A pop-up window appears, just click on OK:
- Write down the secret and recovery codes that will be useful if you lose your 2FA device, then scan the QR Code on your 2FA application with your smartphone:
- From your smartphone, retrieve the current one time password and type it into the text box, then click on Check code to confirm that everything is correct:
- Finally, click on Save:
- After the next connection, 2FA authentication should appear:
Reset 2FA authentication for a user
If you have lost your 2FA device, you will not be able to connect to Roundcube. To recover a user's 2FA recovery code, or to disable the 2FA application, we'll need to perform a few actions on the Roundcube server. This procedure is effective with a SQLite database.
- Connect to the SQLite database:
root@host:~# sqlite3 /var/lib/dbconfig-common/sqlite3/roundcube/roundcube
- Identify the user account to be reset and retrieve 2FA recovery codes :
SELECT * FROM users ;
1|john@std.rocks|std.rocks||2024-02-09 15:02:30|2024-02-24 12:31:00|2024-02-24 11:43:03|1|en_US|a:2:{s:11:"client_hash";s:16:"Tzl9oKiP5cifLfVO";s:24:"twofactor_gauthenticator";a:3:{s:6:"secret";s:16:"VTAPZI2PZVUIR45Q";s:8:"activate";b:1;s:14:"recovery_codes";a:4:{i:0;s:10:"B2FDEYC5J7";i:1;s:10:"A6TY7H5XD6";i:2;s:10:"CYYNSZ22UB";i:3;s:10:"SWISSDWBZ7N";}}}
- Or set preferences to null:
UPDATE users SET preferences = NULL WHERE user_id = 1;
Enable HTTPS
For security reasons, it's a good idea to enable HTTPS connections to Roundcube. This can be done using Let's Encrypt certificates or self-signed certificates. Let's see how to implement either solution.
- First, activate the Apache ssl module:
root@host:~# a2enmod ssl
Let's Encrypt
We can request a Let's Encrypt certificate, the advantage of which is that it will be recognized by web browsers and therefore won't display a warning when you connect.
- Install the certbot utility:
root@host:~# apt update && apt install certbot
- Stop the apache2 service:
root@host:~# systemctl stop apache2
- Run the certbot tool (ports 80 and 443 must be redirected to the Roundcube server, and the dns entry roundcube.std.rocks must point to the same server):
root@host:~# certbot certonly --email letsencrypt@std.rocks --standalone -d roundcube.std.rocks
- Modify the configuration file /etc/apache2/sites-available/default-ssl.conf and add:
SSLCertificateFile /etc/letsencrypt/roundcube.std.rocks/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/roundcube.std.rocks/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/roundcube.std.rocks/chain.pem
- Enable and restart the apache2 service:
root@host:~# a2ensite default-ssl
root@host:~# systemctl start apache2
Self-Signed Certificates
- Alternatively, you can create a self-signed certificate:
root@host:~# mkdir /etc/apache2/ssl/
root@host:~# openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/apache2/ssl/selfsigned.key -out /etc/apache2/ssl/selsigned.crt
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:STD
Locality Name (eg, city) []:stdcity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:std
Organizational Unit Name (eg, section) []:std
Common Name (e.g. server FQDN or YOUR name) []:roundcube.std.rocks
Email Address []:email@std.rocks
root@host:~# cat /etc/apache2/ssl/selfsigned.key /etc/apache2/ssl/selsigned.crt > /etc/apache2/ssl/cert.pem
- Edit the /etc/apache2/sites-available/default-ssl.conf configuration file:
DocumentRoot /var/lib/roundcube/public_html/
#AUTOGENERATE CERTIFICATES
SSLCertificateFile /etc/apache2/ssl/cert.pem
SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key
- Edit the /etc/apache2/ports.conf configuration file and disable http:
#Listen 80
- Enable and restart the apache2 service:
root@host:~# a2ensite default-ssl
root@host:~# systemctl restart apache2