@@ -2,21 +2,32 @@ package http
22
33import (
44 "crypto/tls"
5+ "fmt"
56 "net"
67 "net/http"
8+ "net/url"
9+ "strings"
10+ "syscall"
711 "time"
12+
13+ furl "github.com/influxdata/flux/dependencies/url"
814)
915
1016// NewDefaultTransport creates a new transport with sane defaults.
11- func NewDefaultTransport () * http.Transport {
12- // These defaults are copied from http.DefaultTransport.
13- return & http.Transport {
14- Proxy : http .ProxyFromEnvironment ,
15- DialContext : (& net.Dialer {
17+ func NewDefaultTransport (dialer * net.Dialer ) * http.Transport {
18+
19+ if dialer == nil {
20+ dialer = & net.Dialer {
1621 Timeout : 30 * time .Second ,
1722 KeepAlive : 30 * time .Second ,
1823 DualStack : true ,
19- }).DialContext ,
24+ }
25+ }
26+
27+ // These defaults are copied from http.DefaultTransport.
28+ return & http.Transport {
29+ Proxy : http .ProxyFromEnvironment ,
30+ DialContext : (dialer ).DialContext ,
2031 MaxIdleConns : 100 ,
2132 IdleConnTimeout : 90 * time .Second ,
2233 TLSHandshakeTimeout : 10 * time .Second ,
@@ -27,8 +38,93 @@ func NewDefaultTransport() *http.Transport {
2738}
2839
2940// NewDefaultTransportWithTLS creates a new transport with the specified TLS configuration.
30- func NewDefaultTransportWithTLS (tlsConfig * tls.Config ) * http.Transport {
31- t := NewDefaultTransport ()
41+ func NewDefaultTransportWithTLS (tlsConfig * tls.Config , dialer * net. Dialer ) * http.Transport {
42+ t := NewDefaultTransport (dialer )
3243 t .TLSClientConfig = tlsConfig
3344 return t
3445}
46+
47+ // Control is called after DNS lookup, but before the network connection is
48+ // initiated.
49+ func Control (urlValidator furl.Validator ) func (network , address string , c syscall.RawConn ) error {
50+ return func (network , address string , c syscall.RawConn ) error {
51+ host , _ , err := net .SplitHostPort (address )
52+ if err != nil {
53+ return err
54+ }
55+
56+ ip := net .ParseIP (host )
57+ return urlValidator .ValidateIP (ip )
58+ }
59+ }
60+
61+ // NewDefaultClientWithTLS creates a tls client with sane defaults.
62+ func NewDefaultClientWithTLS (tlsConfig * tls.Config , urlValidator furl.Validator ) * http.Client {
63+
64+ // These defaults are copied from http.DefaultTransport.
65+ return & http.Client {
66+ Transport : NewDefaultTransportWithTLS (tlsConfig , & net.Dialer {
67+ Timeout : 30 * time .Second ,
68+ KeepAlive : 30 * time .Second ,
69+ Control : Control (urlValidator ),
70+ }),
71+ Timeout : 30 * time .Second ,
72+ }
73+ }
74+
75+ // NewDefaultClient creates a client with sane defaults.
76+ func NewDefaultClient (urlValidator furl.Validator ) * http.Client {
77+
78+ // These defaults are copied from http.DefaultTransport.
79+ return & http.Client {
80+ Transport : NewDefaultTransport (& net.Dialer {
81+ Timeout : 30 * time .Second ,
82+ KeepAlive : 30 * time .Second ,
83+ Control : Control (urlValidator ),
84+ // DualStack is deprecated
85+ }),
86+ }
87+ }
88+
89+ // DefaultValidator is the default validator, it can be replaced at start time with a different validator
90+ var DefaultValidator furl.Validator = furl.PassValidator {}
91+
92+ type cidrValidator struct {
93+ cidrs []* net.IPNet
94+ }
95+
96+ func (v cidrValidator ) Validate (u * url.URL ) error {
97+ ips , err := net .LookupIP (u .Hostname ())
98+ if err != nil {
99+ return err
100+ }
101+ for _ , ip := range ips {
102+ err = v .ValidateIP (ip )
103+ if err != nil {
104+ return err
105+ }
106+ }
107+ return nil
108+ }
109+
110+ func (v cidrValidator ) ValidateIP (ip net.IP ) error {
111+ for i := range v .cidrs {
112+ if v .cidrs [i ].Contains (ip ) {
113+ return fmt .Errorf ("ip '%s' is blacklisted" , ip )
114+ }
115+ }
116+ return nil
117+ }
118+
119+ func ParseCIDRsString (s string ) (furl.Validator , error ) {
120+ cidrStrings := strings .Split (s , "," )
121+ cidrs := make ([]* net.IPNet , 0 , len (cidrStrings ))
122+ for i := range cidrStrings {
123+ _ , cidr , err := net .ParseCIDR (cidrStrings [i ])
124+ if err != nil {
125+ return nil , err
126+ }
127+ cidrs = append (cidrs , cidr )
128+ }
129+ return cidrValidator {cidrs : cidrs }, nil
130+ }
0 commit comments