Quellcode durchsuchen

Temporary InsecureSkipVerify work-around for IP SANs issue; use http.DefaultTransport timeouts

Rod Hynes vor 11 Jahren
Ursprung
Commit
3f0dd6fd49
3 geänderte Dateien mit 36 neuen und 14 gelöschten Zeilen
  1. 11 10
      README.md
  2. 6 1
      psiphon/httpProxy.go
  3. 19 3
      psiphon/serverApi.go

+ 11 - 10
README.md

@@ -15,24 +15,22 @@ This project is currently at the proof-of-concept stage. Current production Psip
 
 ### TODO (proof-of-concept)
 
+* replace InsecureSkipVerify work-around for IP SANs issue (see serverApi.go) 
+* shutdown results in log noise: "use of closed network connection"
 * region preference
-* overlap between httpProxy.go and socksProxy.go: refactor?
 * use ContextError in more places
 * psiphon.Conn for Windows
 * build/test on Android and iOS
 * integrate meek-client
-* disconnect all local SOCKS clients when tunnel disconnected
+* disconnect all local proxy clients when tunnel disconnected
+* add connection and idle timeouts to proxied connections where appropriate
 * log levels
 
 ### TODO (future)
 
-* SSH keepalive (+ hook into disconnectedSignal)
-* SSH compression?
+* SSH keepalive
+* SSH compression
 * preemptive reconnect functionality
-* add config options
-  * protocol preference
-  * whether to try multiple protocols for each server (currently only tries one protocol per server)
-  * platform (for upgrade download)
 * implement page view stats
 * implement local traffic stats (e.g., to display bytes sent/received
 * control interface (w/ event messages)?
@@ -41,10 +39,13 @@ This project is currently at the proof-of-concept stage. Current production Psip
 * support upgrades
   * download entire client
   * download core component only
+* support protocol preference
+* try multiple protocols for each server (currently only tries one protocol per server)
 * consider ability to multiplex across multiple tunnel sessions
-* support a "pushedNetworkConfig"
-  * server can push preferred/optimized settings; client should use over defaults
+* support a config pushed by the network
+  * server can push preferred/optimized settings; client should prefer over defaults
   * e.g., etablish worker pool size; multiplex tunnel pool size
+* overlap between httpProxy.go and socksProxy.go: refactor?
 
 Licensing
 --------------------------------------------------------------------------------

+ 6 - 1
psiphon/httpProxy.go

@@ -49,12 +49,17 @@ func NewHttpProxy(tunnel *Tunnel, failureSignal chan bool) (proxy *HttpProxy, er
 	tunneledDialer := func(_, targetAddress string) (conn net.Conn, err error) {
 		return tunnel.sshClient.Dial("tcp", targetAddress)
 	}
+	// Copy default transport for its timeout values
+	transport := new(http.Transport)
+	*transport = *http.DefaultTransport.(*http.Transport)
+	transport.Dial = tunneledDialer
+	transport.Proxy = nil
 	proxy = &HttpProxy{
 		tunnel:        tunnel,
 		failureSignal: failureSignal,
 		listener:      listener,
 		waitGroup:     new(sync.WaitGroup),
-		httpRelay:     &http.Transport{Dial: tunneledDialer},
+		httpRelay:     transport,
 	}
 	proxy.waitGroup.Add(1)
 	go proxy.serveHttpRequests()

+ 19 - 3
psiphon/serverApi.go

@@ -231,8 +231,9 @@ func buildRequestUrl(session *Session, path string, extraParams ...*ExtraParam)
 	return requestUrl.String()
 }
 
-// doGetRequest makes a tunneled HTTPS request, validating the
-// server using the server entry web server certificate.
+// doGetRequest makes a tunneled HTTPS request, validating the server using the server
+// entry web server certificate. This function discards its http.Client after a single
+// use -- it is not intended for making many requests.
 func doGetRequest(session *Session, requestUrl string) (responseBody []byte, err error) {
 	proxyUrl, err := url.Parse(fmt.Sprintf("http://%s", session.localHttpProxyAddress))
 	if err != nil {
@@ -245,7 +246,22 @@ func doGetRequest(session *Session, requestUrl string) (responseBody []byte, err
 	}
 	certPool := x509.NewCertPool()
 	certPool.AddCert(certificate)
-	transport := &http.Transport{TLSClientConfig: &tls.Config{RootCAs: certPool}, Proxy: proxy}
+	// Copy default transport for its timeout values
+	transport := new(http.Transport)
+	*transport = *http.DefaultTransport.(*http.Transport)
+	// ****** SECURITY ISSUE ******
+	// TODO: temporarily using InsecureSkipVerify to work around hostname verification error:
+	// "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
+	// Notes:
+	// - Since Psiphon server self-signed certs don't have IP SANs, we need to disable that part
+	// of verification. We can't add IP SANs.
+	// - We can't easily supply a custom TLS dialer (e.g., such as https://github.com/getlantern/tlsdialer)
+	// since the dialer has to deal with HTTP proxying before talkng TLS. See:
+	// dialConn in http://golang.org/src/pkg/net/http/transport.go
+	// - Mitigating factor: the InsecureSkipVerify TLS is done through the secure, authenticated tunnel
+	// and terminates at the tunnel server host.
+	transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true, RootCAs: certPool}
+	transport.Proxy = proxy
 	httpClient := &http.Client{Transport: transport}
 	response, err := httpClient.Get(requestUrl)
 	if err != nil {