[Solved] Problem Reverse Proxy Caddy and Login Synology DSM with Yubikey

Started by Ronny1978, April 08, 2026, 06:13:29 AM

Previous topic - Next topic
Hello Together.

I have a question I can't seem to figure out. First of all, the background:

- OpnSense 26.1.5
- Lets Encrypt Cert with API of Netcup (*.mydomain.de) with ACME Client
- Caddy Plugin 2.1.0
- Synology DSM 7.2.2 Update 8
- Yubikey as Hardware-Security-Key
- usage until yet -> HAProxy -> Login in DSM works with Yubikey internal and external
- Rewrites of my Servers/Application in Unbound to IP of the Firewall (192.168.100.1)

I wanted to switch my reverse proxy from HAProxy to Caddy over the weekend. It worked fine at first. Then yesterday I noticed that logging in to Synology DSM (username/password/Yubikey as a security key) no longer works. The login is 'interrupted' – but not completely. This means that DSM registers it as an incorrect login. After three attempts, I locked myself out. I was then able to unlock it using a VPN and the OTP code (via the Yubikey). I then removed the Yubikey from the settings and tried to re-pair it -> error message: 'Registration could not be completed. Please try again'.

After an hour, searching on Google and here in the forum hadn't got me anywhere, and even the AI couldn't help. The theory is that Caddy does something with the headers that HAProxy doesn't. I switched back to HAProxy, and immediately the Yubikey registered as a security key again, and I was able to log in using the Yubikey once more.

My reason for switching to Caddy was that I'd like to use Authelia or Authentik in the future. Yes, that's also possible via Lua scripts in HAProxy, but unfortunately I don't understand the technical details well enough to really grasp what I'm doing there.

I'm hoping that someone here in the forum can help me out, as I know there are plenty of members here with loads of technical experience and knowledge.

Thanks in advance for your help. 😉

You're forgetting a key principle here - KISS

If you have a vpn there's no need to expose anything synology to the internet nor do you need 2FA.

Making sure that the management port is in a trusted vlan is all you need. Everything else way overkill.

Thank for your reply and your hint. Unfortunately it doesn't help to solve the problem and understanding caddy. 😉 I have same family members, which also use my Synology and it is to difficult to solve problems (VPN) remote and for these members it is easier to realize the access over a reverse proxy with a Yubikey. Many thanks again.

Ronny

You still have time to reconsider.

With a vpn, WireGuard or OpenVPN you'd only allow specific users to access the resource. Otherwise the whole of the internet can hammer the nas at will.

Assuming you'd go for WireGuard, you'd create everything that's needed and only send the third party a QR code.

Should there be a breakage of the vpn, the nas data is still accessible without issues.

_IF_ you can have ddns running on the clients to connect then you can simply lock down the wan access to the reverse proxy by creating a rule with source alias < ddns clients >, and then get rid of the token altogether.

Anyway, food for thought. The goal is simpler and more secure, one way or another.



Should there be a faulty nas update that breaks 2FA - you're in a heap of trouble.

Quote from: Ronny1978 on April 08, 2026, 06:13:29 AMI wanted to switch my reverse proxy from HAProxy to Caddy over the weekend. It worked fine at first. Then yesterday I noticed that logging in to Synology DSM (username/password/Yubikey as a security key) no longer works. The login is 'interrupted' – but not completely. This means that DSM registers it as an incorrect login.
Did you enable the X-Forwarded-For header in the advanced settings?

Do you proxying the whole domain or a virtual directory?

Is Caddy using the same protocol (http / https) as HAproxy to access the backend?

Hello @virgomann.

Thanks for your post and try to helping me.

QuoteDid you enable the X-Forwarded-For header in the advanced settings?
-> yes, see me screenshot Caddy.jpg



QuoteDo you proxying the whole domain or a virtual directory?
-> Domain

QuoteIs Caddy using the same protocol (http / https) as HAproxy to access the backend?
-> see my pictures HAProxy.jpg, Caddy2.jpg and Caddy3.jpg

Thanks a lot.

