add rate limiter to login and sync on grpc

This commit is contained in:
Pascal Fischer
2025-05-07 20:35:41 +02:00
parent 9359fea507
commit 4a3c782a31
2 changed files with 14 additions and 8 deletions

View File

@@ -2,6 +2,7 @@ package server
import (
"context"
"errors"
"fmt"
"net"
"net/netip"
@@ -13,6 +14,7 @@ import (
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
log "github.com/sirupsen/logrus"
"golang.org/x/time/rate"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/peer"
@@ -125,9 +127,15 @@ func getRealIP(ctx context.Context) net.IP {
return nil
}
var syncLimiter = rate.NewLimiter(rate.Every(time.Minute/300), 1)
// Sync validates the existence of a connecting peer, sends an initial state (all available for the connecting peers) and
// notifies the connected peer of any updates (e.g. new peers under the same account)
func (s *GRPCServer) Sync(req *proto.EncryptedMessage, srv proto.ManagementService_SyncServer) error {
if !syncLimiter.Allow() {
return errors.New("rate limit exceeded")
}
reqStart := time.Now()
if s.appMetrics != nil {
s.appMetrics.GRPCMetrics().CountSyncRequest()
@@ -411,11 +419,17 @@ func (s *GRPCServer) parseRequest(ctx context.Context, req *proto.EncryptedMessa
return peerKey, nil
}
var loginLimiter = rate.NewLimiter(rate.Every(time.Minute/300), 1)
// Login endpoint first checks whether peer is registered under any account
// In case it is, the login is successful
// In case it isn't, the endpoint checks whether setup key is provided within the request and tries to register a peer.
// In case of the successful registration login is also successful
func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error) {
if !loginLimiter.Allow() {
return nil, errors.New("rate limit exceeded")
}
reqStart := time.Now()
defer func() {
if s.appMetrics != nil {

View File

@@ -4,7 +4,6 @@ import (
"context"
"crypto/sha256"
b64 "encoding/base64"
"errors"
"fmt"
"net"
"slices"
@@ -15,7 +14,6 @@ import (
"github.com/rs/xid"
log "github.com/sirupsen/logrus"
"golang.org/x/exp/maps"
"golang.org/x/time/rate"
"github.com/netbirdio/netbird/management/domain"
"github.com/netbirdio/netbird/management/server/geolocation"
@@ -782,17 +780,11 @@ func (am *DefaultAccountManager) handlePeerLoginNotFound(ctx context.Context, lo
return nil, nil, nil, status.Errorf(status.Internal, "failed while logging in peer")
}
var loginLimiter = rate.NewLimiter(rate.Every(time.Minute/500), 1)
// LoginPeer logs in or registers a peer.
// If peer doesn't exist the function checks whether a setup key or a user is present and registers a new peer if so.
func (am *DefaultAccountManager) LoginPeer(ctx context.Context, login types.PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
accountID, err := am.Store.GetAccountIDByPeerPubKey(ctx, login.WireGuardPubKey)
if err != nil {
if !loginLimiter.Allow() {
return nil, nil, nil, errors.New("rate limit exceeded")
}
return am.handlePeerLoginNotFound(ctx, login, err)
}