Reverse Proxy without Subdomains via Routes

1. My Caddy version (caddy version):

2.0.0 (caddy_2.0.0_linux_amd64)

2. How I run Caddy:

caddy run/caddy start with Caddyfile

a. System environment:

Native in an proxmox lxc container (Ubuntu)

d. My complete Caddyfile or JSON config:

example.spdns.de {
/#	encode zstd gzip

	respond "Hello, world!"

	route /nucstation/* {
/#		respond "Test"
		reverse_proxy http://192.168.178.7:5000
/#		reverse_proxy https://192.168.178.7:5001
	}	
}

(i used the /# just beacuase normal it would make it big)

3. The problem I’m having:

Im using a free DynDNS Service, so i cant use Subdomains.
So i would like to use routes to access my different Services.
/nucstation is a Synology Diskstaion. Port 5000 is only http. 5001 is https.
When connecting to example.spdns.de/nucstation/ i get a Synology Page, but not the normal Webinterface. The page says that the requested site is not found. Https gives a Gateway error which i think is because of the wrong certificate.

5. What I already tried:

I looked tgrough the documentation and the forum for help but no one seems to have problem like this.

I really appreciate your help

if i’m not wrong you can’t pass double reverse_proxy parameters for single domain.

Try this:

    example.spdns.de {
      encode zstd gzip
      route /nucstation/* {
        reverse_proxy https://192.168.178.7:5000
      }
     route /nucstationhttps/* {
       reverse_proxy https://192.168.178.7:5001
    }
    }

Thank you i’m gonna try it.
But the https one was commented, as well as the encode zstd gzip and the respond “Test”

Edit:
The result via http stays the same
The result via https is a HTTP ERROR 502

Caddy says:

ERROR   http.log.error  x509: cannot validate certificate for 192.168.178.7 because it doesn't contain any IP SANs      {"request": {"method": "GET", "uri": "/nucstationhttps/", "proto": "HTTP/2.0", "remote_addr": "ip", "host": "example.spdns.de", "headers": {"Upgrade-Insecure-Requests": ["1"], "Dnt": ["1"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.132 Safari/537.36"], "Sec-Fetch-Site": ["cross-site"], "Sec-Fetch-Mode": ["navigate"], "Accept-Encoding": ["gzip, deflate, br"], "Cache-Control": ["max-age=0"], "Sec-Fetch-User": ["?1"], "Sec-Fetch-Dest": ["document"], "Accept-Language": ["de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "example.spdns.de"}}, "duration": 0.029783163, "status": 502, "err_id": "m7m2hhp4n", "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:380)"}

https using x509 certificate hmm

add
insecure_skip_verify

Thanks for the suggestion.
But i dont know where to add it. I always get errors when starting caddy with it

in route’s { … }

Domain {
        encode zstd gzip

        respond "Hello World!"

        route /nucstation/* {
                insecure_skip_verify
                reverse_proxy http://192.168.178.7:5000 {
                }
        }

        route /nucstationhttps/* {
                insecure_skip_verify
                reverse_proxy https://192.168.178.7:5001 {
                }
        }
}

When i do it like this i get this error:

adapting config using caddyfile: parsing caddyfile tokens for 'route': Caddyfile:7 - Error during parsing: unrecognized directive: insecure_skip_verify

@Titanhunter please always wrap your configs and logs with ``` on a line before and after the contents! You got flagged as a spam account because of repeated URLs in your posts. Using backticks will avoid this problem!

Okay, thank you i didnt know this. Im gonna change it

the directive is not

insecure_skip_verify

but

tls_insecure_skip_verify

and it is used inside a transport http directive.
so the complete example should be

Domain {
        encode zstd gzip

        respond "Hello World!"

        route /nucstation/* {
                reverse_proxy http://192.168.178.7:5000 {
                #tls_insecure_skip_verify # not necessary because upstream is http
                }
        }

        route /nucstationhttps/* {
                reverse_proxy https://192.168.178.7:5001 {
                    transport http {
                       tls
                       tls_insecure_skip_verify
                       }
                    }
                }
        }
}
1 Like

I highly recommend you use the caddy fmt command built into the binary to clean up the indentation in your configs! It’ll make it much easier to read and to discuss it.

Okay my config now looks like this

example.spdns.de {
        encode zstd gzip

        respond "Hello World!"

        route /nucstation/* {
                uri strip_prefix nucstation/
                reverse_proxy https://192.168.178.7:5001 {
                        transport http {
                                tls tls_insecure_skip_verify
                        }
                }
        }

        route /pve/* {
                uri strip_prefix pve/
                reverse_proxy https://192.168.178.99:8006 {
                        transport http {
                                tls tls_insecure_skip_verify
                        }
                }
        }
}
}

I used the url strip_prefix from the documentation. At least i get errors now and the right sorcecode is shown. But javascript doesnt seem to work

Edit: Also the Headers are now shown correctly

What do you mean by that?

Also you have a few issues in your Caddyfile. I think you have an extra closing curly brace, and tls tls_insecure_skip_verify isn’t right; they should be on separate lines.

Yes youre right. There was an extra curly brace. and i made the tls_… in an extra line.
That unfortunately didnt solve the problem

These are the Errors i get when loading example.spdns.de/pve/. The Site is completely white

So i thought that there may be a problem with javascript

Yeah, so now your site’s JS is invalid. But that doesn’t (shouldn’t) have anything to do with Caddy.

So I guess the problem is resolved?

I think you actually want to strip the prefix like this:

uri strip_prefix /nucstation

Slash in front, not after.

Yes it kind of is. But i dont have any real use of the reverse proxy because my Services dont work via the reverse proxy. I dont get these errors when im local.
But maybe this is a new topic.

Okay, thank you i changed it. I get the same result anyway.

What’s the output from curling one of these JS requests e.g. curl -iL example.spdns.de/pve/ext-all.js ?

I wonder if you’re running into the subfolder problem (the upstream app doesn’t know it’s meant to be contained within the /pve/ subfolder, so the indexes reference content irrespective of that base URL), which would cause it to respond with Hello world! per your respond directive (so all of those JS responses would be generating first-line errors).

curl -iL example.spdns.de/pve/ext-all.js
HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://example.spdns.de/pve/ext-all.js
Server: Caddy
Date: Thu, 07 May 2020 08:40:50 GMT
Content-Length: 0

HTTP/2 501 
cache-control: max-age=0
date: Thu, 07 May 2020 08:40:50 GMT
expires: Thu, 07 May 2020 08:40:50 GMT
pragma: no-cache
server: Caddy
server: pve-api-daemon/3.0
content-length: 0

Then i tried this one

curl -iL example.spdns.de/pve/proxmoxlib.js
HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://example.spdns.de/pve/proxmoxlib.js
Server: Caddy
Date: Thu, 07 May 2020 08:44:55 GMT
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: application/javascript
Date: Thu, 07 May 2020 08:44:55 GMT
Last-Modified: Thu, 30 Jan 2020 16:49:32 GMT
Server: Caddy
Server: pve-api-daemon/3.0
Transfer-Encoding: chunked

// 2.1-3
Ext.ns('Proxmox');
Ext.ns('Proxmox.Setup');

if (!Ext.isDefined(Proxmox.Setup.auth_cookie_name)) {
    throw "Proxmox library not initialized";
}

// avoid errors related to Accessible Rich Internet Applications
// (access for people with disabilities)
// TODO reenable after all components are upgraded
Ext.enableAria = false;
Ext.enableAriaButtons = false;
Ext.enableAriaPanels = false;

// avoid errors when running without development tools
if (!Ext.isDefined(Ext.global.console)) {
    var console = {
        dir: function() {},
        log: function() {}
    };
}

Ext.Ajax.defaultHeaders = {
    'Accept': 'application/json'
};

Ext.Ajax.on('beforerequest', function(conn, options) {
    if (Proxmox.CSRFPreventionToken) {
        if (!options.headers) {
            options.headers = {};
        }
        options.headers.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
    }
});
...

It displays the whole JS so the first level seem to work just fine