crazy multiport stuff

This commit is contained in:
JackDoan
2026-07-21 10:52:24 -05:00
parent 59ecea92ce
commit 0488793a62
19 changed files with 1801 additions and 76 deletions
+33 -1
View File
@@ -39,6 +39,13 @@ type Result struct {
HandshakeTime uint64
MessageIndex uint64 // number of messages exchanged during the handshake
Initiator bool
// Multiport lane negotiation, from the peer's LaneDetails. All zero when
// the peer did not advertise (vanilla peer or multiport disabled).
// PeerLaneIndex is nonzero only on the responder side of a lane handshake.
PeerPortCount uint32
PeerBasePort uint32
PeerLaneIndex uint32
}
// Machine drives a Noise handshake through N messages. It handles Noise
@@ -61,6 +68,7 @@ type Machine struct {
verifier CertVerifier
result *Result
msgs []msgFlags
lanes *LaneDetails // our multiport advert; nil emits a vanilla payload
myVersion cert.Version
subtype header.MessageSubType
indexAllocated bool
@@ -73,6 +81,8 @@ type Machine struct {
// the noise pattern and the per-message content layout. The credential for
// `version` is fetched via getCred and used to seed the noise.HandshakeState.
// IndexAllocator is called lazily when the first outgoing payload is built.
// lanes, when non-nil, is emitted as this side's multiport advert on every
// payload-bearing message; nil produces byte-identical vanilla payloads.
func NewMachine(
version cert.Version,
getCred GetCredentialFunc,
@@ -80,6 +90,7 @@ func NewMachine(
allocIndex IndexAllocator,
initiator bool,
subtype header.MessageSubType,
lanes *LaneDetails,
) (*Machine, error) {
info, err := subtypeInfoFor(subtype)
if err != nil {
@@ -103,6 +114,7 @@ func NewMachine(
getCred: getCred,
allocIndex: allocIndex,
verifier: verifier,
lanes: lanes,
myVersion: version,
result: &Result{
Initiator: initiator,
@@ -298,7 +310,8 @@ func (m *Machine) processPayload(msg []byte, flags msgFlags) error {
}
// Assert the payload contains exactly what we expect
hasPayloadData := payload.InitiatorIndex != 0 || payload.ResponderIndex != 0 || payload.Time != 0
hasPayloadData := payload.InitiatorIndex != 0 || payload.ResponderIndex != 0 || payload.Time != 0 ||
payload.InitiatorLanes != nil || payload.ResponderLanes != nil
if hasPayloadData != flags.expectsPayload {
m.failed = true
return ErrUnexpectedContent
@@ -327,6 +340,23 @@ func (m *Machine) processPayload(msg []byte, flags msgFlags) error {
m.result.RemoteIndex = remoteIndex
m.result.HandshakeTime = payload.Time
m.payloadSet = true
// Multiport advert from the peer's side of the exchange. Out-of-range
// values mean a peer we can't pair lanes with; ignore the advert
// rather than failing the handshake — the tunnel itself is fine, it
// just won't get lanes. Semantic policing (index bounds vs advert,
// port-count caps) belongs to the handshake manager.
var peerLanes *LaneDetails
if m.result.Initiator {
peerLanes = payload.ResponderLanes
} else {
peerLanes = payload.InitiatorLanes
}
if peerLanes != nil && peerLanes.BasePort <= 0xffff && peerLanes.PortCount <= 0xffff {
m.result.PeerPortCount = peerLanes.PortCount
m.result.PeerBasePort = peerLanes.BasePort
m.result.PeerLaneIndex = peerLanes.LaneIndex
}
}
// Process certificate
@@ -397,9 +427,11 @@ func (m *Machine) marshalOutgoing(flags msgFlags) ([]byte, error) {
if m.result.Initiator {
p.InitiatorIndex = m.result.LocalIndex
p.InitiatorLanes = m.lanes
} else {
p.ResponderIndex = m.result.LocalIndex
p.InitiatorIndex = m.result.RemoteIndex
p.ResponderLanes = m.lanes
}
p.Time = uint64(time.Now().UnixNano())
}