code.gitea.io/gitea@v1.19.3/modules/hostmatcher/http.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package hostmatcher 5 6 import ( 7 "context" 8 "fmt" 9 "net" 10 "syscall" 11 "time" 12 ) 13 14 // NewDialContext returns a DialContext for Transport, the DialContext will do allow/block list check 15 func NewDialContext(usage string, allowList, blockList *HostMatchList) func(ctx context.Context, network, addr string) (net.Conn, error) { 16 // How Go HTTP Client works with redirection: 17 // transport.RoundTrip URL=http://domain.com, Host=domain.com 18 // transport.DialContext addrOrHost=domain.com:80 19 // dialer.Control tcp4:11.22.33.44:80 20 // transport.RoundTrip URL=http://www.domain.com/, Host=(empty here, in the direction, HTTP client doesn't fill the Host field) 21 // transport.DialContext addrOrHost=domain.com:80 22 // dialer.Control tcp4:11.22.33.44:80 23 return func(ctx context.Context, network, addrOrHost string) (net.Conn, error) { 24 dialer := net.Dialer{ 25 // default values comes from http.DefaultTransport 26 Timeout: 30 * time.Second, 27 KeepAlive: 30 * time.Second, 28 29 Control: func(network, ipAddr string, c syscall.RawConn) (err error) { 30 var host string 31 if host, _, err = net.SplitHostPort(addrOrHost); err != nil { 32 return err 33 } 34 // in Control func, the addr was already resolved to IP:PORT format, there is no cost to do ResolveTCPAddr here 35 tcpAddr, err := net.ResolveTCPAddr(network, ipAddr) 36 if err != nil { 37 return fmt.Errorf("%s can only call HTTP servers via TCP, deny '%s(%s:%s)', err=%w", usage, host, network, ipAddr, err) 38 } 39 40 var blockedError error 41 if blockList.MatchHostOrIP(host, tcpAddr.IP) { 42 blockedError = fmt.Errorf("%s can not call blocked HTTP servers (check your %s setting), deny '%s(%s)'", usage, blockList.SettingKeyHint, host, ipAddr) 43 } 44 45 // if we have an allow-list, check the allow-list first 46 if !allowList.IsEmpty() { 47 if !allowList.MatchHostOrIP(host, tcpAddr.IP) { 48 return fmt.Errorf("%s can only call allowed HTTP servers (check your %s setting), deny '%s(%s)'", usage, allowList.SettingKeyHint, host, ipAddr) 49 } 50 } 51 // otherwise, we always follow the blocked list 52 return blockedError 53 }, 54 } 55 return dialer.DialContext(ctx, network, addrOrHost) 56 } 57 }