Can not access web site on itself host via forwardproxy
e.g:
We have a forwardproxy for https://proxy.plus on host A, and a web site https://web.plus ( different from proxy.plus ) on the same host with caddy. P.S. enable tls always.
When browse the https://web.plus via https://proxy.plus proxy, chrome says "ERR_TUNNEL_CONNECTION_FAILED".
Other web sites work okay via https://proxy.plus.
When browse https://web.plus, caddy gives the vhost web.plus which should be proxy.plus.
The code: https://github.com/mholt/caddy/blob/master/caddyhttp/httpserver/server.go#L385
Thanks for the report! I am not sure when I'll be able to dive into this issue, and PRs are always welcome.
When browse https://web.plus, caddy gives the vhost
web.pluswhich should beproxy.plus. IIRC, vhost is determined byHostheader, which isweb.plus.
The problem is most likely that Caddy receives:
CONNECT web.plus HTTP/1.1
Host: web.plus
which is proxying request that should have internally went to proxy.plus, but Caddy matches it to web.plus and sends it there for processing. Then the standard web.plus chain of middleware won't know what to do with this wierd request. The fix will probably involve changes to the Caddy itself, I am not quite sure what would be an elegant solution.
/cc @mholt
P.S. as a temporary workaround you can try using PAC files, to make browser use DIRECT connection to web.plus and not send CONNECT requests to Caddy.
@jim3ma, what client software are you using?
@bemasc just Chrome with SwitchyOmega. @mholt can you consider to extend some config for caddy to match host customize ?
I think I know why this is happening. Caddy is programmed to handle requests by Host header, to choose the middleware chain it follows. For any Host that doesn't match one defined in the Caddyfile, it routes to a forwardproxy chain, if configured. But in this case, Caddy has a site defined for the Host name you're trying to access via a proxy.
How would Caddy know which middleware chain to use?
We could send all CONNECT requests into middleware chain with forwardproxy, but that doesn't integrate very well into current host matching logic of Caddy.
As an aside, here's another temporary workaround: add forwardproxy to all your chains.
@mholt When chrome uses forwardproxy, chrome dials proxy.plus with tls. The tls connection knows the right host is proxy.plus with SNI, so when match vhost, Caddy should consider the SNI hostname.
BTW, each vhost has the supported methods like POST, GET, DELETE. When match vhost, the supported methods should be considered.
@sergeyfrolov add forwardproxy to all chains seems not work for proxy directive.
Caddy should consider the SNI hostname
Webservers generally don't do this, and there are setups that rely on this not being the case. Among other more general network configurations, the fact that webservers don't prioritize SNI in vhost matching is how Domain Fronting censorship circumvention technique works.
BTW each vhost has the supported methods like POST, GET, DELETE. supported methods should be considered
If supported methods are known for each vhost, then this might work. Currently, when forwardproxy loads, it sets the chain it's in to be a fallback for unmatched hosts. We can disable CONNECTs on all vhosts but forwardproxying one and allow CONNECT requests to be handled by fallback. As an added advantage, we would be able use FallbackHost only for unmatched CONNECT requests, as opposed to current state of things in which all and every unmatched request goes into forwardproxying chain.
How about a flag like -sni-first that tells Caddy to try matching a site based on the SNI name and then, if there are no matches, to use the Host header instead?
The sni-first option is okay. So we did not hack the match method which always move traffic to forwardproxy.