forked from libp2p/go-libp2p-kad-dht
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Configurable Peer Filtering (libp2p#471)
Allows specifying peer filter functions on query and on adding peers to the routing table. This patch also includes some reasonable default functions for a public-only and private-only DHT. Co-authored-by: Will Scott <[email protected]> Co-authored-by: Steven Allen <[email protected]>
- Loading branch information
1 parent
fa52ddd
commit 0543571
Showing
8 changed files
with
227 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package dht | ||
|
||
import ( | ||
"bytes" | ||
"net" | ||
|
||
"github.com/libp2p/go-libp2p-core/network" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
netroute "github.com/libp2p/go-netroute" | ||
|
||
ma "github.com/multiformats/go-multiaddr" | ||
manet "github.com/multiformats/go-multiaddr-net" | ||
) | ||
|
||
// QueryFilterFunc is a filter applied when considering peers to dial when querying | ||
type QueryFilterFunc func(dht *IpfsDHT, ai peer.AddrInfo) bool | ||
|
||
// RouteTableFilterFunc is a filter applied when considering connections to keep in | ||
// the local route table. | ||
type RouteTableFilterFunc func(dht *IpfsDHT, conns []network.Conn) bool | ||
|
||
// PublicQueryFilter returns true if the peer is suspected of being publicly accessible | ||
func PublicQueryFilter(_ *IpfsDHT, ai peer.AddrInfo) bool { | ||
if len(ai.Addrs) == 0 { | ||
return false | ||
} | ||
|
||
var hasPublicAddr bool | ||
for _, a := range ai.Addrs { | ||
if !isRelayAddr(a) && manet.IsPublicAddr(a) { | ||
hasPublicAddr = true | ||
} | ||
} | ||
return hasPublicAddr | ||
} | ||
|
||
var _ QueryFilterFunc = PublicQueryFilter | ||
|
||
// PublicRoutingTableFilter allows a peer to be added to the routing table if the connections to that peer indicate | ||
// that it is on a public network | ||
func PublicRoutingTableFilter(dht *IpfsDHT, conns []network.Conn) bool { | ||
if len(conns) == 0 { | ||
return false | ||
} | ||
|
||
// Do we have a public address for this peer? | ||
id := conns[0].RemotePeer() | ||
known := dht.peerstore.PeerInfo(id) | ||
for _, a := range known.Addrs { | ||
if !isRelayAddr(a) && manet.IsPublicAddr(a) { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
var _ RouteTableFilterFunc = PublicRoutingTableFilter | ||
|
||
// PrivateQueryFilter doens't currently restrict which peers we are willing to query from the local DHT. | ||
func PrivateQueryFilter(dht *IpfsDHT, ai peer.AddrInfo) bool { | ||
return len(ai.Addrs) > 0 | ||
} | ||
|
||
var _ QueryFilterFunc = PrivateQueryFilter | ||
|
||
// PrivateRoutingTableFilter allows a peer to be added to the routing table if the connections to that peer indicate | ||
// that it is on a private network | ||
func PrivateRoutingTableFilter(dht *IpfsDHT, conns []network.Conn) bool { | ||
router, _ := netroute.New() | ||
myAdvertisedIPs := make([]net.IP, 0) | ||
for _, a := range dht.Host().Addrs() { | ||
if manet.IsPublicAddr(a) && !isRelayAddr(a) { | ||
ip, err := manet.ToIP(a) | ||
if err != nil { | ||
continue | ||
} | ||
myAdvertisedIPs = append(myAdvertisedIPs, ip) | ||
} | ||
} | ||
|
||
for _, c := range conns { | ||
ra := c.RemoteMultiaddr() | ||
if manet.IsPrivateAddr(ra) && !isRelayAddr(ra) { | ||
return true | ||
} | ||
|
||
if manet.IsPublicAddr(ra) { | ||
ip, err := manet.ToIP(ra) | ||
if err != nil { | ||
continue | ||
} | ||
|
||
// if the ip is the same as one of the local host's public advertised IPs - then consider it local | ||
for _, i := range myAdvertisedIPs { | ||
if i.Equal(ip) { | ||
return true | ||
} | ||
if ip.To4() == nil { | ||
if i.To4() == nil && isEUI(ip) && sameV6Net(i, ip) { | ||
return true | ||
} | ||
} | ||
} | ||
|
||
// if there's no gateway - a direct host in the OS routing table - then consider it local | ||
// This is relevant in particular to ipv6 networks where the addresses may all be public, | ||
// but the nodes are aware of direct links between each other. | ||
if router != nil { | ||
_, gw, _, err := router.Route(ip) | ||
if gw == nil && err == nil { | ||
return true | ||
} | ||
} | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
var _ RouteTableFilterFunc = PrivateRoutingTableFilter | ||
|
||
func isEUI(ip net.IP) bool { | ||
// per rfc 2373 | ||
return ip[11] == 0xff && ip[12] == 0xfe | ||
} | ||
|
||
func sameV6Net(a, b net.IP) bool { | ||
return bytes.Equal(a[0:8], b[0:8]) | ||
} | ||
|
||
func isRelayAddr(a ma.Multiaddr) bool { | ||
for _, p := range a.Protocols() { | ||
if p.Code == ma.P_CIRCUIT { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package dht | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/multiformats/go-multiaddr" | ||
) | ||
|
||
func TestIsRelay(t *testing.T) { | ||
a, _ := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/5002/p2p/QmdPU7PfRyKehdrP5A3WqmjyD6bhVpU1mLGKppa2FjGDjZ/p2p-circuit/p2p/QmVT6GYwjeeAF5TR485Yc58S3xRF5EFsZ5YAF4VcP3URHt") | ||
if !isRelayAddr(a) { | ||
t.Fatalf("thought %s was not a relay", a) | ||
} | ||
a, _ = multiaddr.NewMultiaddr("/p2p-circuit/p2p/QmVT6GYwjeeAF5TR485Yc58S3xRF5EFsZ5YAF4VcP3URHt") | ||
if !isRelayAddr(a) { | ||
t.Fatalf("thought %s was not a relay", a) | ||
} | ||
a, _ = multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/5002/p2p/QmdPU7PfRyKehdrP5A3WqmjyD6bhVpU1mLGKppa2FjGDjZ") | ||
if isRelayAddr(a) { | ||
t.Fatalf("thought %s was a relay", a) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters