diff --git a/Dockerfile b/Dockerfile index 2fc8527ab6..10bd6ba8c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ADD . /go-ethereum RUN cd /go-ethereum && go run build/ci.go install ./cmd/geth # Pull Geth into a second stage deploy alpine container -FROM alpine:3.16.0 +FROM alpine:3.17 ARG BSC_USER=bsc ARG BSC_USER_UID=1000 @@ -26,9 +26,9 @@ ENV BSC_HOME=/bsc ENV HOME=${BSC_HOME} ENV DATA_DIR=/data -ENV PACKAGES ca-certificates~=20220614-r0 jq~=1.6 \ - bash~=5.1.16-r2 bind-tools~=9.16.37 tini~=0.19.0 \ - grep~=3.7 curl~=7.83.1 sed~=4.8-r0 +ENV PACKAGES ca-certificates jq \ + bash bind-tools tini \ + grep curl sed RUN apk add --no-cache $PACKAGES \ && rm -rf /var/cache/apk/* \ diff --git a/eth/handler.go b/eth/handler.go index 19de9ad872..8b41a034dd 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -20,6 +20,7 @@ import ( "errors" "math" "math/big" + "strings" "sync" "sync/atomic" "time" @@ -114,10 +115,12 @@ type handler struct { checkpointNumber uint64 // Block number for the sync progress validator to cross reference checkpointHash common.Hash // Block hash for the sync progress validator to cross reference - database ethdb.Database - txpool txPool - chain *core.BlockChain - maxPeers int + database ethdb.Database + txpool txPool + chain *core.BlockChain + maxPeers int + maxPeersPerIp int + peersPerIp map[string]int downloader *downloader.Downloader blockFetcher *fetcher.BlockFetcher @@ -161,6 +164,7 @@ func newHandler(config *handlerConfig) (*handler, error) { chain: config.Chain, peers: config.PeerSet, merger: config.Merger, + peersPerIp: make(map[string]int), whitelist: config.Whitelist, directBroadcast: config.DirectBroadcast, diffSync: config.DiffSync, @@ -362,7 +366,22 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error { return p2p.DiscTooManyPeers } } - peer.Log().Debug("Ethereum peer connected", "name", peer.Name()) + + remoteAddr := peer.Peer.Info().Network.RemoteAddress + index := strings.Index(remoteAddr, ":") + remoteIp := remoteAddr[:index] + if num, ok := h.peersPerIp[remoteIp]; ok && num > h.maxPeersPerIp { + peer.Log().Debug("The IP has too many peers", "ip", remoteIp, + "maxPeersPerIp", h.maxPeersPerIp, + "name", peer.Peer.Info().Name, + "Enode", peer.Peer.Info().Enode) + return p2p.DiscTooManyPeers + } + h.peersPerIp[remoteIp] = h.peersPerIp[remoteIp] + 1 + + peer.Log().Debug("Ethereum peer connected", "name", peer.Name(), + "remoteAddr", remoteAddr, "remoteIp", remoteIp, + "number", h.peersPerIp[remoteIp]) // Register the peer locally if err := h.peers.registerPeer(peer, snap, diff, trust); err != nil { @@ -578,11 +597,21 @@ func (h *handler) unregisterPeer(id string) { if err := h.peers.unregisterPeer(id); err != nil { logger.Error("Ethereum peer removal failed", "err", err) } + + remoteIp := peer.Peer.Info().Network.RemoteAddress + h.peersPerIp[remoteIp] = h.peersPerIp[remoteIp] - 1 + logger.Debug("unregisterPeer", "ip", remoteIp, + "maxPeersPerIp", h.maxPeersPerIp, + "name", peer.Peer.Info().Name, + "Enode", peer.Peer.Info().Enode) + if h.peersPerIp[remoteIp] == 0 { + delete(h.peersPerIp, remoteIp) + } } func (h *handler) Start(maxPeers int) { h.maxPeers = maxPeers - + h.maxPeersPerIp = 1 // broadcast transactions h.wg.Add(1) h.txsCh = make(chan core.NewTxsEvent, txChanSize) diff --git a/p2p/server.go b/p2p/server.go index 38c2d73a0e..d016e382f1 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -79,6 +79,8 @@ type Config struct { // connected. It must be greater than zero. MaxPeers int + MaxPeersPerIp int + // MaxPendingPeers is the maximum number of peers that can be pending in the // handshake phase, counted separately for inbound and outbound connections. // Zero defaults to preset values.