Hi,
I’m currently facing an annoying issue with HAproxy and my (Synology) WebDAV server, running behind a linux firewall (IPFire).
I’m using Keepass (latest version) on Win10 Pro. Keepass successfully loads a file from my internal WebDAV server w/o any issues, accessing the file with https://webdav.mydomain.de/webdav/pw.kdbx. This traffic is passing the firewall with a running HAProxy service just fine.
keepass -> www -> firewall with haproxy -> LAN -> WebDav (Port 5005)
However, when saving any modification in this password file to the WebDAV again, this results in a bad gateway 502 error.
I noticed that Keepass first successfully creates a temporary file and when trying to move this temp file to the original one, this finally results in the 502 error.
As you will probably notice above, I access the file in question with https and my WebDAV server is running on port 80. SSL termination is done by HAProxy using a LE cert.
At the time of this error, the haproxy log file reads, pls. see last line.
Jun 19 14:49:30 localhost haproxy[25037]: 123.456.78.90:54146 [19/Jun/2020:14:49:30.427] http_https~ webdav_server/webdav01 0/0/1/1/2 401 612 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "GET /webdav/pw.kdbx HTTP/1.1"
Jun 19 14:49:32 localhost haproxy[25037]: 123.456.78.90:54146 [19/Jun/2020:14:49:30.441] http_https~ webdav_server/webdav01 1/0/0/825/1883 200 3336890 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "GET /webdav/pw.kdbx HTTP/1.1"
Jun 19 14:49:39 localhost haproxy[25037]: 123.456.78.90:54146 [19/Jun/2020:14:49:38.485] http_https~ webdav_server/webdav01 0/0/1/628/1430 200 3336890 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "GET /webdav/pw.kdbx HTTP/1.1"
Jun 19 14:49:42 localhost haproxy[25037]: 123.456.78.90:54146 [19/Jun/2020:14:49:41.381] http_https~ webdav_server/webdav01 0/0/1/1365/1366 201 438 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "PUT /webdav/pw.kdbx.tmp HTTP/1.1"
Jun 19 14:49:43 localhost haproxy[25037]: 123.456.78.90:54146 [19/Jun/2020:14:49:42.757] http_https~ webdav_server/webdav01 0/0/1/669/686 200 290052 - - CDNI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "GET /webdav/pw.kdbx HTTP/1.1"
Jun 19 14:49:44 localhost haproxy[25037]: 123.456.78.90:54166 [19/Jun/2020:14:49:43.523] http_https~ webdav_server/webdav01 0/0/1/727/728 204 129 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "DELETE /webdav/pw.kdbx HTTP/1.1"
Jun 19 14:49:44 localhost haproxy[25037]: 123.456.78.90:54166 [19/Jun/2020:14:49:44.259] http_https~ webdav_server/webdav01 1/0/0/676/677 502 406 - - --NI 1/1/0/0/0 0/0 {webdav.mydomain.de|} "MOVE /webdav/pw.kdbx.tmp HTTP/1.1"
What’s interesting: when using the same https URL from within a Android tablet, using one of the abvailable file explorers that is capable of the WebDAV protocol, all is fine! Which means, I can download any file from the server, create, delete any files and folders w/o any issues.
IMO, the WebDAV server is not the cause if this problem. Maybe HAProxy or maybe Keepass at the end.
I’ve done a further test: I’ve created a port forwarding in the firewall to let Keepass reach the WebDAV server in LAN without passing HAProxy, using the URL http://123.456.78.90/webdav/pw.kdbx to access the file. Guess what? Keepass successfully saved the modified file without any error.
I found out alread when removing those lines from config file
http-request set-header X-Forwarded-Proto https
redirect scheme https code 301 if !{ ssl_fc }
Keepass works as expected. Of course I’m now using the http protocol instead of desired https.
Now I’m clueless! Any hints on how to get rid of this problem, is highly appreciated!
Below is my current haproxy.cfg
cu,
Michael
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
log 127.0.0.1 local1
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user nobody
group nobody
daemon
tune.ssl.default-dh-param 2048
#tune.maxrewrite 4096
#tune.http.maxhdr 202
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch except 172.0.0.0/8
retries 3
timeout http-request 30s
timeout queue 1m
timeout connect 30s
timeout client 1m
timeout server 1m
timeout http-keep-alive 30s
timeout check 30s
maxconn 3000
#---------------------------------------------------------------------
# Frontend Configuration
#---------------------------------------------------------------------
frontend http_https
bind 172.17.0.2:80
#Add available LE certs
bind 172.17.0.2:443 ssl crt /etc/haproxy/certs/webdav.mydomain.de.pem
mode http
#---------------------
#HAProxy handles SSL
#---------------------
#X-Forwarded-Proto for SSL offloading - needed for
http-request set-header X-Forwarded-Proto https
redirect scheme https code 301 if !{ ssl_fc }
#Logging
capture request header host len 40
capture request header cookie len 20
#Default log format, unchanged
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
http-response set-header Strict-Transport-Security max-age=31536000
# X-Content-Type-Options
http-response set-header X-Content-Type-Options nosniff
# X-Xss-Protection (for Chrome, Safari, IE)
http-response set-header X-Xss-Protection 1;\ mode=block
# X-Frame-Options (DENY or SELF)
http-response set-header X-Frame-Options DENY
# X-Robots-Tag to not index our site
http-response set-header X-Robots-Tag none
# Delete Server Header
http-response del-header Server
#Instruct clients to not sniff for Content-Type
http-response set-header X-Content-Type-Options: nosniff
#Leaving HTTPS to HTTP page permit sniffing to find out actual HTTPS URLs
http-response set-header Referrer-Policy no-referrer-when-downgrade
#---------------------------------------------------------------------
#Backend Configuration
#---------------------------------------------------------------------
acl is_webdav_domain hdr_beg(host) -i webdav.mydomain.de
#----WEBDAV----
acl is_webdav_path path -i /webdav/
http-request set-path /webdav%[path] if is_webdav_domain !is_webdav_path
use_backend webdav_server if is_webdav_domain
#default
default_backend no_match
#---------------------------------------------------------------------
# Backend WEBDAV
#---------------------------------------------------------------------
backend webdav_server
balance leastconn
cookie WEBDAVSERVER insert indirect nocache
http-check disable-on-404
http-check expect status 401
option httpchk GET /webdav
server webdav01 192.168.6.96:5005 cookie webdav01 inter 60s
#---------------------------------------------------------------------
# Backend: No Match
#---------------------------------------------------------------------
backend no_match
http-request deny deny_status 400