2020-03-10 15:31:38 -07:00
|
|
|
package dht
|
2020-03-03 02:58:39 -05:00
|
|
|
|
|
|
|
import (
|
2020-03-10 14:48:27 -07:00
|
|
|
"net"
|
|
|
|
|
2020-03-03 02:58:39 -05:00
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
|
|
|
"github.com/libp2p/go-libp2p-core/network"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2020-03-10 14:48:27 -07:00
|
|
|
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
|
|
|
|
type QueryFilterFunc func(h host.Host, ai peer.AddrInfo) bool
|
|
|
|
|
|
|
|
// RouteTableFilterFunc is a filter applied when considering connections to keep in
|
|
|
|
// the local route table.
|
2020-03-10 14:48:27 -07:00
|
|
|
type RouteTableFilterFunc func(h host.Host, 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
|
|
|
|
func PublicQueryFilter(h host.Host, ai peer.AddrInfo) bool {
|
|
|
|
if len(ai.Addrs) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
var hasPublicAddr bool
|
|
|
|
for _, a := range ai.Addrs {
|
|
|
|
if isRelayAddr(a) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if manet.IsPublicAddr(a) {
|
|
|
|
hasPublicAddr = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hasPublicAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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-10 14:48:27 -07:00
|
|
|
func PublicRoutingTableFilter(_ host.Host, conns []network.Conn) bool {
|
2020-03-03 02:58:39 -05:00
|
|
|
for _, c := range conns {
|
|
|
|
addr := c.RemoteMultiaddr()
|
|
|
|
if !isRelayAddr(addr) && manet.IsPublicAddr(addr) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrivateQueryFilter returns true if the peer is suspected of being accessible over a shared private network
|
|
|
|
func PrivateQueryFilter(h host.Host, ai peer.AddrInfo) bool {
|
|
|
|
conns := h.Network().ConnsToPeer(ai.ID)
|
|
|
|
if len(conns) > 0 {
|
|
|
|
for _, c := range conns {
|
|
|
|
if manet.IsPrivateAddr(c.RemoteMultiaddr()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(ai.Addrs) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
var hasPrivateAddr bool
|
|
|
|
for _, a := range ai.Addrs {
|
|
|
|
if manet.IsPublicAddr(a) {
|
|
|
|
if !isRelayAddr(a) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hasPrivateAddr = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hasPrivateAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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-10 14:48:27 -07:00
|
|
|
func PrivateRoutingTableFilter(h host.Host, conns []network.Conn) bool {
|
|
|
|
router, _ := netroute.New()
|
|
|
|
myAdvertisedIPs := make([]net.IP, 0)
|
|
|
|
for _, a := range h.Addrs() {
|
|
|
|
if manet.IsPublicAddr(a) {
|
|
|
|
ip, _ := manet.ToIP(a)
|
|
|
|
myAdvertisedIPs = append(myAdvertisedIPs, ip)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-03 02:58:39 -05:00
|
|
|
for _, c := range conns {
|
|
|
|
if manet.IsPrivateAddr(c.RemoteMultiaddr()) {
|
|
|
|
return true
|
|
|
|
}
|
2020-03-10 14:48:27 -07:00
|
|
|
|
|
|
|
if manet.IsPublicAddr(c.RemoteMultiaddr()) {
|
|
|
|
ip, _ := manet.ToIP(c.RemoteMultiaddr())
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: if the first 64 bits of an IPv6 match the host, and the last 64 bits are in EUI format - then consider it local
|
|
|
|
|
|
|
|
// if there's no gateway - a direct host in the OS routing table - then consider it local
|
|
|
|
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-10 14:48:27 -07:00
|
|
|
|
2020-03-03 02:58:39 -05:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func isRelayAddr(a ma.Multiaddr) bool {
|
2020-03-04 17:29:38 -05:00
|
|
|
val, err := a.ValueForProtocol(ma.P_CIRCUIT)
|
|
|
|
return err != nil && val != ""
|
2020-03-03 02:58:39 -05:00
|
|
|
}
|