github.com/jfrerich/mattermost-server@v5.8.0-rc2+incompatible/services/httpservice/client.go (about) 1 // Copyright (c) 2017-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 "github.com/mattermost/mattermost-server/model" 15 ) 16 17 const ( 18 ConnectTimeout = 3 * time.Second 19 RequestTimeout = 30 * time.Second 20 ) 21 22 var reservedIPRanges []*net.IPNet 23 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 var defaultUserAgent string 34 35 func init() { 36 for _, cidr := range []string{ 37 // See https://tools.ietf.org/html/rfc6890 38 "0.0.0.0/8", // This host on this network 39 "10.0.0.0/8", // Private-Use 40 "127.0.0.0/8", // Loopback 41 "169.254.0.0/16", // Link Local 42 "172.16.0.0/12", // Private-Use Networks 43 "192.168.0.0/16", // Private-Use Networks 44 "::/128", // Unspecified Address 45 "::1/128", // Loopback Address 46 "fc00::/7", // Unique-Local 47 "fe80::/10", // Linked-Scoped Unicast 48 } { 49 _, parsed, err := net.ParseCIDR(cidr) 50 if err != nil { 51 panic(err) 52 } 53 reservedIPRanges = append(reservedIPRanges, parsed) 54 } 55 defaultUserAgent = "mattermost-" + model.CurrentVersion 56 } 57 58 type DialContextFunction func(ctx context.Context, network, addr string) (net.Conn, error) 59 60 var AddressForbidden error = errors.New("address forbidden, you may need to set AllowedUntrustedInternalConnections to allow an integration access to your internal network") 61 62 func dialContextFilter(dial DialContextFunction, allowHost func(host string) bool, allowIP func(ip net.IP) bool) DialContextFunction { 63 return func(ctx context.Context, network, addr string) (net.Conn, error) { 64 host, port, err := net.SplitHostPort(addr) 65 if err != nil { 66 return nil, err 67 } 68 69 if allowHost != nil && allowHost(host) { 70 return dial(ctx, network, addr) 71 } 72 73 ips, err := net.LookupIP(host) 74 if err != nil { 75 return nil, err 76 } 77 78 var firstErr error 79 for _, ip := range ips { 80 select { 81 case <-ctx.Done(): 82 return nil, ctx.Err() 83 default: 84 } 85 86 if allowIP == nil || !allowIP(ip) { 87 continue 88 } 89 90 conn, err := dial(ctx, network, net.JoinHostPort(ip.String(), port)) 91 if err == nil { 92 return conn, nil 93 } 94 if firstErr == nil { 95 firstErr = err 96 } 97 } 98 if firstErr == nil { 99 return nil, AddressForbidden 100 } 101 return nil, firstErr 102 } 103 } 104 105 func NewTransport(enableInsecureConnections bool, allowHost func(host string) bool, allowIP func(ip net.IP) bool) http.RoundTripper { 106 dialContext := (&net.Dialer{ 107 Timeout: ConnectTimeout, 108 KeepAlive: 30 * time.Second, 109 }).DialContext 110 111 if allowHost != nil || allowIP != nil { 112 dialContext = dialContextFilter(dialContext, allowHost, allowIP) 113 } 114 115 return &MattermostTransport{ 116 &http.Transport{ 117 Proxy: http.ProxyFromEnvironment, 118 DialContext: dialContext, 119 MaxIdleConns: 100, 120 IdleConnTimeout: 90 * time.Second, 121 TLSHandshakeTimeout: ConnectTimeout, 122 ExpectContinueTimeout: 1 * time.Second, 123 TLSClientConfig: &tls.Config{ 124 InsecureSkipVerify: enableInsecureConnections, 125 }, 126 }, 127 } 128 }