diff --git a/config.go b/config.go index d5fbe30b8..3bc244468 100644 --- a/config.go +++ b/config.go @@ -720,6 +720,7 @@ func DefaultConfig() Config { MsgRateBytes: discovery.DefaultMsgBytesPerSecond, MsgBurstBytes: discovery.DefaultMsgBytesBurst, FilterConcurrency: discovery.DefaultFilterConcurrency, + BanThreshold: discovery.DefaultBanThreshold, }, Invoices: &lncfg.Invoices{ HoldExpiryDelta: lncfg.DefaultHoldInvoiceExpiryDelta, diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 34cd2b75e..c3ef87fce 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -403,6 +403,10 @@ type Config struct { // FilterConcurrency is the maximum number of concurrent gossip filter // applications that can be processed. FilterConcurrency int + + // BanThreshold is the score used to decide whether a given peer is + // banned or not. + BanThreshold uint64 } // processedNetworkMsg is a wrapper around networkMsg and a boolean. It is @@ -586,7 +590,7 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper maxRejectedUpdates, ), chanUpdateRateLimiter: make(map[uint64][2]*rate.Limiter), - banman: newBanman(DefaultBanThreshold), + banman: newBanman(cfg.BanThreshold), } gossiper.vb = NewValidationBarrier(1000, gossiper.quit) diff --git a/lncfg/gossip.go b/lncfg/gossip.go index 0c297e324..61e5fe739 100644 --- a/lncfg/gossip.go +++ b/lncfg/gossip.go @@ -39,6 +39,8 @@ type Gossip struct { MsgBurstBytes uint64 `long:"msg-burst-bytes" description:"The maximum burst of outbound gossip data, in bytes, that can be sent at once. This works in conjunction with gossip.msg-rate-bytes as part of a token bucket rate-limiting scheme. This value represents the size of the token bucket. It allows for short, high-speed bursts of traffic, with the long-term rate controlled by gossip.msg-rate-bytes. This value must be larger than the maximum lightning message size (~65KB) to allow sending large gossip messages."` FilterConcurrency int `long:"filter-concurrency" description:"The maximum number of concurrent gossip filter applications that can be processed. If not set, defaults to 5."` + + BanThreshold uint64 `long:"ban-threshold" description:"The score at which a peer is banned. A peer's ban score is incremented for each invalid gossip message. Invalid messages include those with bad signatures, stale timestamps, excessive updates, or invalid chain data. Once the score reaches this threshold, the peer is banned."` } // Parse the pubkeys for the pinned syncers. diff --git a/sample-lnd.conf b/sample-lnd.conf index cba40213c..38f761783 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1784,6 +1784,22 @@ ; See docs/gossip_rate_limiting.md for mor information. ; gossip.filter-concurrency=5 +; The score at which a peer is banned. Each time a peer sends a gossip message +; that is considered invalid, its ban score is incremented. Once the score +; reaches this threshold, the peer is banned for a default of 48 hours, and we +; will no longer process gossip messages from them. This is a measure to +; protect the node from spam and misbehaving peers. +; +; A gossip message can be considered invalid for several reasons, including: +; - Invalid signature on the announcement. +; - Stale timestamp, older than what we already have. +; - Too many channel updates for the same channel in a short period. +; - Announcing a channel that is not found on-chain. +; - Announcing a channel that has already been closed. +; - Announcing a channel with an invalid proof. +; +; gossip.ban-threshold=100 + [invoices] ; If a hold invoice has accepted htlcs that reach their expiry height and are diff --git a/server.go b/server.go index 9af5ac128..5e08fb51d 100644 --- a/server.go +++ b/server.go @@ -1226,6 +1226,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, MsgRateBytes: cfg.Gossip.MsgRateBytes, MsgBurstBytes: cfg.Gossip.MsgBurstBytes, FilterConcurrency: cfg.Gossip.FilterConcurrency, + BanThreshold: cfg.Gossip.BanThreshold, }, nodeKeyDesc) accessCfg := &accessManConfig{