401Unauthorized for Reverse-proxy with basicauth

1. The problem I’m having:

I have an rpc endpoint at port 12345, which can be called

curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"methodname","params":[],"id":67}' localhost:12345

now I am calling it on my local PC so it would be like:

curl -u 'usr:psswd' -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"methodname","params":[],"id":67}' https://this_is_the_dmain

Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying myip:443...
* TCP_NODELAY set
* Connected tothis_is_the_doman_name (myip) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=jchenrethnode.xyz
*  start date: Jul 19 00:26:55 2023 GMT
*  expire date: Oct 17 00:26:54 2023 GMT
*  subjectAltName: host "jchenrethnode.xyz" matched cert's "jchenrethnode.xyz"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Server auth using Basic with user 'admin'
* Using Stream ID: 1 (easy handle 0x55fa10e63840)
> POST / HTTP/2
> Host:this_is_the_doman_name
> authorization: Basic xx
> user-agent: curl/7.68.0
> accept: */*
> content-type: application/json
> content-length: 62
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 401
< alt-svc: h3=":443"; ma=2592000
< content-type: text/plain; charset=utf-8
< server: Caddy
* Authentication problem. Ignoring this.
< www-authenticate: Basic realm="restricted"
< content-length: 16
< date: Wed, 19 Jul 2023 03:32:56 GMT
<
* Connection #0 to hostthis_is_the_doman_name left intact
401 Unauthorized%

2. Error messages and/or full log output:

Jul 19 03:10:29 c3-large-x86-lax-1 systemd[1]: Starting Caddy...
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: caddy.HomeDir=/var/lib/caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: caddy.AppDataDir=/var/lib/caddy/.local/share/caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: caddy.AppConfigDir=/var/lib/caddy/.config/caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: caddy.ConfigAutosavePath=/var/lib/caddy/.config/caddy/autosave.json
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: caddy.Version=v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.GOOS=linux
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.GOARCH=amd64
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.Compiler=gc
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.NumCPU=48
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.GOMAXPROCS=48
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: runtime.Version=go1.20
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: os.Getwd=/
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: LANG=C.UTF-8
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: NOTIFY_SOCKET=/run/systemd/notify
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: HOME=/var/lib/caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: LOGNAME=caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: USER=caddy
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: INVOCATION_ID=8db45adc56ae4eea8d891b77a03130a8
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: JOURNAL_STREAM=8:6871974
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: SYSTEMD_EXEC_PID=118135
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5079222,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.509779,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5098946,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5099056,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5099454,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0001e8cb0"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.510153,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.51019,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size for details."}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5101929,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/var/lib/caddy/.local/share/caddy"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736229.5102417,"logger":"http","msg":"starting server loop","address":"[::]:443","tls":true,"http3":true}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5102518,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736229.5102677,"logger":"http","msg":"starting server loop","address":"[::]:80","tls":false,"http3":false}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5102715,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5102746,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["this_is_the_doman_name.xyz"]}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736229.5182009,"logger":"tls","msg":"loading managed certificate","domain":"this_is_the_doman_name.xyz","expiration":1697502415,"issuer_key":"acme-v02.api.letsencrypt.org-directory","storage":"FileStorage:/var/lib/caddy/.local/share/caddy"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5182784,"logger":"tls","msg":"finished cleaning storage units"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736229.5184479,"logger":"tls.cache","msg":"added certificate to cache","subjects":["this_is_the_doman_name.xyz"],"expiration":1697502415,"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"c5047d9c3075ea93b592655208e795b93740d9c0ab8ce60cd44d7a979fbd5ce8","cache_size":1,"cache_capacity":10000}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736229.5184703,"logger":"events","msg":"event","name":"cached_managed_cert","id":"fe3a215a-cd87-4048-91e5-4d6a78fd2be3","origin":"tls","data":{"sans":["this_is_the_doman_name.xyz"]}}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5185728,"msg":"autosaved config (load with --resume flag)","file":"/var/lib/caddy/.config/caddy/autosave.json"}
Jul 19 03:10:29 c3-large-x86-lax-1 caddy[118135]: {"level":"info","ts":1689736229.5186017,"msg":"serving initial configuration"}
Jul 19 03:10:29 c3-large-x86-lax-1 systemd[1]: Started Caddy.

Jul 19 03:12:36 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736356.8607526,"logger":"events","msg":"event","name":"tls_get_certificate","id":"6f8408ac-0608-420d-88e3-03312b5f91f2","origin":"tls","data":{"client_hello":{"CipherSuites":[4866,4867,4865,49196,49200,159,52393,52392,52394,49195,49199,158,49188,49192,107,49187,49191,103,49162,49172,57,49161,49171,51,157,156,61,60,53,47,255],"ServerName":"this_is_the_doman_name.xyz","SupportedCurves":[29,23,30,25,24],"SupportedPoints":"AAEC","SignatureSchemes":[1027,1283,1539,2055,2056,2057,2058,2059,2052,2053,2054,1025,1281,1537,771,769,770,1026,1282,1538],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771],"Conn":{}}}}
Jul 19 03:12:36 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736356.8609262,"logger":"tls.handshake","msg":"choosing certificate","identifier":"this_is_the_doman_name.xyz","num_choices":1}
Jul 19 03:12:36 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736356.8609476,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"this_is_the_doman_name.xyz","subjects":["this_is_the_doman_name.xyz"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"c5047d9c3075ea93b592655208e795b93740d9c0ab8ce60cd44d7a979fbd5ce8"}
Jul 19 03:12:36 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736356.8609633,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"68.36.53.112","remote_port":"61566","subjects":["this_is_the_doman_name.xyz"],"managed":true,"expiration":1697502415,"hash":"c5047d9c3075ea93b592655208e795b93740d9c0ab8ce60cd44d7a979fbd5ce8"}
Jul 19 03:12:37 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736357.8385465,"logger":"http.log.error.log0","msg":"not authenticated","request":{"remote_ip":"68.36.53.112","remote_port":"61566","proto":"HTTP/2.0","method":"POST","host":"this_is_the_doman_name.xyz","uri":"/","headers":{"Content-Length":["62"],"Authorization":[],"User-Agent":["curl/7.68.0"],"Accept":["*/*"],"Content-Type":["application/json"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"this_is_the_doman_name.xyz"}},"duration":0.900485636,"status":401,"err_id":"mdpg0qnyf","err_trace":"caddyauth.Authentication.ServeHTTP (caddyauth.go:88)"}
Jul 19 03:16:52 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736612.4052033,"logger":"events","msg":"event","name":"tls_get_certificate","id":"858ed029-c526-4368-822e-799704e695a4","origin":"tls","data":{"client_hello":{"CipherSuites":[49195,49199,49196,49200,52393,52392,49161,49171,49162,49172,156,157,47,53,49170,10,4865,4866,4867],"ServerName":"this_is_the_doman_name.xyz","SupportedCurves":[29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[2052,1027,2055,2053,2054,1025,1281,1537,1283,1539,513,515],"SupportedProtos":null,"SupportedVersions":[772,771],"Conn":{}}}}
Jul 19 03:16:52 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736612.4053135,"logger":"tls.handshake","msg":"choosing certificate","identifier":"this_is_the_doman_name.xyz","num_choices":1}
Jul 19 03:16:52 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736612.405336,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"this_is_the_doman_name.xyz","subjects":["this_is_the_doman_name.xyz"],"managed":true,"issuer_key":"acme-v02.api.letsencrypt.org-directory","hash":"c5047d9c3075ea93b592655208e795b93740d9c0ab8ce60cd44d7a979fbd5ce8"}
Jul 19 03:16:52 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736612.4053512,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"40.113.118.83","remote_port":"40115","subjects":["this_is_the_doman_name.xyz"],"managed":true,"expiration":1697502415,"hash":"c5047d9c3075ea93b592655208e795b93740d9c0ab8ce60cd44d7a979fbd5ce8"}
Jul 19 03:16:52 c3-large-x86-lax-1 caddy[118135]: {"level":"debug","ts":1689736612.5616946,"logger":"http.log.error.log0","msg":"not authenticated","request":{"remote_ip":"40.113.118.83","remote_port":"40115","proto":"HTTP/1.1","method":"GET","host":"this_is_the_doman_name.xyz","uri":"/","headers":{"User-Agent":["Go-http-client/1.1"],"Accept-Encoding":["gzip"],"Connection":["close"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","server_name":"this_is_the_doman_name.xyz"}},"duration":0.000043501,"status":401,"err_id":"wjx0vjy5g","err_trace":"caddyauth.Authentication.ServeHTTP (caddyauth.go:88)"}

While cat vitalik.log (the log file specified in the caddyfile) gives:

{
    "level": "error",
    "ts": 1689736357.8386104,
    "logger": "http.log.access.log0",
    "msg": "handled request",
    "request": {
        "remote_ip": "68.36.53.112",
        "remote_port": "61566",
        "proto": "HTTP/2.0",
        "method": "POST",
        "host": "this_is_the_doman_name.xyz",
        "uri": "/",
        "headers": {
            "Authorization": [],
            "User-Agent": [
                "curl/7.68.0"
            ],
            "Accept": [
                "*/*"
            ],
            "Content-Type": [
                "application/json"
            ],
            "Content-Length": [
                "62"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "cipher_suite": 4865,
            "proto": "h2",
            "server_name": "this_is_the_doman_name.xyz"
        }
    },
    "user_id": "",
    "duration": 0.900485636,
    "size": 16,
    "status": 401,
    "resp_headers": {
        "Alt-Svc": [
            "h3=\":443\"; ma=2592000"
        ],
        "Www-Authenticate": [
            "Basic realm=\"restricted\""
        ],
        "Content-Type": [
            "text/plain; charset=utf-8"
        ],
        "Server": [
            "Caddy"
        ]
    }
}
{
    "level": "error",
    "ts": 1689736612.5617342,
    "logger": "http.log.access.log0",
    "msg": "handled request",
    "request": {
        "remote_ip": "40.113.118.83",
        "remote_port": "40115",
        "proto": "HTTP/1.1",
        "method": "GET",
        "host": "this_is_the_doman_name.xyz",
        "uri": "/",
        "headers": {
            "Accept-Encoding": [
                "gzip"
            ],
            "Connection": [
                "close"
            ],
            "User-Agent": [
                "Go-http-client/1.1"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "cipher_suite": 4865,
            "proto": "",
            "server_name": "this_is_the_doman_name.xyz"
        }
    },
    "user_id": "",
    "duration": 0.000043501,
    "size": 16,
    "status": 401,
    "resp_headers": {
        "Content-Type": [
            "text/plain; charset=utf-8"
        ],
        "Server": [
            "Caddy"
        ],
        "Alt-Svc": [
            "h3=\":443\"; ma=2592000"
        ],
        "Www-Authenticate": [
            "Basic realm=\"restricted\""
        ]
    }
}

3. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

Follow the official docs using APT INSTALL

a. System environment:

Ubuntu 22.04

b. Command:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

c. Service/unit/compose file:

d. My complete Caddy config:

{
        log {
                level DEBUG
        }

        email hi@this_is_the_doman_name.xyz
}

this_is_the_doman_name.xyz {
        basicauth {
                admin admintoken
        }

        reverse_proxy 127.0.0.1:12345
        reverse_proxy /graphql 127.0.0.1:12345

        # Set the default 404 page
        # https://caddyserver.com/docs/caddyfile/directives/handle_errors
        handle_errors {
                respond "{http.error.status_code} {http.error.status_text}"
        }

        # Log startup messages
        log {
                output file /var/log/caddy/vitalik.log
                format json
        }
}

5. Links to relevant resources:

How did you generate the password for basicauth? It must be a bcrypt hash.

Hi francislavoie, thanks for the reply.

Yeah I am using the long hash string for password. Actually I am using the one mentioned in the documentation (basicauth (Caddyfile directive) — Caddy Documentation). I think it’s ok for the test purpose and for sanity check. But it still gives the same response just like the one I mentioned in section 1.

btw I find this line in the response of curl -vl looks suspicious, but I searched online without finding anything solutions.

* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 401

I tested it with this config:

{
    debug
}

:8881 {
    log
    basicauth {
        Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
    }

    respond "Hello"
}

And it works fine:

$ curl -v -u 'Bob:hiccup' localhost:8881                                                                           
*   Trying 127.0.0.1:8881...
* Connected to localhost (127.0.0.1) port 8881 (#0)
* Server auth using Basic with user 'Bob'
> GET / HTTP/1.1
> Host: localhost:8881
> Authorization: Basic Qm9iOmhpY2N1cA==
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Server: Caddy
< Date: Thu, 20 Jul 2023 07:21:44 GMT
< Content-Length: 5
< 
* Connection #0 to host localhost left intact
Hello

I’m not sure what to tell you.

Hi francislavoie, I think I find the reason. I am passing the hashed version of the password, instead I should pass the original un-hashed password. Thank you!

btw may I ask why I got different result each time I hash the same string, like the one you used ‘biccup’? how can caddy verify that if the hashed string is un-deterministic?

1 Like

Yeah, you need to send the actual plaintext password. Browsers/clients don’t hash passwords client-side, they just take user input then send it to the server to verify.

See Salt (cryptography) - Wikipedia and bcrypt - Wikipedia

1 Like

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