WIP: rebase fork onto upstream/main (v1.103.0) #15

Closed
codinget wants to merge 670 commits from webnet into save/webnet-2026-07-29
3 changed files with 36 additions and 1 deletions
Showing only changes of commit 15a70243ed - Show all commits
+7
View File
@@ -1763,6 +1763,13 @@ func (b *LocalBackend) PeerCaps(src netip.Addr) tailcfg.PeerCapMap {
return b.currentNode().PeerCaps(src)
}
// PeerCapsIncludingUnsigned is like [LocalBackend.PeerCaps] but does not deny
// capabilities to peers with UnsignedPeerAPIOnly set. It exists only for the
// Funnel ingress path; see [nodeBackend.PeerCapsIncludingUnsigned].
func (b *LocalBackend) PeerCapsIncludingUnsigned(src netip.Addr) tailcfg.PeerCapMap {
return b.currentNode().PeerCapsIncludingUnsigned(src)
}
// PeerCapsForIP returns the capabilities that remote src IP has when
// talking to the given destination IP on this node.
func (b *LocalBackend) PeerCapsForIP(src, dst netip.Addr) tailcfg.PeerCapMap {
+22
View File
@@ -432,10 +432,32 @@ func (nb *nodeBackend) srcIsUnsignedPeerLocked(src netip.Addr) bool {
return ok && n.UnsignedPeerAPIOnly()
}
// PeerCapsIncludingUnsigned is like [nodeBackend.PeerCaps] but does not deny
// capabilities to peers with UnsignedPeerAPIOnly set.
//
// Funnel ingress relays are delivered as UnsignedPeerAPIOnly nodes: per the
// docs on [tailcfg.Node.UnsignedPeerAPIOnly] they get no network access at all
// and exist solely to reach this node's peerapi. The ingress endpoint they need
// is gated on [tailcfg.PeerCapabilityIngress], so denying them capabilities
// wholesale — as peerCapsLocked does upstream as of 0eb38dc2e — makes Funnel
// impossible. Callers must therefore be limited to the ingress path.
//
// This is a fork-local patch; drop it once upstream restores Funnel.
// See webnet/tailscale#16.
func (nb *nodeBackend) PeerCapsIncludingUnsigned(src netip.Addr) tailcfg.PeerCapMap {
nb.mu.Lock()
defer nb.mu.Unlock()
return nb.peerCapsIgnoringSignatureLocked(src)
}
func (nb *nodeBackend) peerCapsLocked(src netip.Addr) tailcfg.PeerCapMap {
if nb.srcIsUnsignedPeerLocked(src) {
return nil
}
return nb.peerCapsIgnoringSignatureLocked(src)
}
func (nb *nodeBackend) peerCapsIgnoringSignatureLocked(src netip.Addr) tailcfg.PeerCapMap {
if nb.netMap == nil {
return nil
}
+7 -1
View File
@@ -592,8 +592,14 @@ func (h *peerAPIHandler) canDebug() bool {
var allowSelfIngress = envknob.RegisterBool("TS_ALLOW_SELF_INGRESS")
// canIngress reports whether h can send ingress requests to this node.
//
// The ingress cap is resolved without the unsigned-peer denial that
// [nodeBackend.PeerCaps] applies, because Funnel ingress relays are by design
// UnsignedPeerAPIOnly nodes whose only permitted action is this endpoint.
// See [nodeBackend.PeerCapsIncludingUnsigned].
func (h *peerAPIHandler) canIngress() bool {
return h.peerHasCap(tailcfg.PeerCapabilityIngress) || (allowSelfIngress() && h.isSelf)
caps := h.ps.b.PeerCapsIncludingUnsigned(h.remoteAddr.Addr())
return caps.HasCapability(tailcfg.PeerCapabilityIngress) || (allowSelfIngress() && h.isSelf)
}
func (h *peerAPIHandler) peerHasCap(wantCap tailcfg.PeerCapability) bool {