Apply Tailscale endpoint awareness
This commit is contained in:
parent
749db0015c
commit
414291f6d6
3 changed files with 45 additions and 2 deletions
34
conn/conn.go
34
conn/conn.go
|
|
@ -86,6 +86,40 @@ type Endpoint interface {
|
||||||
SrcIP() netip.Addr
|
SrcIP() netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitiationAwareEndpoint is an optional [Endpoint] specialization for
|
||||||
|
// integrations that want to know when a WireGuard handshake initiation
|
||||||
|
// message has been received, enabling just-in-time peer configuration before
|
||||||
|
// attempted decryption.
|
||||||
|
//
|
||||||
|
// It's most useful when used in combination with [PeerAwareEndpoint], enabling
|
||||||
|
// JIT peer configuration and post-decryption peer verification from a single
|
||||||
|
// implementer.
|
||||||
|
type InitiationAwareEndpoint interface {
|
||||||
|
// InitiationMessagePublicKey is called when a handshake initiation message
|
||||||
|
// has been received, and the sender's public key has been identified, but
|
||||||
|
// BEFORE an attempt has been made to verify it.
|
||||||
|
InitiationMessagePublicKey(peerPublicKey [32]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerAwareEndpoint is an optional Endpoint specialization for
|
||||||
|
// integrations that want to know about the outcome of Cryptokey Routing
|
||||||
|
// identification.
|
||||||
|
//
|
||||||
|
// If they receive a packet from a source they had not pre-identified,
|
||||||
|
// to learn the identification WireGuard can derive from the session
|
||||||
|
// or handshake.
|
||||||
|
//
|
||||||
|
// A [PeerAwareEndpoint] may be installed as the [conn.Endpoint] following
|
||||||
|
// successful decryption unless endpoint roaming has been disabled for
|
||||||
|
// the peer.
|
||||||
|
type PeerAwareEndpoint interface {
|
||||||
|
// FromPeer is called at least once per successfully Cryptokey Routing ID'd
|
||||||
|
// [ReceiveFunc] packets batch for a given node key. wireguard-go will
|
||||||
|
// always call it for the latest/tail packet in the batch, only ever
|
||||||
|
// suppressing calls for older packets.
|
||||||
|
FromPeer(peerPublicKey [32]byte)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrBindAlreadyOpen = errors.New("bind is already open")
|
ErrBindAlreadyOpen = errors.New("bind is already open")
|
||||||
ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type")
|
ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type")
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/wireguard-go/conn"
|
||||||
"github.com/sagernet/wireguard-go/tai64n"
|
"github.com/sagernet/wireguard-go/tai64n"
|
||||||
"golang.org/x/crypto/blake2s"
|
"golang.org/x/crypto/blake2s"
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
|
@ -337,7 +338,7 @@ func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, e
|
||||||
return &msg, nil
|
return &msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation, endpoint conn.Endpoint) *Peer {
|
||||||
var (
|
var (
|
||||||
hash [blake2s.Size]byte
|
hash [blake2s.Size]byte
|
||||||
chainKey [blake2s.Size]byte
|
chainKey [blake2s.Size]byte
|
||||||
|
|
@ -371,6 +372,11 @@ func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
||||||
|
|
||||||
// lookup peer
|
// lookup peer
|
||||||
|
|
||||||
|
initEP, ok := endpoint.(conn.InitiationAwareEndpoint)
|
||||||
|
if ok {
|
||||||
|
initEP.InitiationMessagePublicKey(peerPK)
|
||||||
|
}
|
||||||
|
|
||||||
peer := device.LookupPeer(peerPK)
|
peer := device.LookupPeer(peerPK)
|
||||||
if peer == nil || !peer.isRunning.Load() {
|
if peer == nil || !peer.isRunning.Load() {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
|
|
||||||
// consume initiation
|
// consume initiation
|
||||||
|
|
||||||
peer := device.ConsumeMessageInitiation(&msg)
|
peer := device.ConsumeMessageInitiation(&msg, elem.endpoint)
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
device.log.Verbosef("Received invalid initiation message from %s", elem.endpoint.DstToString())
|
device.log.Verbosef("Received invalid initiation message from %s", elem.endpoint.DstToString())
|
||||||
goto skip
|
goto skip
|
||||||
|
|
@ -459,6 +459,9 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||||
peer.timersHandshakeComplete()
|
peer.timersHandshakeComplete()
|
||||||
peer.SendStagedPackets()
|
peer.SendStagedPackets()
|
||||||
}
|
}
|
||||||
|
if ep, ok := elem.endpoint.(conn.PeerAwareEndpoint); ok {
|
||||||
|
ep.FromPeer(peer.handshake.remoteStatic)
|
||||||
|
}
|
||||||
rxBytesLen += uint64(len(elem.packet) + MinMessageSize)
|
rxBytesLen += uint64(len(elem.packet) + MinMessageSize)
|
||||||
|
|
||||||
if len(elem.packet) == 0 {
|
if len(elem.packet) == 0 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue