Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

core: add modular network_proxy support #6399

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:8884
reverse_proxy 127.0.0.1:65535 {
transport http {
forward_proxy_url http://localhost:8080
}
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":8884"
],
"routes": [
{
"handle": [
{
"handler": "reverse_proxy",
"transport": {
"network_proxy": {
"from": "url",
"url": "http://localhost:8080"
},
"protocol": "http"
},
"upstreams": [
{
"dial": "127.0.0.1:65535"
}
]
}
]
}
]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
:8884
reverse_proxy 127.0.0.1:65535 {
transport http {
network_proxy none
}
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":8884"
],
"routes": [
{
"handle": [
{
"handler": "reverse_proxy",
"transport": {
"network_proxy": {
"from": "none"
},
"protocol": "http"
},
"upstreams": [
{
"dial": "127.0.0.1:65535"
}
]
}
]
}
]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:8884
reverse_proxy 127.0.0.1:65535 {
transport http {
network_proxy url http://localhost:8080
}
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":8884"
],
"routes": [
{
"handle": [
{
"handler": "reverse_proxy",
"transport": {
"network_proxy": {
"from": "url",
"url": "http://localhost:8080"
},
"protocol": "http"
},
"upstreams": [
{
"dial": "127.0.0.1:65535"
}
]
}
]
}
]
}
}
}
}
}
24 changes: 22 additions & 2 deletions modules/caddyhttp/reverseproxy/caddyfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/caddyserver/caddy/v2/modules/caddyhttp/headers"
"github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite"
"github.com/caddyserver/caddy/v2/modules/caddytls"
"github.com/caddyserver/caddy/v2/modules/internal/network"
)

func init() {
Expand Down Expand Up @@ -980,7 +981,9 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
// read_buffer <size>
// write_buffer <size>
// max_response_header <size>
// forward_proxy_url <url>
// network_proxy <module> {
// ...
// }
// dial_timeout <duration>
// dial_fallback_delay <duration>
// response_header_timeout <duration>
Expand All @@ -991,6 +994,9 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
// tls_insecure_skip_verify
// tls_timeout <duration>
// tls_trusted_ca_certs <cert_files...>
// tls_trust_pool <module> {
// ...
// }
// tls_server_name <sni>
// tls_renegotiation <level>
// tls_except_ports <ports...>
Expand Down Expand Up @@ -1069,10 +1075,24 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}

case "forward_proxy_url":
caddy.Log().Warn("The 'forward_proxy_url' field is deprecated. Use 'network_proxy url <url>' instead.")
if !d.NextArg() {
return d.ArgErr()
}
h.ForwardProxyURL = d.Val()
u := network.ProxyFromURL{URL: d.Val()}
h.NetworkProxyRaw = caddyconfig.JSONModuleObject(u, "from", "url", nil)

case "network_proxy":
if !d.NextArg() {
return d.ArgErr()
}
modStem := d.Val()
modID := "caddy.network_proxy.source." + modStem
unm, err := caddyfile.UnmarshalModule(d, modID)
if err != nil {
return err
}
h.NetworkProxyRaw = caddyconfig.JSONModuleObject(unm, "from", modStem, nil)
mohammed90 marked this conversation as resolved.
Show resolved Hide resolved

