Răsfoiți Sursa

Ignore unexpected host_bytes from legacy clients

Rod Hynes 8 ani în urmă
părinte
comite
3d1c78bc2c
2 a modificat fișierele cu 50 adăugiri și 10 ștergeri
  1. 20 10
      psiphon/server/api.go
  2. 30 0
      psiphon/server/tunnelServer.go

+ 20 - 10
psiphon/server/api.go

@@ -209,6 +209,11 @@ func handshakeAPIRequestHandler(
 		}
 		}
 	}
 	}
 
 
+	// Note: no guarantee that PsinetDatabase won't reload between database calls
+	db := support.PsinetDatabase
+
+	httpsRequestRegexes := db.GetHttpsRequestRegexes(sponsorID)
+
 	// Flag the SSH client as having completed its handshake. This
 	// Flag the SSH client as having completed its handshake. This
 	// may reselect traffic rules and starts allowing port forwards.
 	// may reselect traffic rules and starts allowing port forwards.
 
 
@@ -218,9 +223,10 @@ func handshakeAPIRequestHandler(
 	activeAuthorizationIDs, authorizedAccessTypes, err := support.TunnelServer.SetClientHandshakeState(
 	activeAuthorizationIDs, authorizedAccessTypes, err := support.TunnelServer.SetClientHandshakeState(
 		sessionID,
 		sessionID,
 		handshakeState{
 		handshakeState{
-			completed:   true,
-			apiProtocol: apiProtocol,
-			apiParams:   copyBaseRequestParams(params),
+			completed:         true,
+			apiProtocol:       apiProtocol,
+			apiParams:         copyBaseRequestParams(params),
+			expectDomainBytes: len(httpsRequestRegexes) > 0,
 		},
 		},
 		authorizations)
 		authorizations)
 	if err != nil {
 	if err != nil {
@@ -241,14 +247,12 @@ func handshakeAPIRequestHandler(
 			params,
 			params,
 			baseRequestParams)).Info("handshake")
 			baseRequestParams)).Info("handshake")
 
 
