caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
58.7k stars 4.05k forks source link

Feature Addition: Enhance reverse_proxy module with support for a specified transport proxy #6111

Closed ImpostorKeanu closed 8 months ago

ImpostorKeanu commented 9 months ago

For the http.reverse_proxy module, having the option of specifying a HTTP/SOCKS proxy for the http.Transport of the reverse proxy client in the configuration file would be ideal. It's currently configurable only via http.ProxyFromEnvironment and may impact functionality of other modules.

I've implemented the proposed changes and they seem to work well but I'm new to contributing to the project so there's a chance that they're naive. I'll submit a PR for review.

P.S. Caddy is amazing. It's become a critical component in so many of my projects and I'm very grateful for all the thoughtful hard work. ❤️

francislavoie commented 9 months ago

In case you didn't realize, you can use the HTTP_PROXY env var. That's what ProxyFromEnvironment does.

ImpostorKeanu commented 9 months ago

I've ran into situations where particular modules need to use distinct HTTP proxies. Is this possible with http.ProxyFromEnvironment?

francislavoie commented 9 months ago

You mean different proxies per reverse_proxy in your config? No I don't think that's possible.

Thinking back, I think ~1 year ago+ @mohammed90 @mholt and I had a discussion about this stuff... I think one problem is that we have HTTP clients all over Caddy in different places, like the ACME client, reverse proxy, etc which means we'd probably want a centralized place to configure all of them. But it would be complicated to have to push down that config to relevant places.

The question is whether we want to only have a URL as config, or if we might want to make it modular (i.e. allow plugins to choose the proxy). I don't know what kind of usecases there would be to having it modular though, I've never needed a forward proxy myself.

ImpostorKeanu commented 9 months ago

Yes, that's what I've been coming up against. There has been at least one other discussion where someone was trying to achieve the same but it seems the discussion died.

My use case is being able to reverse engineer applications during penetration tests. I've found it useful to be able to send the entire request chain through Burp for inspection/analysis. While HTTP_PROXY works, adjacent reverse_proxy configurations are also proxying through Burp when they ideally wouldn't.

flowchart
ua["User Agent"] --> burp[Burp] --> caddy["Caddy (Reverse Proxy)"] --> burp --> inscope[In-Scope Wapp]

Admittedly this isn't a common use case, but I decided to propose the change after seeing that at least one other person had a similar issue.

IMVHO, allowing modules to take precedent over HTTP_PROXY with distinct configurations would be solid. This'd allow a global proxy to be set for all HTTP clients and granular configuration for individual plugins/modules (if they care to). Again, y'all know the architecture/code base much better than I do so no problem at all if we think this is bad/complex design that few will benefit from.