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  }