Unable to access my reverse proxied webdav after enabling basic_auth

1. The problem I’m having:

Hello Caddy community! (newcomer here)

I am currently trying to implement a webdav server reverse proxied by Caddy. The webdav server is basically a bunch of dufs processes serving files over unix sockets.
I can access the webdav without basic_auth, which is great!

But when I try to add in basic_auth, I always get “Could not connect” errors on my webdav clients (testing in MacOS Finder). I feel like I am using basic_auth as documented, so must be missing something obvious, but spent too much time trying to debug this.

Help? :face_holding_back_tears:

2. Error messages and/or full log output:

I ran the server, tried logging in and then stopped the server. Only 3 messages show up in log file.

2024/11/19 16:35:04.606	e[34mINFOe[0m	http.log.access.log0	handled request	{"request": {"remote_ip": "127.0.0.1", "remote_port": "65220", "client_ip": "127.0.0.1", "proto": "HTTP/1.1", "method": "OPTIONS", "host": "127.0.0.1:8443", "uri": "/webdav/path1/", "headers": {"Content-Length": ["0"], "Connection": ["close"], "User-Agent": ["WebDAVLib/1.3"], "Accept": ["*/*"]}, "tls": {"resumed": false, "version": 771, "cipher_suite": 49195, "proto": "", "server_name": "127.0.0.1"}}, "bytes_read": 0, "user_id": "", "duration": 0.00078775, "size": 0, "status": 401, "resp_headers": {"Www-Authenticate": ["Basic realm=\"restricted\""], "Server": ["Caddy"], "Alt-Svc": ["h3=\":8443\"; ma=2592000"]}}
2024/11/19 16:35:18.475	e[34mINFOe[0m	http.log.access.log0	handled request	{"request": {"remote_ip": "127.0.0.1", "remote_port": "65222", "client_ip": "127.0.0.1", "proto": "HTTP/1.1", "method": "OPTIONS", "host": "127.0.0.1:8443", "uri": "/webdav/path1/", "headers": {"Accept": ["*/*"], "Content-Length": ["0"], "Connection": ["close"], "User-Agent": ["WebDAVLib/1.3"]}, "tls": {"resumed": false, "version": 771, "cipher_suite": 49195, "proto": "", "server_name": "127.0.0.1"}}, "bytes_read": 0, "user_id": "", "duration": 0.000053459, "size": 0, "status": 401, "resp_headers": {"Server": ["Caddy"], "Alt-Svc": ["h3=\":8443\"; ma=2592000"], "Www-Authenticate": ["Basic realm=\"restricted\""]}}
2024/11/19 16:35:19.606	e[34mINFOe[0m	http.log.access.log0	handled request	{"request": {"remote_ip": "127.0.0.1", "remote_port": "65223", "client_ip": "127.0.0.1", "proto": "HTTP/1.1", "method": "OPTIONS", "host": "127.0.0.1:8443", "uri": "/webdav/path1/", "headers": {"User-Agent": ["WebDAVLib/1.3"], "Accept": ["*/*"], "Authorization": ["REDACTED"], "Content-Length": ["0"], "Connection": ["close"]}, "tls": {"resumed": false, "version": 771, "cipher_suite": 49195, "proto": "", "server_name": "127.0.0.1"}}, "bytes_read": 0, "user_id": "user1", "duration": 1.110079292, "size": 0, "status": 401, "resp_headers": {"Server": ["Caddy"], "Alt-Svc": ["h3=\":8443\"; ma=2592000"], "Allow": ["GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE,CHECKAUTH,LOGOUT"], "Dav": ["1, 2, 3"], "Www-Authenticate": ["Digest realm=\"DUFS\", nonce=\"673cbe47ade8053ed9f9016c001f4c526b\", qop=\"auth\"", "Basic realm=\"DUFS\""], "Content-Length": ["0"], "Date": ["Tue, 19 Nov 2024 16:35:19 GMT"]}}

I think from the stdout, these ones are about the failed authentication:

2024/11/19 16:35:17.514	DEBUG	http.stdlib	http: TLS handshake error from [fe80::1cfa:ba1:43b0:8bec%en0]:52283: tls: client offered only unsupported versions: [301]
2024/11/19 16:35:18.466	DEBUG	events	event	{"name": "tls_get_certificate", "id": "484ae097-77ef-4ad7-ae84-1f690162e23b", "origin": "tls", "data": {"client_hello":{"CipherSuites":[255,49196,49195,49188,49187,49162,49161,49160,49200,49199,49192,49191,49172,49171,49170,157,156,61,60,53,47,10],"ServerName":"127.0.0.1","SupportedCurves":[23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[1025,513,1281,1537,1027,515,1283,1539],"SupportedProtos":null,"SupportedVersions":[771,770,769],"RemoteAddr":{"IP":"127.0.0.1","Port":65222,"Zone":""},"LocalAddr":{"IP":"127.0.0.1","Port":8443,"Zone":""}}}}
2024/11/19 16:35:18.466	DEBUG	tls.handshake	choosing certificate	{"identifier": "127.0.0.1", "num_choices": 1}
2024/11/19 16:35:18.466	DEBUG	tls.handshake	default certificate selection results	{"identifier": "127.0.0.1", "subjects": ["127.0.0.1"], "managed": true, "issuer_key": "local", "hash": "5a7f0d7b69d42a5aa7fe64bfbcc664e19b071fac010bd1ab13ce2fa1e1eab533"}
2024/11/19 16:35:18.466	DEBUG	tls.handshake	matched certificate in cache	{"remote_ip": "127.0.0.1", "remote_port": "65222", "subjects": ["127.0.0.1"], "managed": true, "expiration": "2024/11/19 20:51:11.000", "hash": "5a7f0d7b69d42a5aa7fe64bfbcc664e19b071fac010bd1ab13ce2fa1e1eab533"}
2024/11/19 16:35:18.475	DEBUG	http.log.error.log0	not authenticated	{"request": {"remote_ip": "127.0.0.1", "remote_port": "65222", "client_ip": "127.0.0.1", "proto": "HTTP/1.1", "method": "OPTIONS", "host": "127.0.0.1:8443", "uri": "/webdav/path1/", "headers": {"User-Agent": ["WebDAVLib/1.3"], "Accept": ["*/*"], "Content-Length": ["0"], "Connection": ["close"]}, "tls": {"resumed": false, "version": 771, "cipher_suite": 49195, "proto": "", "server_name": "127.0.0.1"}}, "duration": 0.000053459, "status": 401, "err_id": "r3mi480bu", "err_trace": "caddyauth.Authentication.ServeHTTP (caddyauth.go:89)"}
2024/11/19 16:35:18.478	DEBUG	events	event	{"name": "tls_get_certificate", "id": "008a7a8d-4401-4fad-b1d5-abbd0a3b9543", "origin": "tls", "data": {"client_hello":{"CipherSuites":[255,49196,49195,49188,49187,49162,49161,49160,49200,49199,49192,49191,49172,49171,49170,157,156,61,60,53,47,10],"ServerName":"127.0.0.1","SupportedCurves":[23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[1025,513,1281,1537,1027,515,1283,1539],"SupportedProtos":null,"SupportedVersions":[771,770,769],"RemoteAddr":{"IP":"127.0.0.1","Port":65223,"Zone":""},"LocalAddr":{"IP":"127.0.0.1","Port":8443,"Zone":""}}}}
2024/11/19 16:35:18.478	DEBUG	tls.handshake	choosing certificate	{"identifier": "127.0.0.1", "num_choices": 1}
2024/11/19 16:35:18.478	DEBUG	tls.handshake	default certificate selection results	{"identifier": "127.0.0.1", "subjects": ["127.0.0.1"], "managed": true, "issuer_key": "local", "hash": "5a7f0d7b69d42a5aa7fe64bfbcc664e19b071fac010bd1ab13ce2fa1e1eab533"}
2024/11/19 16:35:18.478	DEBUG	tls.handshake	matched certificate in cache	{"remote_ip": "127.0.0.1", "remote_port": "65223", "subjects": ["127.0.0.1"], "managed": true, "expiration": "2024/11/19 20:51:11.000", "hash": "5a7f0d7b69d42a5aa7fe64bfbcc664e19b071fac010bd1ab13ce2fa1e1eab533"}
2024/11/19 16:35:18.572	DEBUG	http.stdlib	http: TLS handshake error from [fe80::1cfa:ba1:43b0:8bec%en0]:52285: tls: client offered only unsupported versions: [301]

3. Caddy version:

v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

4. How I installed and ran Caddy:

Installed using homebrew

a. System environment:

MacOS 15.1 (24B83)
(Not using Docker)

b. Command:

caddy run --config Caddyfile

c. Service/unit/compose file:

Not relevant

d. My complete Caddy config:

{
	debug
	http_port 8080
	https_port 8443
}

localhost, 127.0.0.1 {
	encode gzip

	# Reverse proxies to DUFS webdav (NOTE: removed user-pass info)
	basic_auth {
	    user1 $2a$......
	    user2 $2a$14$....
	}

	# This works with basic_auth, but reverse proxies dont
	#respond "Welcome, {http.auth.user.id}" 200

	# DAV path 1
	redir /webdav/path1 /webdav/path1/
	handle /webdav/path1/* {
		reverse_proxy unix//tmp/dufs-path1.sock
	}

	# Max file uploads/download size
	request_body {
		max_size 10GB
	}

	# Enable logging
	log {
		output file ./logs/caddy.log
		#format json
		format console
	}

	handle {
		# Fallback for any otherwise unhandled requests, maybe a 404 if you want
		respond "Nope!" 404
	}
}

5. Links to relevant resources:

DUFS (rust based file server): GitHub - sigoden/dufs: A file server that supports static serving, uploading, searching, accessing control, webdav...

6. Additional Info

Steps to recreate (macOS):

brew install dufs
cd /path/to/test/directory
# copy dufs-config.yml as written below
dufs -c dufs-config.yml &
# copy Caddyfile contents
caddy run -c Caddyfile
# In finder, open (cmd+k): https://127.0.0.1:8443/webdav/path1/
# Upon credential request, add user and password as configured
# At this stage, I hope you see the same error
# later you can comment/remove the basic_auth from Caddyfile to confirm if webdav is accessible like I can

dufs-config.yml

# Modify path before testing! (should have perms)
serve-path: '/path/to/share'
bind: '/tmp/dufs-path1.sock'
path-prefix: '/webdav/path1'
hidden:
  - '.DS_Store'
  - '.DS_Store?'
# User auth taken care by caddy
# just provide files with either rw/ro permissions
auth:
  - '@/:rw'
allow-all: false
allow-upload: true
allow-delete: true
allow-search: true
allow-symlink: false
allow-archive: false
enable-cors: false
render-index: false
render-try-index: false
render-spa: false
# DUFS logs become bloated and not useful
log-format: ''

My credentials are correct when entered, since removing the reverse proxies and just having a respond works (when opening in browser).

Howdy @R-Bose, welcome to the Caddy community.

I had a little play around with it using your steps to recreate. (Thanks for supplying that!)

TL;DR: It looks to be a quirk between Finder DAV client and DUFS. DUFS seems to want your Caddy basic auth user to exist because Finder supplies the same credentials as digest post-basic auth. Configuring both resolved the issue.

Here was the Caddyfile I tested with:

{
  debug
}

http:// {
  basic_auth {
    # foo bar
    foo $2a$14$Owz6ly4jYQ90aHAF3VL/ruHMic6nHtgwF.3gNU6oE00BhJW6e.NNC
  }

  redir /webdav/path1 /webdav/path1/
  handle /webdav/path1/* {
    reverse_proxy unix//tmp/dufs-path1.sock
  }
}

And instead of homebrew I ran dufs with: nix run nixpkgs#dufs -- -c dufs-config.yml

With basic_auth commented out, I found that I could connect from Finder as a guest, no problem. When I uncommented it, Finder indicated the credentials were rejected despite being correct.

The debug logs revealed something interesting:

2024/11/19 23:48:50.596	DEBUG	http.handlers.reverse_proxy	upstream roundtrip	{"upstream": "unix//tmp/dufs-path1.sock", "duration": 0.000594208, "request": {"remote_ip": "::1", "remote_port": "60695", "client_ip": "::1", "proto": "HTTP/1.1", "method": "OPTIONS", "host": "localhost", "uri": "/webdav/path1/", "headers": {"Content-Length": ["0"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost"], "X-Forwarded-For": ["::1"], "User-Agent": ["WebDAVLib/1.3"], "Accept": ["*/*"], "Authorization": ["REDACTED"]}}, "headers": {"Content-Length": ["0"], "Date": ["Tue, 19 Nov 2024 23:48:50 GMT"], "Allow": ["GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE"], "Dav": ["1, 2, 3, sabredav-partialupdate"], "Www-Authenticate": ["Digest realm=\"DUFS\", nonce=\"673d23e24d82aa0c3834a678923f99545e\", qop=\"auth\"", "Basic realm=\"DUFS\""]}, "status": 401}

Caddy didn’t issue the 401 - it was DUFS itself! When you supply credentials as prompted for basic auth, MacOS in fact supplies these credentials as digest as well for DUFS. Well - your dufs-config.yml doesn’t have a foo user so it 401’d it.

I changed '@/:rw' to 'foo:bar@/:rw' in the DUFS configuration and restarted it. Now Caddy prompts for basic auth, Finder supplies it, the digest auth goes to DUFS which authenticates a valid user, and I was able to access the DAV share.

2 Likes

@Whitestrake

Thank you for getting back to my issue with a swift debug!
I was out for work so couldn’t test your fix right away. This may work, however it raises the problem of writing the plaintext password in the dufs config which I am avoiding for when I need multiple users.

Is there any way to prevent passing on the auth information to dufs? I tried commenting the auth block of dufs yaml configs, but the server still rejects my password. :frowning:

You could probably set header_up -Www-Authenticate to prevent Caddy from sending that header upstream at all.

https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#header_up

Also I’m pretty sure DUFS lets you hash your passwords, too. It’s a different hash from the one Caddy uses, though, I think.

I ended up with dufs handling the authentication after figuring out how to use authentication for multiple paths. Thank you!

(I have another problem now but will open another thread for it).

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.