tobychui / zoraxy

A general purpose HTTP reverse proxy and forwarding tool. Now written in Go!
https://zoraxy.aroz.org
GNU Affero General Public License v3.0
3.11k stars 188 forks source link

[HELP] Bitwarden/Vaultwarden websockets, how? #407

Open RainmakerRaw opened 1 day ago

RainmakerRaw commented 1 day ago

What happened? A clear and concise description of what the problem is. Ex. I tried to create a proxy rule but it doesn't work. When I connects to my domain, I see [...]

I have moved to Zoraxy from Caddy, as I love the blacklist and stats dashboard. So far, so good! However, one bugbear remains. I can't seem to get 'live sync' (websockets) working between clients in my self-hosted Vaultwarden. It works fine under Caddy - not especially helpful, I know, but my point is the feature is otherwise available and working outside of Zoraxy config.

The Vaultwarden wiki says that one needs to map two variables to get it working. They give some example proxy configs, including Nginx:

# Needed to support websocket connections
# See: https://nginx.org/en/docs/http/websocket.html
# Instead of "close" as stated in the above link we send an empty value.
# Else all keepalive connections will not work.
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      "";
}

Their Websockets page further states that a reverse proxy must pass on the Upgrade and Connection headers.

When using Caddy (or NPM) I can make an entry in the Bitwarden app/extension on any client and immediately see it appear in all other desktop and mobile client apps/extensions. Under Zoraxy, I have to manually sync the vault on the device creating an entry to 'commit' the change to the server, and then sync the other client devices to pull the new entry. It would be preferable to enable websocket support for the 'live sync' feature to work between clients again .

Describe what have you tried A clear and concise description of what you expect to see and what you have tried to debug it.

I have entered a proxy entry in the Zoraxy webUI, for the relevant Proxmox LXC container running Vaultwarden. All my local devices and servers have a static RFC1918 IPv4 address, and a 'static' DHCPv6 global scope ('public') address. When making the Zoraxy proxy entry for Vaultwarden, I left the default config for websockets and did not enable any further TLS config outside of the pre-existing Acme wildcard certificate. I have, however, also set a custom header for X-Frame-Options = SAMEHEADER as required by Vaultwarden to enable MFA.

Screenshot 2024-12-02 at 19 38 13

Describe the networking setup you are using Here are some example, commonly asked questions from our maintainers:

Additional context Add any other context or screenshots about the feature request here.

tobychui commented 21 hours ago

Hi @RainmakerRaw ,

Usually in cases like these I would recommend keeping the Caddy setup, as Zoraxy are primary for beginners with much less options available for tinkering.

Zoraxy handle websocket connection with the following logic.

/* WebSocket automatic proxy */
    requestURL := r.URL.String()
    if r.Header["Upgrade"] != nil && strings.ToLower(r.Header["Upgrade"][0]) == "websocket" {
        //Handle WebSocket request. Forward the custom Upgrade header and rewrite origin
        r.Header.Set("Zr-Origin-Upgrade", "websocket")
        wsRedirectionEndpoint := selectedUpstream.OriginIpOrDomain
        if wsRedirectionEndpoint[len(wsRedirectionEndpoint)-1:] != "/" {
            //Append / to the end of the redirection endpoint if not exists
            wsRedirectionEndpoint = wsRedirectionEndpoint + "/"
        }
        if len(requestURL) > 0 && requestURL[:1] == "/" {
            //Remove starting / from request URL if exists
            requestURL = requestURL[1:]
        }
        u, _ := url.Parse("ws://" + wsRedirectionEndpoint + requestURL)
        if selectedUpstream.RequireTLS {
            u, _ = url.Parse("wss://" + wsRedirectionEndpoint + requestURL)
        }
        h.Parent.logRequest(r, true, 101, "host-websocket", selectedUpstream.OriginIpOrDomain)
        wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
            SkipTLSValidation: selectedUpstream.SkipCertValidations,
            SkipOriginCheck:   selectedUpstream.SkipWebSocketOriginCheck,
            Logger:            h.Parent.Option.Logger,
        })
        wspHandler.ServeHTTP(w, r)
        return
    }

I don't see there is any problem from the code level, at least in Zoraxy side. A few thing you might try.

Morethanevil commented 9 hours ago

Vaultwarden works out of the box with Zoraxy, I use it in Docker. No additional configuration needed, websockets are enabled by default

I use this environment in my compose file for Vaultwarden:

       environment:
            - 'TZ=Europe/Berlin'
            - 'SIGNUPS_ALLOWED=false'
            - 'DOMAIN=${DOMAIN}'
            - 'IP_HEADER=X-Forwarded-For'
            - 'SENDS_ALLOWED=true'
            - 'EMAIL_CHANGE_ALLOWED=true'
            - 'EVENTS_DAYS_RETAIN=360'
            - 'PASSWORD_HINTS_ALLOWED=true'
            - 'PUSH_ENABLED=true'
            - 'PUSH_INSTALLATION_ID=${PUSH_INSTALLATION_ID}'
            - 'PUSH_INSTALLATION_KEY=${PUSH_INSTALLATION_KEY}'
            - 'PUSH_RELAY_URI=https://push.bitwarden.eu'
            - 'PUSH_IDENTITY_URI=https://identity.bitwarden.eu'

Push sync works for me, maybe my configuration can help you with your setup.