-	// Note: no guarantee that PsinetDatabase won't reload between database calls
-	db := support.PsinetDatabase
 	handshakeResponse := protocol.HandshakeResponse{
 	handshakeResponse := protocol.HandshakeResponse{
 		SSHSessionID:           sessionID,
 		SSHSessionID:           sessionID,
 		Homepages:              db.GetRandomizedHomepages(sponsorID, geoIPData.Country, isMobile),
 		Homepages:              db.GetRandomizedHomepages(sponsorID, geoIPData.Country, isMobile),
 		UpgradeClientVersion:   db.GetUpgradeClientVersion(clientVersion, normalizedPlatform),
 		UpgradeClientVersion:   db.GetUpgradeClientVersion(clientVersion, normalizedPlatform),
 		PageViewRegexes:        make([]map[string]string, 0),
 		PageViewRegexes:        make([]map[string]string, 0),
-		HttpsRequestRegexes:    db.GetHttpsRequestRegexes(sponsorID),
+		HttpsRequestRegexes:    httpsRequestRegexes,
 		EncodedServerList:      db.DiscoverServers(geoIPData.DiscoveryValue),
 		EncodedServerList:      db.DiscoverServers(geoIPData.DiscoveryValue),
 		ClientRegion:           geoIPData.Country,
 		ClientRegion:           geoIPData.Country,
 		ServerTimestamp:        common.GetCurrentTimestamp(),
 		ServerTimestamp:        common.GetCurrentTimestamp(),
@@ -329,6 +333,8 @@ func statusAPIRequestHandler(
 		return nil, common.ContextError(err)
 		return nil, common.ContextError(err)
 	}
 	}
 
 
+	sessionID, _ := getStringRequestParam(params, "client_session_id")
+
 	statusData, err := getJSONObjectRequestParam(params, "statusData")
 	statusData, err := getJSONObjectRequestParam(params, "statusData")
 	if err != nil {
 	if err != nil {
 		return nil, common.ContextError(err)
 		return nil, common.ContextError(err)
@@ -344,11 +350,15 @@ func statusAPIRequestHandler(
 	// Domain bytes transferred stats
 	// Domain bytes transferred stats
 	// Older clients may not submit this data
 	// Older clients may not submit this data
 
 
-	// TODO: ignore these stats if regexes for client were empty; in this
-	// case, clients are expected to send no host_bytes, but older clients
-	// may still send.
+	// Clients are expected to send host_bytes/domain_bytes stats only when
+	// configured to do so in the handshake reponse. Legacy clients may still
+	// report "(OTHER)" host_bytes when no regexes are set. Drop those stats.
+	domainBytesExpected, err := support.TunnelServer.ExpectClientDomainBytes(sessionID)
+	if err != nil {
+		return nil, common.ContextError(err)
+	}
 
 
-	if statusData["host_bytes"] != nil {
+	if domainBytesExpected && statusData["host_bytes"] != nil {
 
 
 		hostBytes, err := getMapStringInt64RequestParam(statusData, "host_bytes")
 		hostBytes, err := getMapStringInt64RequestParam(statusData, "host_bytes")
 		if err != nil {
 		if err != nil {

+ 30 - 0
psiphon/server/tunnelServer.go

@@ -246,6 +246,14 @@ func (server *TunnelServer) GetClientHandshaked(
 	return server.sshServer.getClientHandshaked(sessionID)
 	return server.sshServer.getClientHandshaked(sessionID)
 }
 }
 
 
+// ExpectClientDomainBytes indicates whether the client was configured to report
+// domain bytes in its handshake response.
+func (server *TunnelServer) ExpectClientDomainBytes(
+	sessionID string) (bool, error) {
+
+	return server.sshServer.expectClientDomainBytes(sessionID)
+}
+
 // SetEstablishTunnels sets whether new tunnels may be established or not.
 // SetEstablishTunnels sets whether new tunnels may be established or not.
 // When not establishing, incoming connections are immediately closed.
 // When not establishing, incoming connections are immediately closed.
 func (server *TunnelServer) SetEstablishTunnels(establish bool) {
 func (server *TunnelServer) SetEstablishTunnels(establish bool) {
@@ -718,6 +726,20 @@ func (sshServer *sshServer) getClientHandshaked(
 	return completed, exhausted, nil
 	return completed, exhausted, nil
 }
 }
 
 
+func (sshServer *sshServer) expectClientDomainBytes(
+	sessionID string) (bool, error) {
+
+	sshServer.clientsMutex.Lock()
+	client := sshServer.clients[sessionID]
+	sshServer.clientsMutex.Unlock()
+
+	if client == nil {
+		return false, common.ContextError(errors.New("unknown session ID"))
+	}
+
+	return client.expectDomainBytes(), nil
+}
+
 func (sshServer *sshServer) stopClients() {
 func (sshServer *sshServer) stopClients() {
 
 
 	sshServer.clientsMutex.Lock()
 	sshServer.clientsMutex.Lock()
@@ -875,6 +897,7 @@ type handshakeState struct {
 	apiProtocol           string
 	apiProtocol           string
 	apiParams             requestJSONObject
 	apiParams             requestJSONObject
 	authorizedAccessTypes []string
 	authorizedAccessTypes []string
+	expectDomainBytes     bool
 }
 }
 
 
 func newSshClient(
 func newSshClient(
@@ -1874,6 +1897,13 @@ func (sshClient *sshClient) getHandshaked() (bool, bool) {
 	return completed, exhausted
 	return completed, exhausted
 }
 }
 
 
+func (sshClient *sshClient) expectDomainBytes() bool {
+	sshClient.Lock()
+	defer sshClient.Unlock()
+
+	return sshClient.handshakeState.expectDomainBytes
+}
+
 // setTrafficRules resets the client's traffic rules based on the latest server config
 // setTrafficRules resets the client's traffic rules based on the latest server config
 // and client properties. As sshClient.trafficRules may be reset by a concurrent
 // and client properties. As sshClient.trafficRules may be reset by a concurrent
 // goroutine, trafficRules must only be accessed within the sshClient mutex.
 // goroutine, trafficRules must only be accessed within the sshClient mutex.