Linux WebDav Server using Apache and MySql

  •  
  •  

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:

/etc/apache2/sites-available/400-webdav.conf
«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

/etc/fail2ban/jail.local
[apache-auth]
enabled = true
logpath = /var/log/apache2/error.log

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

/etc/apache2/sites-available/400-webdav.conf
Require ip YOURIP
Require valid-user

Sources