mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 21:48:43 +00:00 
			
		
		
		
	ipn/ipnserver: only permit the pre-HTTP LocalAPI protocol on Windows
Updates #6417 Change-Id: I1c9dbee3f72969f703b3ff2dbbaa145a17db868b Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
		 Brad Fitzpatrick
					Brad Fitzpatrick
				
			
				
					committed by
					
						 Brad Fitzpatrick
						Brad Fitzpatrick
					
				
			
			
				
	
			
			
			 Brad Fitzpatrick
						Brad Fitzpatrick
					
				
			
						parent
						
							033bd94d4c
						
					
				
				
					commit
					250edeb3da
				
			| @@ -165,11 +165,38 @@ func bufferIsConnect(br *bufio.Reader) bool { | ||||
| 	return mem.HasPrefix(mem.B(peek), mem.S("CONN")) | ||||
| } | ||||
| 
 | ||||
| // permitOldProtocol is whether we permit the old pre-HTTP protocol from the | ||||
| // client (cmd/tailscale or GUI client) to the tailscaled server. | ||||
| // | ||||
| // This is currently (2022-11-24) only permitted on Windows. There is an | ||||
| // outstanding change to the Windows GUI to finish the migration to the | ||||
| // HTTP-based protocol. Once it's in, this constant will go away and the old | ||||
| // protocol will not be permitted for any platform. | ||||
| const permitOldProtocol = runtime.GOOS == "windows" | ||||
| 
 | ||||
| // ipnProtoAndMethodSniffTimeout returns the read timeout to try to read a few | ||||
| // bytes from incoming IPN connection to determine whether it's an old-style | ||||
| // IPN bus connection or a new-style HTTP connection. And if an HTTP connection, | ||||
| // what its HTTP method is. | ||||
| func ipnProtoAndMethodSniffTimeout() time.Duration { | ||||
| 	if permitOldProtocol { | ||||
| 		// In the old protocol, the client might not be sending anything at all | ||||
| 		// and only receiving, so keep a short timeout as to not delay | ||||
| 		// connecting to the IPN bus and getting ipn.Notify messages. | ||||
| 		return 1 * time.Second | ||||
| 	} | ||||
| 	// But in the new protocol, there will always be an HTTP request to start, | ||||
| 	// so we can take a long time to receive the first few bytes. 30s is | ||||
| 	// overkill. | ||||
| 	return 30 * time.Second | ||||
| } | ||||
| 
 | ||||
| func (s *Server) serveConn(ctx context.Context, c net.Conn, logf logger.Logf) { | ||||
| 	// First see if it's an HTTP request. | ||||
| 	// First sniff a few bytes to see if it's an HTTP request. And if so, which | ||||
| 	// HTTP method. | ||||
| 	br := bufio.NewReader(c) | ||||
| 	c.SetReadDeadline(time.Now().Add(time.Second)) | ||||
| 	br.Peek(4) | ||||
| 	c.SetReadDeadline(time.Now().Add(ipnProtoAndMethodSniffTimeout())) | ||||
| 	br.Peek(4) // either 4 bytes old protocol length header, or HTTP "GET " etc. | ||||
| 	c.SetReadDeadline(time.Time{}) | ||||
| 
 | ||||
| 	// Handle logtail CONNECT requests early. (See docs on handleProxyConnectConn) | ||||
| @@ -178,7 +205,10 @@ func (s *Server) serveConn(ctx context.Context, c net.Conn, logf logger.Logf) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	isHTTPReq := bufferHasHTTPRequest(br) | ||||
| 	// If we don't permit the old "IPN bus" JSON bidi stream protocol, then | ||||
| 	// assume it's HTTP. Otherwise sniff the first few bytes to see if it looks | ||||
| 	// like HTTP. | ||||
| 	isHTTPReq := !permitOldProtocol || bufferHasHTTPRequest(br) | ||||
| 
 | ||||
| 	ci, err := s.addConn(c, isHTTPReq) | ||||
| 	if err != nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user