case "dial_timeout":
if !d.NextArg() {
Expand Down
40 changes: 32 additions & 8 deletions modules/caddyhttp/reverseproxy/httptransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
weakrand "math/rand"
"net"
"net/http"
"net/url"
"os"
"reflect"
"strings"
Expand All @@ -36,8 +35,10 @@ import (
"golang.org/x/net/http2"

"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"github.com/caddyserver/caddy/v2/modules/caddytls"
"github.com/caddyserver/caddy/v2/modules/internal/network"
)

func init() {
Expand Down Expand Up @@ -88,6 +89,7 @@ type HTTPTransport struct {
// forward_proxy_url -> upstream
//
// Default: http.ProxyFromEnvironment
// DEPRECATED: Use NetworkProxyRaw|`network_proxy` instead. Subject to removal.
ForwardProxyURL string `json:"forward_proxy_url,omitempty"`

// How long to wait before timing out trying to connect to
Expand Down Expand Up @@ -139,6 +141,22 @@ type HTTPTransport struct {
// The pre-configured underlying HTTP transport.
Transport *http.Transport `json:"-"`

// The module that provides the network (forward) proxy
// URL that the HTTP transport will use to proxy
// requests to the upstream. See [http.Transport.Proxy](https://pkg.go.dev/net/http#Transport.Proxy)
// for information regarding supported protocols.
//
// Providing a value to this parameter results in requests
// flowing through the reverse_proxy in the following way:
//
// User Agent ->
// reverse_proxy ->
// [proxy provided by the module] -> upstream
//
// 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"`

h2cTransport *http2.Transport
h3Transport *http3.RoundTripper // TODO: EXPERIMENTAL (May 2024)
}
Expand Down Expand Up @@ -326,16 +344,22 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
}

// negotiate any HTTP/SOCKS proxy for the HTTP transport
var proxy func(*http.Request) (*url.URL, error)
proxy := http.ProxyFromEnvironment
if h.ForwardProxyURL != "" {
pUrl, err := url.Parse(h.ForwardProxyURL)
caddyCtx.Logger().Warn("forward_proxy_url is deprecated; use network_proxy instead")
u := network.ProxyFromURL{URL: h.ForwardProxyURL}
h.NetworkProxyRaw = caddyconfig.JSONModuleObject(u, "from", "url", nil)
}
if len(h.NetworkProxyRaw) != 0 {
proxyMod, err := caddyCtx.LoadModule(h, "ForwardProxyRaw")
if err != nil {
return nil, fmt.Errorf("failed to parse transport proxy url: %v", err)
return nil, fmt.Errorf("failed to load network_proxy module: %v", err)
}
if m, ok := proxyMod.(caddy.ProxyFuncProducer); ok {
proxy = m.ProxyFunc()
} else {
return nil, fmt.Errorf("network_proxy module is not `(func(*http.Request) (*url.URL, error))``")
}
caddyCtx.Logger().Info("setting transport proxy url", zap.String("url", h.ForwardProxyURL))
proxy = http.ProxyURL(pUrl)
} else {
proxy = http.ProxyFromEnvironment
}

rt := &http.Transport{
Expand Down
19 changes: 17 additions & 2 deletions modules/caddytls/acmeissuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type ACMEIssuer struct {
// be used. EXPERIMENTAL: Subject to change.
CertificateLifetime caddy.Duration `json:"certificate_lifetime,omitempty"`

// Forward proxy module
NetworkProxyRaw json.RawMessage `json:"network_proxy,omitempty" caddy:"namespace=caddy.network_proxy.source inline_key=from"`

rootPool *x509.CertPool
logger *zap.Logger

Expand Down Expand Up @@ -170,15 +173,15 @@ func (iss *ACMEIssuer) Provision(ctx caddy.Context) error {
}

var err error
iss.template, err = iss.makeIssuerTemplate()
iss.template, err = iss.makeIssuerTemplate(ctx)
if err != nil {
return err
}

return nil
}

func (iss *ACMEIssuer) makeIssuerTemplate() (certmagic.ACMEIssuer, error) {
func (iss *ACMEIssuer) makeIssuerTemplate(ctx caddy.Context) (certmagic.ACMEIssuer, error) {
template := certmagic.ACMEIssuer{
CA: iss.CA,
TestCA: iss.TestCA,
Expand All @@ -191,6 +194,18 @@ func (iss *ACMEIssuer) makeIssuerTemplate() (certmagic.ACMEIssuer, error) {
Logger: iss.logger,
}

if len(iss.NetworkProxyRaw) != 0 {
proxyMod, err := ctx.LoadModule(iss, "ForwardProxyRaw")
if err != nil {
return template, fmt.Errorf("failed to load network_proxy module: %v", err)
}
if m, ok := proxyMod.(caddy.ProxyFuncProducer); ok {
template.HTTPProxy = m.ProxyFunc()
} else {
return template, fmt.Errorf("network_proxy module is not `(func(*http.Request) (*url.URL, error))``")
}
}

if iss.Challenges != nil {
if iss.Challenges.HTTP != nil {
template.DisableHTTPChallenge = iss.Challenges.HTTP.Disabled
Expand Down
3 changes: 3 additions & 0 deletions modules/caddytls/proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package caddytls

import _ "github.com/caddyserver/caddy/v2/modules/internal/network"
Loading
Loading