@@ -741,6 +741,26 @@ func (d *Daemon) handleStreamPacket(pkt *protocol.Packet) {
741741 return
742742 }
743743
744+ // Trust gate: private nodes only accept SYN from trusted or same-network peers.
745+ // Runs before rate limiting so untrusted sources cannot waste rate-limit tokens.
746+ if ! d .config .Public {
747+ srcNode := pkt .Src .Node
748+ trusted := d .handshakes .IsTrusted (srcNode )
749+ if ! trusted && d .regConn != nil {
750+ // Fall back to registry trust check (covers admin-set trust pairs + shared networks)
751+ trusted , _ = d .regConn .CheckTrust (d .NodeID (), srcNode )
752+ }
753+ if ! trusted {
754+ slog .Warn ("SYN rejected: untrusted source" , "src_node" , srcNode , "src_addr" , pkt .Src , "dst_port" , pkt .DstPort )
755+ d .webhook .Emit ("syn.rejected" , map [string ]interface {}{
756+ "src_node_id" : srcNode ,
757+ "src_addr" : pkt .Src .String (),
758+ "dst_port" : pkt .DstPort ,
759+ })
760+ return // silent drop — no RST to avoid leaking node existence
761+ }
762+ }
763+
744764 // SYN rate limiting
745765 if ! d .allowSYN () {
746766 slog .Warn ("SYN rate limit exceeded" , "src_addr" , pkt .Src , "src_port" , pkt .SrcPort )
@@ -768,26 +788,6 @@ func (d *Daemon) handleStreamPacket(pkt *protocol.Packet) {
768788 return
769789 }
770790
771- // Trust gate: private nodes only accept SYN from trusted or same-network peers
772- if ! d .config .Public {
773- srcNode := pkt .Src .Node
774- trusted := d .handshakes .IsTrusted (srcNode )
775- if ! trusted && d .regConn != nil {
776- // Fall back to registry trust check (covers admin-set trust pairs + shared networks)
777- trusted , _ = d .regConn .CheckTrust (d .NodeID (), srcNode )
778- }
779- if ! trusted {
780- slog .Warn ("SYN rejected: untrusted source" , "src_node" , srcNode , "src_addr" , pkt .Src , "dst_port" , pkt .DstPort )
781- d .webhook .Emit ("syn.rejected" , map [string ]interface {}{
782- "src_node_id" : srcNode ,
783- "src_addr" : pkt .Src .String (),
784- "dst_port" : pkt .DstPort ,
785- })
786- d .sendRST (pkt )
787- return
788- }
789- }
790-
791791 conn := d .ports .NewConnection (pkt .DstPort , pkt .Src , pkt .SrcPort )
792792 conn .Mu .Lock ()
793793 conn .LocalAddr = d .Addr ()
@@ -1056,13 +1056,33 @@ func (d *Daemon) sendDelayedACK(conn *Connection) {
10561056}
10571057
10581058func (d * Daemon ) handleDatagramPacket (pkt * protocol.Packet ) {
1059- if len (pkt .Payload ) > 0 {
1060- d .webhook .Emit ("data.datagram" , map [string ]interface {}{
1061- "src_addr" : pkt .Src .String (), "src_port" : pkt .SrcPort ,
1062- "dst_port" : pkt .DstPort , "size" : len (pkt .Payload ),
1063- })
1064- d .ipc .DeliverDatagram (pkt .Src , pkt .SrcPort , pkt .DstPort , pkt .Payload )
1059+ if len (pkt .Payload ) == 0 {
1060+ return
10651061 }
1062+
1063+ // Trust gate: private nodes only accept datagrams from trusted or same-network peers
1064+ if ! d .config .Public {
1065+ srcNode := pkt .Src .Node
1066+ trusted := d .handshakes .IsTrusted (srcNode )
1067+ if ! trusted && d .regConn != nil {
1068+ trusted , _ = d .regConn .CheckTrust (d .NodeID (), srcNode )
1069+ }
1070+ if ! trusted {
1071+ slog .Warn ("datagram rejected: untrusted source" , "src_node" , srcNode , "src_addr" , pkt .Src , "dst_port" , pkt .DstPort )
1072+ d .webhook .Emit ("datagram.rejected" , map [string ]interface {}{
1073+ "src_node_id" : srcNode ,
1074+ "src_addr" : pkt .Src .String (),
1075+ "dst_port" : pkt .DstPort ,
1076+ })
1077+ return
1078+ }
1079+ }
1080+
1081+ d .webhook .Emit ("data.datagram" , map [string ]interface {}{
1082+ "src_addr" : pkt .Src .String (), "src_port" : pkt .SrcPort ,
1083+ "dst_port" : pkt .DstPort , "size" : len (pkt .Payload ),
1084+ })
1085+ d .ipc .DeliverDatagram (pkt .Src , pkt .SrcPort , pkt .DstPort , pkt .Payload )
10661086}
10671087
10681088func (d * Daemon ) handleControlPacket (pkt * protocol.Packet ) {
0 commit comments