Skip to content

Commit

Permalink
consider dns addresses as public
Browse files Browse the repository at this point in the history
  • Loading branch information
sukunrt committed Sep 7, 2023
1 parent e9b02fc commit c0880b5
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 38 deletions.
62 changes: 61 additions & 1 deletion net/private.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package manet

import (
"net"
"strings"

ma "github.com/multiformats/go-multiaddr"
)
Expand Down Expand Up @@ -46,6 +47,55 @@ var unroutableCIDR6 = []string{
"ff00::/8",
}

// specialUseDomains are reserved for various purposes and do not have a central authority
// for consistent resolution in different networks.
// see: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_names
// This list doesn't contain `.onion` addresses as they are consistently resolved everywhere.
var specialUseDomains = []string{
"6tisch.arpa",
"10.in-addr.arpa",
"16.172.in-addr.arpa",
"17.172.in-addr.arpa",
"18.172.in-addr.arpa",
"19.172.in-addr.arpa",
"20.172.in-addr.arpa",
"21.172.in-addr.arpa",
"22.172.in-addr.arpa",
"23.172.in-addr.arpa",
"24.172.in-addr.arpa",
"25.172.in-addr.arpa",
"26.172.in-addr.arpa",
"27.172.in-addr.arpa",
"28.172.in-addr.arpa",
"29.172.in-addr.arpa",
"30.172.in-addr.arpa",
"31.172.in-addr.arpa",
"168.192.in-addr.arpa",
"170.0.0.192.in-addr.arpa",
"171.0.0.192.in-addr.arpa",
"ipv4only.arpa",
"254.169.in-addr.arpa",
"8.e.f.ip6.arpa",
"9.e.f.ip6.arpa",
"a.e.f.ip6.arpa",
"b.e.f.ip6.arpa",
"home.arpa",
"example",
"example.com",
"example.net",
"example.org",
"invalid",
"intranet",
"internal",
"private",
"corp",
"home",
"lan",
"local",
"localhost",
"test",
}

func init() {
Private4 = parseCIDR(privateCIDR4)
Private6 = parseCIDR(privateCIDR6)
Expand All @@ -65,7 +115,8 @@ func parseCIDR(cidrs []string) []*net.IPNet {
return ipnets
}

// IsPublicAddr retruns true if the IP part of the multiaddr is a publicly routable address
// IsPublicAddr returns true if the IP part of the multiaddr is a publicly routable address
// or if it's a dns address without a special use domain e.g. .local.
func IsPublicAddr(a ma.Multiaddr) bool {
isPublic := false
ma.ForEach(a, func(c ma.Component) bool {
Expand All @@ -78,6 +129,15 @@ func IsPublicAddr(a ma.Multiaddr) bool {
case ma.P_IP6:
ip := net.IP(c.RawValue())
isPublic = !inAddrRange(ip, Private6) && !inAddrRange(ip, Unroutable6)
case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
dnsAddr := c.Value()
isPublic = true
for _, sd := range specialUseDomains {
if strings.HasSuffix(dnsAddr, sd) {
isPublic = false
break
}
}
}
return false
})
Expand Down
85 changes: 48 additions & 37 deletions net/private_test.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,59 @@
package manet

import (
"fmt"
"testing"

ma "github.com/multiformats/go-multiaddr"
)

func TestIsPublicAddr(t *testing.T) {
a, err := ma.NewMultiaddr("/ip4/192.168.1.1/tcp/80")
if err != nil {
t.Fatal(err)
}

if IsPublicAddr(a) {
t.Fatal("192.168.1.1 is not a public address!")
}

if !IsPrivateAddr(a) {
t.Fatal("192.168.1.1 is a private address!")
}

a, err = ma.NewMultiaddr("/ip4/1.1.1.1/tcp/80")
if err != nil {
t.Fatal(err)
}

if !IsPublicAddr(a) {
t.Fatal("1.1.1.1 is a public address!")
}

if IsPrivateAddr(a) {
t.Fatal("1.1.1.1 is not a private address!")
}

a, err = ma.NewMultiaddr("/tcp/80/ip4/1.1.1.1")
if err != nil {
t.Fatal(err)
}

if IsPublicAddr(a) {
t.Fatal("shouldn't consider an address that starts with /tcp/ as *public*")
}

if IsPrivateAddr(a) {
t.Fatal("shouldn't consider an address that starts with /tcp/ as *private*")
tests := []struct {
addr ma.Multiaddr
isPublic bool
isPrivate bool
}{
{
addr: ma.StringCast("/ip4/192.168.1.1/tcp/80"),
isPublic: false,
isPrivate: true,
},
{
addr: ma.StringCast("/ip4/1.1.1.1/tcp/80"),
isPublic: true,
isPrivate: false,
},
{
addr: ma.StringCast("/tcp/80/ip4/1.1.1.1"),
isPublic: false,
isPrivate: false,
},
{
addr: ma.StringCast("/dns/node.libp2p.io/udp/1/quic-v1"),
isPublic: true,
isPrivate: false,
},
{
addr: ma.StringCast("/dnsaddr/node.libp2p.io/udp/1/quic-v1"),
isPublic: true,
isPrivate: false,
},
{
addr: ma.StringCast("/dns/node.libp2p.local/udp/1/quic-v1"),
isPublic: false,
isPrivate: false, // You can configure .local domains in local networks to return public addrs
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
isPublic := IsPublicAddr(tt.addr)
isPrivate := IsPrivateAddr(tt.addr)
if isPublic != tt.isPublic {
t.Errorf("IsPublicAddr check failed for %s: expected %t, got %t", tt.addr, tt.isPublic, isPublic)
}
if isPrivate != tt.isPrivate {
t.Errorf("IsPrivateAddr check failed for %s: expected %t, got %t", tt.addr, tt.isPrivate, isPrivate)
}
})
}
}

0 comments on commit c0880b5

Please sign in to comment.