Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ability to Restrict Outbound Dials #5794

Merged
merged 3 commits into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions beacon-chain/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var appFlags = []cli.Flag{
cmd.P2PPrivKey,
cmd.P2PMetadata,
cmd.P2PWhitelist,
cmd.P2PBlacklist,
cmd.P2PEncoding,
cmd.P2PPubsub,
cmd.DataDirFlag,
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ func (b *BeaconNode) registerP2P(cliCtx *cli.Context) error {
UDPPort: cliCtx.Uint(cmd.P2PUDPPort.Name),
MaxPeers: cliCtx.Uint(cmd.P2PMaxPeers.Name),
WhitelistCIDR: cliCtx.String(cmd.P2PWhitelist.Name),
BlacklistCIDR: sliceutil.SplitCommaSeparated(cliCtx.StringSlice(cmd.P2PBlacklist.Name)),
EnableUPnP: cliCtx.Bool(cmd.EnableUPnPFlag.Name),
DisableDiscv5: cliCtx.Bool(flags.DisableDiscv5.Name),
Encoding: cliCtx.String(cmd.P2PEncoding.Name),
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/p2p/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Config struct {
UDPPort uint
MaxPeers uint
WhitelistCIDR string
BlacklistCIDR []string
Encoding string
StateNotifier statefeed.Notifier
PubSub string
Expand Down
26 changes: 26 additions & 0 deletions beacon-chain/p2p/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func buildOptions(cfg *Config, ip net.IP, priKey *ecdsa.PrivateKey) []libp2p.Opt
libp2p.EnableRelay(),
libp2p.ListenAddrs(listen),
whitelistSubnet(cfg.WhitelistCIDR),
blacklistSubnets(cfg.BlacklistCIDR),
// Add one for the boot node and another for the relay, otherwise when we are close to maxPeers we will be above the high
// water mark and continually trigger pruning.
libp2p.ConnectionManager(connmgr.NewConnManager(int(cfg.MaxPeers+2), int(cfg.MaxPeers+2), 1*time.Second)),
Expand Down Expand Up @@ -121,3 +122,28 @@ func whitelistSubnet(cidr string) libp2p.Option {
return nil
}
}

// blacklistSubnet adds a blacklist multiaddress filter for multiple given CIDR subnets.
// Example: 192.168.0.0/16 may be used to deny connections from your local
// network.
func blacklistSubnets(mulCidrs []string) libp2p.Option {
if len(mulCidrs) == 0 {
return func(_ *libp2p.Config) error {
return nil
}
}
return func(cfg *libp2p.Config) error {
if cfg.Filters == nil {
cfg.Filters = filter.NewFilters()
}

for _, cidr := range mulCidrs {
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return err
}
cfg.Filters.AddFilter(*ipnet, filter.ActionDeny)
}
return nil
}
}
56 changes: 56 additions & 0 deletions beacon-chain/p2p/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package p2p

import (
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"testing"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/prysmaticlabs/prysm/shared/testutil"
)

Expand Down Expand Up @@ -58,3 +63,54 @@ func TestPrivateKeyLoading(t *testing.T) {
t.Errorf("Private keys do not match got %#x but wanted %#x", rawBytes, newRaw)
}
}

func TestPeerBlacklist(t *testing.T) {
// create host with blacklist
ipAddr, pkey := createAddrAndPrivKey(t)
ipAddr2, pkey2 := createAddrAndPrivKey(t)

mask := ipAddr2.DefaultMask()
ones, _ := mask.Size()
maskedIP := ipAddr2.Mask(mask)
cidr := maskedIP.String() + fmt.Sprintf("/%d", ones)

listen, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", ipAddr, 2000))
if err != nil {
t.Fatalf("Failed to p2p listen: %v", err)
}
h1, err := libp2p.New(context.Background(), []libp2p.Option{privKeyOption(pkey), libp2p.ListenAddrs(listen), blacklistSubnets([]string{cidr})}...)
if err != nil {
t.Fatal(err)
}
defer func() {
err := h1.Close()
if err != nil {
t.Fatal(err)
}
}()

// create alternate host
listen, err = multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", ipAddr2, 3000))
if err != nil {
t.Fatalf("Failed to p2p listen: %v", err)
}
h2, err := libp2p.New(context.Background(), []libp2p.Option{privKeyOption(pkey2), libp2p.ListenAddrs(listen)}...)
if err != nil {
t.Fatal(err)
}
defer func() {
err := h2.Close()
if err != nil {
t.Fatal(err)
}
}()
multiAddress, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", ipAddr2, 3000, h2.ID()))
addrInfo, err := peer.AddrInfoFromP2pAddr(multiAddress)
if err != nil {
t.Fatal(err)
}
err = h1.Connect(context.Background(), *addrInfo)
if err == nil {
t.Error("Wanted connection to fail with blacklist")
}
}
1 change: 1 addition & 0 deletions beacon-chain/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ var appHelpFlagGroups = []flagGroup{
cmd.P2PPrivKey,
cmd.P2PMetadata,
cmd.P2PWhitelist,
cmd.P2PBlacklist,
cmd.StaticPeers,
cmd.EnableUPnPFlag,
cmd.P2PEncoding,
Expand Down
7 changes: 7 additions & 0 deletions shared/cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ var (
"would whitelist connections to peers on your local network only. The default " +
"is to accept all connections.",
}
// P2PBlacklist defines a list of CIDR subnets to disallow connections from them.
P2PBlacklist = &cli.StringSliceFlag{
Name: "p2p-blacklist",
Usage: "The CIDR subnets for blacklisting peer connections. Example: 192.168.0.0/16 " +
"would blacklist connections from peers on your local network only. The default " +
"is to accept all connections.",
}
// P2PEncoding defines the encoding format for p2p messages.
P2PEncoding = &cli.StringFlag{
Name: "p2p-encoding",
Expand Down