Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

core: add modular network_proxy support #6399

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open

Conversation

mohammed90
Copy link
Member

@mohammed90 mohammed90 commented Jun 14, 2024

The PR #5369 introduced support for the standard env vars HTTP_PROXY, HTTPS_PROXY, and NO_PROXY in the reverse_proxy handler. The ACME client in Caddy has always respected the vars. The issue #6111 shows a need for configurable forward-proxy outside the env vars due to the global state of env vars.

The post (https://caddy.community/t/routing-acme-requests-via-http-proxy/24363) in the Caddy forum shows a need for forward-proxy support for ACME (external requests) but not for reverse-proxy upstreams. Again, the global state nature of the env vars impedes any effort to separate those concerns.

To brainstorm the best solution, I'm introducing modular approach, where the proxy address can be explicitly configured via module and falls back to env var. Discussion and iteration on this PR is necessary to ensure a common satisfactory solution is reached. I haven't wired up the Caddyfile parts.

CC/ @ImpostorKeanu

Note if this approach is acceptable, the ForwardProxyURL field will be deprecated in favor of the "from": "url" module.

TODO:

  • Caddyfile
  • Tests

Co-authored-by: @ImpostorKeanu
Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
@mohammed90 mohammed90 added in progress 🏃‍♂️ Being actively worked on discussion 💬 The right solution needs to be found needs docs ✍️ Requires documentation changes needs tests 💯 Requires automated tests labels Jun 14, 2024
@ImpostorKeanu
Copy link
Contributor

Slick! I support everything about this!

Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
@mohammed90 mohammed90 marked this pull request as ready for review August 24, 2024 13:11
Copy link
Member

@francislavoie francislavoie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design makes sense to me 👍

caddy.RegisterModule(ProxyFromNone{})
}

// The "url" proxy source uses the defined URL as the proxy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we usually start godoc comments with the name of the type as the first word? I don't know why that's the convention but I think that's what we typically do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a Go idiom. However, we pick up the same doc lines for our documentation, so I had to make a judgement call to either make it sensible for our documentation or meet the informal convention of Go docs. It's less confusing for our users to see the module name instead of the other way around.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes linters/vet will catch this, but if not, I guess we can keep it as-is.

I had planned at one point to tune our Caddy docs to account for the Godoc convention and help eliminate the repetition, but I haven't gotten around to it yet.

mohammed90 and others added 2 commits August 27, 2024 10:48
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
@mohammed90 mohammed90 linked an issue Aug 29, 2024 that may be closed by this pull request
@mohammed90
Copy link
Member Author

I forgot about this PR. @mholt, @francislavoie, should we move it to 2.10? I'm fine either way.

@mohammed90 mohammed90 removed in progress 🏃‍♂️ Being actively worked on needs docs ✍️ Requires documentation changes needs tests 💯 Requires automated tests labels Dec 29, 2024
@mohammed90 mohammed90 added the under review 🧐 Review is pending before merging label Dec 29, 2024
@mholt
Copy link
Member

mholt commented Dec 30, 2024

Hm, yeah, that might be best. Thanks for updating and we'll get back to this soon!

@mholt mholt added this to the v2.10.0-beta.1 milestone Dec 30, 2024
@mholt mholt modified the milestones: v2.10.0-beta.1, v2.10.0-beta.2 Mar 6, 2025
Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Mohammed! Looking pretty good, just a few nits on my end.

//
// If nil, defaults to reading the `HTTP_PROXY`,
// `HTTPS_PROXY`, and `NO_PROXY` environment variables.
NetworkProxyRaw json.RawMessage `json:"network_proxy,omitempty" caddy:"namespace=caddy.network_proxy.source inline_key=from"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other modules that could be made under caddy.network_proxy? (i.e. is the .source namespace useful)?

If so, let's definitely keep it -- just curious.

@@ -0,0 +1,3 @@
package caddytls

import _ "github.com/caddyserver/caddy/v2/modules/internal/network"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting; why the indirection here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is embarrassing. I don't remember, and it still works without it.

caddy.RegisterModule(ProxyFromNone{})
}

// The "url" proxy source uses the defined URL as the proxy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes linters/vet will catch this, but if not, I guess we can keep it as-is.

I had planned at one point to tune our Caddy docs to account for the Godoc convention and help eliminate the repetition, but I haven't gotten around to it yet.

Comment on lines +134 to +136
var (
_ caddy.Module = ProxyFromURL{}
_ caddy.Provisioner = &ProxyFromURL{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for interface guards, caddy.Module isn't needed since you call RegisterModule().

I also prefer this pattern to avoid allocations:

var _ caddy.Provisioner = (*ProxyFromURL)(nil)

"net/url"
)

type ProxyFuncProducer interface {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How necessary is this for it to have its own file? Can we move this into an existing file?

Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
@mholt mholt modified the milestones: v2.10.0-beta.2, v2.10.0-beta.3 Mar 8, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
discussion 💬 The right solution needs to be found under review 🧐 Review is pending before merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Placeholders for forward_proxy_url
5 participants