github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/services/httpservice/client.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package httpservice 5 6 import ( 7 "context" 8 "crypto/tls" 9 "errors" 10 "net" 11 "net/http" 12 "time" 13 ) 14 15 const ( 16 ConnectTimeout = 3 * time.Second 17 RequestTimeout = 30 * time.Second 18 ) 19 20 var reservedIPRanges []*net.IPNet 21 22 // IsReservedIP checks whether the target IP belongs to reserved IP address ranges to avoid SSRF attacks to the internal 23 // network of the HungKnow server 24 func IsReservedIP(ip net.IP) bool { 25 for _, ipRange := range reservedIPRanges { 26 if ipRange.Contains(ip) { 27 return true 28 } 29 } 30 return false 31 } 32 33 // IsOwnIP handles the special case that a request might be made to the public IP of the host which on Linux is routed 34 // directly via the loopback IP to any listening sockets, effectively bypassing host-based firewalls such as firewalld 35 func IsOwnIP(ip net.IP) (bool, error) { 36 interfaces, err := net.Interfaces() 37 if err != nil { 38 return false, err 39 } 40 41 for _, interf := range interfaces { 42 addresses, err := interf.Addrs() 43 if err != nil { 44 return false, err 45 } 46 47 for _, addr := range addresses { 48 var selfIP net.IP 49 switch v := addr.(type) { 50 case *net.IPNet: 51 selfIP = v.IP 52 case *net.IPAddr: 53 selfIP = v.IP 54 } 55 56 if ip.Equal(selfIP) { 57 return true, nil 58 } 59 } 60 } 61 62 return false, nil 63 } 64 65 var defaultUserAgent string 66 67 func init() { 68 for _, cidr := range []string{ 69 // See https://tools.ietf.org/html/rfc6890 70 "0.0.0.0/8", // This host on this network 71 "10.0.0.0/8", // Private-Use 72 "127.0.0.0/8", // Loopback 73 "169.254.0.0/16", // Link Local 74 "172.16.0.0/12", // Private-Use Networks 75 "192.168.0.0/16", // Private-Use Networks 76 "::/128", // Unspecified Address 77 "::1/128", // Loopback Address 78 "fc00::/7", // Unique-Local 79 "fe80::/10", // Linked-Scoped Unicast 80 } { 81 _, parsed, err := net.ParseCIDR(cidr) 82 if err != nil { 83 panic(err) 84 } 85 reservedIPRanges = append(reservedIPRanges, parsed) 86 } 87 defaultUserAgent = "Mattermost-Bot/1.1" 88 } 89 90 type DialContextFunction func(ctx context.Context, network, addr string) (net.Conn, error) 91 92 var AddressForbidden error = errors.New("address forbidden, you may need to set AllowedUntrustedInternalConnections to allow an integration access to your internal network") 93 94 func dialContextFilter(dial DialContextFunction, allowHost func(host string) bool, allowIP func(ip net.IP) bool) DialContextFunction { 95 return func(ctx context.Context, network, addr string) (net.Conn, error) { 96 host, port, err := net.SplitHostPort(addr) 97 if err != nil { 98 return nil, err 99 } 100 101 if allowHost != nil && allowHost(host) { 102 return dial(ctx, network, addr) 103 } 104 105 ips, err := net.LookupIP(host) 106 if err != nil { 107 return nil, err 108 } 109 110 var firstErr error 111 for _, ip := range ips { 112 select { 113 case <-ctx.Done(): 114 return nil, ctx.Err() 115 default: 116 } 117 118 if allowIP == nil || !allowIP(ip) { 119 continue 120 } 121 122 conn, err := dial(ctx, network, net.JoinHostPort(ip.String(), port)) 123 if err == nil { 124 return conn, nil 125 } 126 if firstErr == nil { 127 firstErr = err 128 } 129 } 130 if firstErr == nil { 131 return nil, AddressForbidden 132 } 133 return nil, firstErr 134 } 135 } 136 137 func NewTransport(enableInsecureConnections bool, allowHost func(host string) bool, allowIP func(ip net.IP) bool) *MattermostTransport { 138 dialContext := (&net.Dialer{ 139 Timeout: ConnectTimeout, 140 KeepAlive: 30 * time.Second, 141 }).DialContext 142 143 if allowHost != nil || allowIP != nil { 144 dialContext = dialContextFilter(dialContext, allowHost, allowIP) 145 } 146 147 return &MattermostTransport{ 148 &http.Transport{ 149 Proxy: http.ProxyFromEnvironment, 150 DialContext: dialContext, 151 MaxIdleConns: 100, 152 IdleConnTimeout: 90 * time.Second, 153 TLSHandshakeTimeout: ConnectTimeout, 154 ExpectContinueTimeout: 1 * time.Second, 155 TLSClientConfig: &tls.Config{ 156 InsecureSkipVerify: enableInsecureConnections, 157 }, 158 }, 159 } 160 }