mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
259406e797
And some minor cleanup in the process. Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package derp implements DERP, the Detour Encrypted Routing Protocol.
|
|
//
|
|
// DERP routes packets to clients using curve25519 keys as addresses.
|
|
//
|
|
// DERP is used by Tailscale nodes to proxy encrypted WireGuard
|
|
// packets through the Tailscale cloud servers when a direct path
|
|
// cannot be found or opened. DERP is a last resort. Both sides
|
|
// between very aggressive NATs, firewalls, no IPv6, etc? Well, DERP.
|
|
package derp
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// magic is the derp magic number, sent on the wire as a uint32.
|
|
// It's "DERP" with a non-ASCII high-bit.
|
|
const magic = 0x44c55250
|
|
|
|
// frameType is the one byte frame type header in frame headers.
|
|
type frameType byte
|
|
|
|
const (
|
|
typeServerKey = frameType(0x01)
|
|
typeServerInfo = frameType(0x02)
|
|
typeSendPacket = frameType(0x03)
|
|
typeRecvPacket = frameType(0x04)
|
|
typeKeepAlive = frameType(0x05)
|
|
)
|
|
|
|
func (b frameType) Write(w io.ByteWriter) error {
|
|
return w.WriteByte(byte(b))
|
|
}
|
|
|
|
const keepAlive = 60 * time.Second
|
|
|
|
var bin = binary.BigEndian
|
|
|
|
const oneMB = 1 << 20
|
|
|
|
func readType(r *bufio.Reader, t frameType) error {
|
|
packetType, err := r.ReadByte()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if frameType(packetType) != t {
|
|
return fmt.Errorf("bad packet type 0x%X, want 0x%X", packetType, t)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func putUint32(w io.Writer, v uint32) error {
|
|
var b [4]byte
|
|
bin.PutUint32(b[:], v)
|
|
_, err := w.Write(b[:])
|
|
return err
|
|
}
|
|
|
|
func readUint32(r io.Reader, maxVal uint32) (uint32, error) {
|
|
b := make([]byte, 4)
|
|
if _, err := io.ReadFull(r, b); err != nil {
|
|
return 0, err
|
|
}
|
|
val := bin.Uint32(b)
|
|
if val > maxVal {
|
|
return 0, fmt.Errorf("uint32 %d exceeds limit %d", val, maxVal)
|
|
}
|
|
return val, nil
|
|
}
|