Ronny

With the help of a member from another forum, we found the solution:

Additional header configuration:

header_up Host {host}
That solves the problem.

Thanks JohneDoe 😉👍

Quote from: Ronny1978 on April 11, 2026, 07:31:54 AMheader_up Host {host}
Strange. This header already exists in the clients request and Caddy shouldn't remove it by default.

And also HAproxy doen't add it without specific settings.

Quote from: viragomann on April 11, 2026, 09:53:59 AM
Quote from: Ronny1978 on April 11, 2026, 07:31:54 AMheader_up Host {host}
Strange. This header already exists in the clients request and Caddy shouldn't remove it by default.

Caddy recently changed how they treat that header when the backend/upstream connection is via HTTPS. See:

https://forum.opnsense.org/index.php?topic=51150.0
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

I see. Thank you.

I don't run HTTPS backends behind Caddy to be honest. But I do behind HAproxy.

However, I'm wondering, what's the particular meaning of removing the host header or overriding it with something else.
The host header is mostly used differentiator to select the proper virtual server, when running multiple websites on a single backend. The client is sending the proper header value. So why does Caddy change it?

HAproxy doesn't behave like that.

Probably because it expects to handle TLS termination and distribution of sites to different backend by itself, anyway.
However, even if it does that, a reverse proxy should aim for maximum transparency, also with the client info that is passed on.

I like HAproxy better as well. It has some distinguishing features that set it apart and with @TheHellSites tutorial, it works just great for me.

Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

If the backend is HTTPS the host header is now forced to the configured backend URL. I find this quite reasonable - the backend might even rely on SNI ...
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

Hello Together.

Unfortunately, I didn't receive an email notification that the discussion had continued here. My apologies for that. Unfortunately, my knowledge of reverse proxies, headers and configurations isn't quite up to scratch yet. I'd like to use Authelia or Authentik, but I'm simply struggling to find a guide for HAProxy that I can actually understand.

However, it seems that Caddy does support implementation for these apps. That is why I decided to go with it.

And once again regarding the use of HTTPS behind a reverse proxy: I still don't understand why I should only use HTTP here. It makes no sense to me to downgrade Synology's DSM, Proxmox and the Unifi Controller to HTTP, if that is even possible. I also had the problem at Synology DSM with Yubikey as a hardware token - not if I had used Yubikey as OTP generator.

If you have further information, please let me know. I'm very interested in that.

P.S.
@viragomann: Do you use 2 Reverse Proxys? Caddy AND HAProxy?

You can use HTTPS for the backend, but if you do you must pass the host header from Caddy to the backend, too. I showed how to do that here:

https://forum.opnsense.org/index.php?topic=51150.msg261846#msg261846
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

Thanks @Patrick. I have seen in the protocoll of caddy another error. I'm not sure, what the error message means.

"warn","ts":"2026-04-16T15:06:23Z","logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"10.0.80.9:8096","duration":0.043666007,"request":{"remote_ip":"xxx.xxx.xx.xx","remote_port":"64698","client_ip":"xxx.xxx.xx.xx","proto":"HTTP/2.0","method":"GET","host":"jellyfin-nas01.xxxxxx","uri":"/Videos/d98dd6bf-5112-6253-69c2-3e678e867234/stream?container=mkv&static=true&tag=0fee8bb2a7d611d87a8b8fd6a2daf47f&mediaSourceId=d98dd6bf5112625369c23e678e867234&streamOptions=%7B%7D&enableAudioVbrEncoding=true","headers":{"X-Forwarded-For":["xxx.xxx.xx.xx"],"X-Forwarded-Proto":["https"],"Accept-Encoding":["identity"],"User-Agent":["okhttp/4.12.0"],"Icy-Metadata":["1"],"X-Forwarded-Host":["jellyfin-nas01.xxxxxx"],"Via":["2.0 Caddy"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"jellyfin-nas01.xxxxxx","ech":false}},"error":"writing: http2: stream closed"}

How can I correct my configuration?

Thanks a lot again. Have a great rest of the week.

Ronny