WebDav Server
Where previous guides rely on libapache2-mod-auth-mysql
, we'll use Apache's mod_authn_dbd
instead, which is included with Apache2.4 by default.
First we setup our environment:
apt-get install apache2 mysql-server mysql-client
a2enmod dav_fs
a2enmod dav
a2enmod dbd
mkdir -p /srv/webdav
chown -Rf www-data: /srv/webdav
Then we create a file to configure Apache:
«VirtualHost *:80»
ServerName webdav.perfacilis.example
RewriteEngine On
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
«/VirtualHost»
«VirtualHost *:443»
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/webdav.perfacilis.example/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/webdav.perfacilis.example/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/webdav.perfacilis.example/chain.pem
SSLProtocol -all +TLSv1.2
SSLHonorCipherOrder On
SSLCipherSuite "ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"
# HSTS
Header always set Strict-Transport-Security "max-age=15768000"
ServerName webdav.perfacilis.example
Options Indexes
DBDriver mysql
DBDParams "host=MYSQL_HOST dbname=MYSQL_DB_NAME user=MYSQL_USER pass=PASSWORD_NOT_IN_ROCKYOU_PLZ"
# 2 4 10 300
DBDMin 1
DBDKeep 1
DBDMax 2
DBDExptime 300
DavLockDB /tmp/davlock
DavDepthInfinity on
Alias /share1 /srv/webdav/share1
«Location /share1»
DAV on
AuthType Digest
AuthName "share1"
AuthDigestProvider dbd
Require valid-user
AuthDBDUserRealmQuery \
"SELECT passwd FROM mysql_auth WHERE username = %s AND share = %s"
«/Location»
«/VirtualHost»
Finally we enable our configuration. The example above uses certbot to create a certificate for apache.
certbot-auto certonly --agree-tos -m admin@mail.addr --rsa-key-size 4096 --renew-hook "apachectl graceful" \
--webroot --webroot-path /var/www/letsencrypt/ \
--cert-name webdav.perfacilis.example --domains webdav.perfacilis.example
a2ensite 400-webdav.conf
apachectl configtest && apachectl graceful
MySql configuration
The database will store the credentials, unique per user and per share combination.
Keep in mind he password has a special concatenated format: MD5(CONCAT( username, ':', realm, ':', plain_password ))
.
CREATE TABLE `mysql_auth` (
`username` char(50) NOT NULL,
`share` char(25) NOT NULL,
`passwd` char(32) NOT NULL,
PRIMARY KEY (`username`,`realm`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
# Repeat for every user and every share
INSERT INTO `mysql_auth`
SET `username` = 'user1',
`share` = 'share1',
`passwd` = MD5(CONCAT( 'user1', ':', 'share1', ':', 'not_in_rockyou' ));
WebDav Client
Prerequisites
sudo apt install davfs2
sudo mkdir "/media/$USER/share1"
sudo chown "$USER:" "/media/$USER/share1"
To test our setup, we can simply connect and mount to our created webdav share:
mount -t davfs https://webdav.perfacilis.example/share1 "/media/$USER/share1"
Alternatively, we can make it auto-mount on startup:
# Optional: Allow non-root user to mount
sudo usermod -a -G davfs2 "$USER"
# Setup secrets file, we use global file for extra security
echo "/media/$USER/share1 user1 \"not_in_rockyou\"" | sudo tee -a /etc/davfs2/secrets
echo "
https://webdav.perfacilis.example/share1 /media/$USER/share1 davfs user,noauto,uid=$USER,file_mode=600,dir_mode=700 0 1" | sudo tee -a /etc/fstab
Security
Below three simple ways how to avoid your password being brute forced or any tempering with your Webdav setup:
Brute-force protection using Fail2ban
[apache-auth]
enabled = true
logpath = /var/log/apache2/error.log
port = http,https
Firewall using iptables
iptables -A INPUT -m state --state NEW -p tcp -m multiport --dport 80,443 -s YOURIPADDRESS -j ACCEPT/code>
Only allow certain IPs using Apache
Require ip YOURIP
Require valid-user
Sources
- How To Set Up WebDAV With MySQL Authentication On Apache2 (Debian Etch)
- /etc/apache2/mods-available/dbd.load - Debian GNU/Linux 10 (buster)
- Apache Module mod_authn_dbd
Changes
- 2024-09-18
- Fix error on fail2ban's ban action: add
port = http,https
to config.