mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-21 14:11:56 +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:
parent
033bd94d4c
commit
250edeb3da
@ -165,11 +165,38 @@ func bufferIsConnect(br *bufio.Reader) bool {
|
|||||||
return mem.HasPrefix(mem.B(peek), mem.S("CONN"))
|
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) {
|
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)
|
br := bufio.NewReader(c)
|
||||||
c.SetReadDeadline(time.Now().Add(time.Second))
|
c.SetReadDeadline(time.Now().Add(ipnProtoAndMethodSniffTimeout()))
|
||||||
br.Peek(4)
|
br.Peek(4) // either 4 bytes old protocol length header, or HTTP "GET " etc.
|
||||||
c.SetReadDeadline(time.Time{})
|
c.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
// Handle logtail CONNECT requests early. (See docs on handleProxyConnectConn)
|
// 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
|
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)
|
ci, err := s.addConn(c, isHTTPReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user