Skip to content

Add handshakes.max_rate to limit new handshakes per second - #1643

Open
jrwren wants to merge 2 commits into
masterfrom
jay.wren-handshakes.max_rate
Open

Add handshakes.max_rate to limit new handshakes per second#1643
jrwren wants to merge 2 commits into
masterfrom
jay.wren-handshakes.max_rate

Conversation

@jrwren

@jrwren jrwren commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Nebula is vulnerable to DoS via handshake flooding since each incoming
handshake performs expensive DH operations. This adds a token bucket
rate limiter to the handshake manager that caps both inbound and
outbound new handshakes per second. When the limit is reached, new
handshakes are silently dropped and counted via the
handshake_manager.rate_limited metric.

Configured via handshakes.max_rate (default 0 = unlimited).

Co-Authored-By: Claude svc-devxp-claude@slack-corp.com

  Nebula is vulnerable to DoS via handshake flooding since each incoming
  handshake performs expensive DH operations. This adds a token bucket
  rate limiter to the handshake manager that caps both inbound and
  outbound new handshakes per second. When the limit is reached, new
  handshakes are silently dropped and counted via the
  handshake_manager.rate_limited metric.

  Configured via handshakes.max_rate (default 0 = unlimited).

  Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@jrwren
jrwren force-pushed the jay.wren-handshakes.max_rate branch from a10ebee to 3df60ae Compare March 30, 2026 19:45
Comment thread examples/config.yml
# handshakes count against this limit. Once the limit is reached, new handshakes are dropped
# until the next second. A value of 0 means unlimited (default).
# This is useful for preventing DoS attacks that attempt to exhaust CPU with handshake crypto.
# Running `openssl speed ecdhp256` on your hardware can be a good rule of thumb for choosing

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might note that this is single-core, and that you may wish to scale this number per routine

Comment thread handshake_manager.go Outdated
return hh.hostinfo
}

// Check rate limit for new outbound handshakes

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from a DOS perspective, does it make sense to rate-limit outbound handshakes?

Comment thread handshake_manager.go Outdated
hm.metricRateLimited.Inc(1)
hm.l.WithField("vpnAddr", vpnAddr).Debug("Handshake rate limit reached, dropping outbound handshake")
hm.Unlock()
return nil

@JackDoan JackDoan Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

historically this has always been non-nil, is there anywhere that barfs bc we changed that? If we do decide to ratelimit outbounds, I'd have a slight preference to refactor this to be (*HostInfo, error) I think

Remove rate limiting from StartHandshake (outbound) since DoS
protection only needs to limit inbound handshakes. This also avoids
returning nil from StartHandshake which historically always returned
non-nil. Update config comment to note openssl speed is single-core
and suggest scaling by routines.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants