forwardproxy
forwardproxy copied to clipboard
Proxy served on all (sub)domains
Here's my caddyfile (I have to use port 443 for other reasons, but this happens on any port):
pi:443 {
tls off
}
proxy.website.com:443 {
forwardproxy {
basicauth username password
serve_pac config.pac
}
tls off
}
pi is my server's hostname in my LAN. A proxy is hosted at proxy.website.com, which is what should be happening. The problem is, it's also hosted on port 443 on any other domain. This Caddyfile is just one example. No matter what I try, I can't only host the proxy on one domain, no matter the port or domain.
Another example:
website.com:80 {
root websiteroot
ext html htm
}
proxy.website.com:80 {
forwardproxy {
basicauth username password
}
}
Here, a webpage won't get served at website.com:80. Instead, a proxy will. this makes it impossible to have a proxy served only on a subdomain, on the same port.
@hacker1024
This is a known (to developers) limitation and it has to do how Caddy matches requests to websites.
While forwardproxying, the only place where website name shows up is Subject Name Indication during TLS handshake. After the tls handshake, it's just CONNECT somesite.com HTTP/1.1 OR GET anothersite.com HTTP/1.1.
For any use-case, other than forwardproxy (which came around last August), Caddy doesn't need to keep track of which SNI was used for which TLS connection, and thus was designed to simply match requests where they should go, as they come. Other webservers share this behavior. So what we've done, when we added forwardproxy, is that whenever forwardproxy is on, Caddy will match all unmatched requests into the forwardproxying chain. Hence, your issue.
As a result, fixing this issue would require (potentially substantial) changes in Caddy's core to make sure incoming requests have context that includes original SNI. I, as author of forwardproxy, do not know whether @mholt (Caddy author) would be happy for this to happen. If you describe your use-case and why it's important for forwardproxy to only work with single SNI, that might help.
Sergey is right.
... although technically, Caddy does already (uniquely) hold onto the TLS ClientHello info for MITM detection for each HTTPS request. It doesn't currently hold onto the SNI information but we could potentially add it.
Anyway, it's not out of the question.
I see. In the meantime, perhaps an error or warning could show when someone tries to do what I've done?
Perhaps we could introduce a -sni-first flag (as in #12), except by this issue the flag would also disable forwardproxy's "fallback" behavior. In other words, without the -sni-first flag, the forwardproxy plugin tells Caddy to "fall back" to the site of the forwardproxy when the Host header doesn't match any site definitions. This is how it already works. But if we use -sni-first then we would have to disable that, since we would match on SNI to find the site definition that applies to that request, then consume the Host header with forwardproxy.
It's a bit of a hack, and very, very niche use, and we'd have to consider on the implications for probe resistance. Feedback and critique welcome.
I think the -sni-first disables the forwardproxy's "fallback" behavior is not matter.
When proxy traffic comes with -sni-first, caddy knows it is for the proxy site(which configured with forwardproxy).
While currently the fallback method is just a workaround. We should consider a perfect solution.
With -sni-first, forwardproxy should register with the site and the CONNECT method for catching the proxy traffic and this can resolve this issue.
Without -sni-first, it seems that fallback is the only way.