@@ -67,6 +67,13 @@ func main() {
6767 synRate := flag .Int ("syn-rate-limit" , 0 , "max SYN packets per second (default 100)" )
6868 maxConnsPerPort := flag .Int ("max-conns-per-port" , 0 , "max connections per port (default 1024)" )
6969 maxConnsTotal := flag .Int ("max-conns-total" , 0 , "max total connections (default 4096)" )
70+ // PILOT-343/344/345 rate-limit whitelists. Comma-separated trusted-peer
71+ // node IDs (decimal uint32). Env fallbacks let deployments configure
72+ // without editing flag strings. Empty default preserves backwards
73+ // compatibility — fleets that don't set them behave exactly as before.
74+ synWhitelist := flag .String ("syn-whitelist" , "" , "PILOT-343: comma-separated trusted source node IDs that bypass the SYN rate limit. Env: PILOT_SYN_WHITELIST." )
75+ replyWhitelist := flag .String ("reply-whitelist" , "" , "PILOT-344: comma-separated trusted peer node IDs that bypass the keyexchange reply interval gate. Env: PILOT_REPLY_WHITELIST." )
76+ rekeyWhitelist := flag .String ("rekey-whitelist" , "" , "PILOT-345: comma-separated trusted peer node IDs that bypass the tunnel-rekey interval and 4096 cap. Env: PILOT_REKEY_WHITELIST." )
7077 timeWait := flag .Duration ("time-wait" , 0 , "TIME_WAIT duration (default 10s)" )
7178 public := flag .Bool ("public" , false , "make this node's endpoint publicly visible (default: private)" )
7279 relayOnly := flag .Bool ("relay-only" , false , "hide real_addr from peers; reach this node only via beacon-relay path. Privacy stance: peers cannot enumerate this daemon's public IP. Trade-off: relay adds one beacon hop. Default false (current direct-first behavior)." )
@@ -260,6 +267,15 @@ func main() {
260267 if err := rt .StartPlugins (context .Background ()); err != nil {
261268 log .Fatalf ("plugin startup: %v" , err )
262269 }
270+
271+ // PILOT-343/344/345: apply rate-limit whitelists BEFORE Start so the
272+ // first inbound SYN/PILA/encrypted-frame already sees them. Each
273+ // helper tolerates empty/garbage input — bad tokens log a warning
274+ // and are dropped so a typo in env doesn't fail-fast the daemon.
275+ applyNodeIDWhitelist ("syn" , * synWhitelist , "PILOT_SYN_WHITELIST" , d .SetSYNWhitelist )
276+ applyNodeIDWhitelist ("reply" , * replyWhitelist , "PILOT_REPLY_WHITELIST" , d .SetReplyWhitelist )
277+ applyNodeIDWhitelist ("rekey" , * rekeyWhitelist , "PILOT_REKEY_WHITELIST" , d .SetRekeyWhitelist )
278+
263279 if err := d .Start (); err != nil {
264280 log .Fatalf ("daemon start: %v" , err )
265281 }
@@ -317,3 +333,43 @@ func parseNetworkIDs(s string) []uint16 {
317333 }
318334 return ids
319335}
336+
337+ // parseNodeIDs parses a comma-separated string of uint32 node IDs.
338+ // Garbage tokens are logged and skipped — a typo in env shouldn't
339+ // fail-fast the daemon.
340+ func parseNodeIDs (s string ) []uint32 {
341+ if s == "" {
342+ return nil
343+ }
344+ var ids []uint32
345+ for _ , p := range strings .Split (s , "," ) {
346+ p = strings .TrimSpace (p )
347+ if p == "" {
348+ continue
349+ }
350+ n , err := strconv .ParseUint (p , 10 , 32 )
351+ if err != nil {
352+ log .Printf ("warning: invalid node ID %q: %v" , p , err )
353+ continue
354+ }
355+ ids = append (ids , uint32 (n ))
356+ }
357+ return ids
358+ }
359+
360+ // applyNodeIDWhitelist resolves flag, falls back to env, parses the
361+ // comma-separated list, and applies via the provided setter. Logs one
362+ // line on success showing the count so deployments can sanity-check
363+ // what landed.
364+ func applyNodeIDWhitelist (name , flagVal , envName string , set func ([]uint32 )) {
365+ raw := flagVal
366+ if raw == "" {
367+ raw = os .Getenv (envName )
368+ }
369+ if raw == "" {
370+ return
371+ }
372+ ids := parseNodeIDs (raw )
373+ set (ids )
374+ log .Printf ("%s-rate-limit whitelist configured: %d node(s)" , name , len (ids ))
375+ }
0 commit comments