diff options
author | Jason Song <i@wolfogre.com> | 2023-10-18 17:44:36 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-18 09:44:36 +0000 |
commit | 4e98224a4501238286ee3fd5ed911958951da9b0 (patch) | |
tree | 462c9e987f18ecd2fa2e23a302a277149ce9c3c0 /modules/hostmatcher | |
parent | 8abc1aae4ab5b03be0bcbdd390bb903b54ccd21a (diff) | |
download | gitea-4e98224a4501238286ee3fd5ed911958951da9b0.tar.gz gitea-4e98224a4501238286ee3fd5ed911958951da9b0.zip |
Support allowed hosts for webhook to work with proxy (#27655)
When `webhook.PROXY_URL` has been set, the old code will check if the
proxy host is in `ALLOWED_HOST_LIST` or reject requests through the
proxy. It requires users to add the proxy host to `ALLOWED_HOST_LIST`.
However, it actually allows all requests to any port on the host, when
the proxy host is probably an internal address.
But things may be even worse. `ALLOWED_HOST_LIST` doesn't really work
when requests are sent to the allowed proxy, and the proxy could forward
them to any hosts.
This PR fixes it by:
- If the proxy has been set, always allow connectioins to the host and
port.
- Check `ALLOWED_HOST_LIST` before forwarding.
Diffstat (limited to 'modules/hostmatcher')
-rw-r--r-- | modules/hostmatcher/http.go | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/modules/hostmatcher/http.go b/modules/hostmatcher/http.go index 65f5f78b14..c743f6efb3 100644 --- a/modules/hostmatcher/http.go +++ b/modules/hostmatcher/http.go @@ -7,12 +7,17 @@ import ( "context" "fmt" "net" + "net/url" "syscall" "time" ) // NewDialContext returns a DialContext for Transport, the DialContext will do allow/block list check func NewDialContext(usage string, allowList, blockList *HostMatchList) func(ctx context.Context, network, addr string) (net.Conn, error) { + return NewDialContextWithProxy(usage, allowList, blockList, nil) +} + +func NewDialContextWithProxy(usage string, allowList, blockList *HostMatchList, proxy *url.URL) func(ctx context.Context, network, addr string) (net.Conn, error) { // How Go HTTP Client works with redirection: // transport.RoundTrip URL=http://domain.com, Host=domain.com // transport.DialContext addrOrHost=domain.com:80 @@ -26,11 +31,18 @@ func NewDialContext(usage string, allowList, blockList *HostMatchList) func(ctx Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - Control: func(network, ipAddr string, c syscall.RawConn) (err error) { - var host string - if host, _, err = net.SplitHostPort(addrOrHost); err != nil { + Control: func(network, ipAddr string, c syscall.RawConn) error { + host, port, err := net.SplitHostPort(addrOrHost) + if err != nil { return err } + if proxy != nil { + // Always allow the host of the proxy, but only on the specified port. + if host == proxy.Hostname() && port == proxy.Port() { + return nil + } + } + // in Control func, the addr was already resolved to IP:PORT format, there is no cost to do ResolveTCPAddr here tcpAddr, err := net.ResolveTCPAddr(network, ipAddr) if err != nil { |