Dial error when using placeholder as proxy target

1. Caddy version (caddy version):


2. How I run Caddy:

bin/caddy run -config assets/conf/Caddyfile

a. System environment:

macOS Catelina

b. Command:

bin/caddy run -config assets/conf/Caddyfile

c. Service/unit/compose file:

paste full file contents here

d. My complete Caddyfile or JSON config:

  https_port   8443

localhost:8443 {

  route {
    @mytest {
      query proxyTarget=*
    reverse_proxy @mytest {http.request.uri.query.proxyTarget} {
      transport http {

  log {
    output file /opt/caddy/log/access.log
    format single_field common_log

3. The problem I’m having:

Dial error when using placeholder to specify proxy target.

4. Error messages and/or full log output:

dial https:: unknown network https

5. What I already tried:

The above Caddyfile works great if I hardcode a target url: https://myhome.com
or if I use an environment variable

export PROXY_TARGET="https://myhost.com"

reverse_proxy {$PROXY_TARGET}

Yet via a placeholder I get an error!

curl --insecure -v "https://localhost:8443/app/api-docs?proxyTarget=https://myhost.com"

6. Links to relevant resources:

Dial addresses must be only a host and port. The https:// bit is Caddyfile sugar for enabling the tls option (if using the http transport). Your placeholder is being used at runtime, so that skips right past the Caddyfile’s logic.

So you’ll need to make your request ?proxyTarget=myhost.com:443

This seems ripe for abuse though. I think you should set up a whitelist for the allowed values :thinking:

FYI re query matcher, I found a bug with it yesterday, so you may need to wait for v2.3.0 to properly whitelist with a query matcher:


1 Like

That explains it :smiley:

I had some success with a pair of placeholders (one host and one port) however a combined placeholder of host, colon and port, as you suggest, failed

To explain, if I have three placeholders

proxy_target = myhost.com:443
proxy_host = myhost.com
proxy_port = 443

reverse_proxy {proxy_target}

I get

invalid dial address myhost.com:443:80

However if I use:

reverse_proxy {proxy_host}:{proxy_port}

it works!

BTW: We intend to run a whitelist plus JWT validation to hopefully avoid obvious open proxy abuse

Right, sorry about that, that bug with :80 was fixed recently but hasn’t been released yet:


Looks like v2.3.0 will be a big one for you :sweat_smile:

Good news… thanks for this.

You know it’s only a matter of time before I’m gonna ask about a release date for 2.3.0 :stuck_out_tongue_winking_eye:

Probably at least a few weeks away. There’s still a lot of PRs that need to get reviewed and merged (I flooded Matt’s inbox this weekend lmao)

You can always build from source if you need to, it’s dead-simple with xcaddy:

You can specify a specific commit hash to build from.

Thank you… I’ll start with xcaddy now.

I used xcaddy with commit: c9fdff9
And I still have a problem. It looks like a colon : is being inserted unless I use a colon between two placeholders but if a colon exists within a placeholder another is added before the dial.

making dial info: upstream {http.scheme}{http.host}{http.port}:: invalid dial address https://github.com:443:: address /github.com:443:: too many colons in address

Well, you can’t have the scheme; that’s one thing. The scheme is a Caddyfile-only shortcut to enable the tls field in the JSON. Caddy isn’t equipped to proxy to HTTP or HTTPS dynamically, it’s either or.

That said, I don’t know where the :: is coming from, that doesn’t make sense :thinking:

My bad… you already told me the scheme is stripped

But I think there must be code looking for and adding a missing : and doing so before placeholder expansion.

Also… if the Caddyfile processing removes https would it be possible to assume 443 (if port is not provided)?

Yes, Caddyfile will add :443 if there’s no port, I think, if you specify https://. But you can easily verify by using caddy adapt and looking at the output.

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