mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
control/controlbase: don't enforce a max protocol version at handshake time.
Doing so makes development unpleasant, because we have to first break the client by bumping to a version the control server rejects, then upgrade the control server to make it accept the new version. This strict rejection at handshake time is only necessary if we want to blocklist some vulnerable protocol versions in the future. So, switch to a default-permissive stance: until we have such a version that we have to eagerly block early, we'll accept whatever version the client presents, and leave it to the user of controlbase.Conn to make decisions based on that version. Noise still enforces that the client and server *agree* on what protocol version is being used, and the control server still has the option to finish the handshake and then hang up with an in-noise error, rather than abort at the handshake level. Updates #3488 Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:

committed by
Dave Anderson

parent
c6ac29bcc4
commit
f570372b4d
@@ -193,19 +193,13 @@ func continueClientHandshake(ctx context.Context, conn net.Conn, s *symmetricSta
|
||||
// Server initiates a control server handshake, returning the resulting
|
||||
// control connection.
|
||||
//
|
||||
// maxSupportedVersion is the highest handshake version the server is
|
||||
// willing to handshake with. The server will handshake with any
|
||||
// version from 0 to maxSupportedVersion inclusive, the caller should
|
||||
// inspect conn.Version() to determine what version of the handshake
|
||||
// was executed.
|
||||
//
|
||||
// optionalInit can be the client's initial handshake message as
|
||||
// returned by ClientDeferred, or nil in which case the initial
|
||||
// message is read from conn.
|
||||
//
|
||||
// The context deadline, if any, covers the entire handshaking
|
||||
// process.
|
||||
func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, maxSupportedVersion uint16, optionalInit []byte) (*Conn, error) {
|
||||
func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, optionalInit []byte) (*Conn, error) {
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
if err := conn.SetDeadline(deadline); err != nil {
|
||||
return nil, fmt.Errorf("setting conn deadline: %w", err)
|
||||
@@ -245,15 +239,11 @@ func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, m
|
||||
} else if _, err := io.ReadFull(conn, init.Header()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Currently, these versions exclusively indicate what the upper
|
||||
// RPC protocol understands, the Noise handshake is exactly the
|
||||
// same in all versions. If that ever changes, this check will
|
||||
// need to become more complex to handle different kinds of
|
||||
// handshake.
|
||||
if init.Version() > maxSupportedVersion {
|
||||
return nil, sendErr("unsupported handshake version")
|
||||
}
|
||||
// Just a rename to make it more obvious what the value is
|
||||
// Just a rename to make it more obvious what the value is. In the
|
||||
// current implementation we don't need to block any protocol
|
||||
// versions at this layer, it's safe to let the handshake proceed
|
||||
// and then let the caller make decisions based on the agreed-upon
|
||||
// protocol version.
|
||||
clientVersion := init.Version()
|
||||
if init.Type() != msgTypeInitiation {
|
||||
return nil, sendErr("unexpected handshake message type")
|
||||
|
Reference in New Issue
Block a user