go-libp2p-kad-dht/dht_filters.go

140 lines
3.5 KiB
Go
Raw Normal View History

package dht
2020-03-03 02:58:39 -05:00
import (
2020-03-10 16:13:29 -07:00
"bytes"
"net"
2020-03-03 02:58:39 -05:00
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
netroute "github.com/libp2p/go-netroute"
2020-03-03 02:58:39 -05:00
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"
)
2020-03-06 15:03:32 -08:00
// QueryFilterFunc is a filter applied when considering peers to dial when querying
2020-03-19 15:22:13 -07:00
type QueryFilterFunc func(dht *IpfsDHT, ai peer.AddrInfo) bool
2020-03-06 15:03:32 -08:00
// RouteTableFilterFunc is a filter applied when considering connections to keep in
// the local route table.
2020-03-19 15:22:13 -07:00
type RouteTableFilterFunc func(dht *IpfsDHT, conns []network.Conn) bool
2020-03-06 15:03:32 -08:00
2020-03-03 02:58:39 -05:00
// PublicQueryFilter returns true if the peer is suspected of being publicly accessible
2020-03-19 15:22:13 -07:00
func PublicQueryFilter(_ *IpfsDHT, ai peer.AddrInfo) bool {
2020-03-03 02:58:39 -05:00
if len(ai.Addrs) == 0 {
return false
}
var hasPublicAddr bool
for _, a := range ai.Addrs {
2020-03-31 16:51:39 -07:00
if !isRelayAddr(a) && manet.IsPublicAddr(a) {
2020-03-03 02:58:39 -05:00
hasPublicAddr = true
}
}
return hasPublicAddr
}
2020-03-19 15:22:13 -07:00
var _ QueryFilterFunc = PublicQueryFilter
2020-03-03 02:58:39 -05:00
// 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
2020-03-19 16:19:54 -07:00
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
2020-03-03 02:58:39 -05:00
}
}
2020-03-19 16:19:54 -07:00
return false
}
2020-03-03 02:58:39 -05:00
2020-03-19 16:19:54 -07:00
var _ RouteTableFilterFunc = PublicRoutingTableFilter
2020-03-03 02:58:39 -05:00
2020-03-19 16:19:54 -07:00
// 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
2020-03-03 02:58:39 -05:00
}
2020-03-19 15:22:13 -07:00
var _ QueryFilterFunc = PrivateQueryFilter
2020-03-03 02:58:39 -05:00
// 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
2020-03-19 15:22:13 -07:00
func PrivateRoutingTableFilter(dht *IpfsDHT, conns []network.Conn) bool {
router, _ := netroute.New()
myAdvertisedIPs := make([]net.IP, 0)
2020-03-19 15:22:13 -07:00
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)
}
}
2020-03-03 02:58:39 -05:00
for _, c := range conns {
ra := c.RemoteMultiaddr()
2020-03-31 16:51:39 -07:00
if manet.IsPrivateAddr(ra) && !isRelayAddr(ra) {
2020-03-03 02:58:39 -05:00
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
}
2020-03-10 16:13:29 -07:00
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
2020-03-31 16:51:39 -07:00
// 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
}
}
}
2020-03-03 02:58:39 -05:00
}
2020-03-03 02:58:39 -05:00
return false
}
2020-03-19 15:22:13 -07:00
var _ RouteTableFilterFunc = PrivateRoutingTableFilter
2020-03-10 16:13:29 -07:00
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])
}
2020-03-03 02:58:39 -05:00
func isRelayAddr(a ma.Multiaddr) bool {
for _, p := range a.Protocols() {
if p.Code == ma.P_CIRCUIT {
return true
}
}
return false
2020-03-03 02:58:39 -05:00
}