Skip to content

Commit c0880b5

Browse files
committed
consider dns addresses as public
1 parent e9b02fc commit c0880b5

File tree

2 files changed

+109
-38
lines changed

2 files changed

+109
-38
lines changed

net/private.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package manet
22

33
import (
44
"net"
5+
"strings"
56

67
ma "github.com/multiformats/go-multiaddr"
78
)
@@ -46,6 +47,55 @@ var unroutableCIDR6 = []string{
4647
"ff00::/8",
4748
}
4849

50+
// specialUseDomains are reserved for various purposes and do not have a central authority
51+
// for consistent resolution in different networks.
52+
// see: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_names
53+
// This list doesn't contain `.onion` addresses as they are consistently resolved everywhere.
54+
var specialUseDomains = []string{
55+
"6tisch.arpa",
56+
"10.in-addr.arpa",
57+
"16.172.in-addr.arpa",
58+
"17.172.in-addr.arpa",
59+
"18.172.in-addr.arpa",
60+
"19.172.in-addr.arpa",
61+
"20.172.in-addr.arpa",
62+
"21.172.in-addr.arpa",
63+
"22.172.in-addr.arpa",
64+
"23.172.in-addr.arpa",
65+
"24.172.in-addr.arpa",
66+
"25.172.in-addr.arpa",
67+
"26.172.in-addr.arpa",
68+
"27.172.in-addr.arpa",
69+
"28.172.in-addr.arpa",
70+
"29.172.in-addr.arpa",
71+
"30.172.in-addr.arpa",
72+
"31.172.in-addr.arpa",
73+
"168.192.in-addr.arpa",
74+
"170.0.0.192.in-addr.arpa",
75+
"171.0.0.192.in-addr.arpa",
76+
"ipv4only.arpa",
77+
"254.169.in-addr.arpa",
78+
"8.e.f.ip6.arpa",
79+
"9.e.f.ip6.arpa",
80+
"a.e.f.ip6.arpa",
81+
"b.e.f.ip6.arpa",
82+
"home.arpa",
83+
"example",
84+
"example.com",
85+
"example.net",
86+
"example.org",
87+
"invalid",
88+
"intranet",
89+
"internal",
90+
"private",
91+
"corp",
92+
"home",
93+
"lan",
94+
"local",
95+
"localhost",
96+
"test",
97+
}
98+
4999
func init() {
50100
Private4 = parseCIDR(privateCIDR4)
51101
Private6 = parseCIDR(privateCIDR6)
@@ -65,7 +115,8 @@ func parseCIDR(cidrs []string) []*net.IPNet {
65115
return ipnets
66116
}
67117

68-
// IsPublicAddr retruns true if the IP part of the multiaddr is a publicly routable address
118+
// IsPublicAddr returns true if the IP part of the multiaddr is a publicly routable address
119+
// or if it's a dns address without a special use domain e.g. .local.
69120
func IsPublicAddr(a ma.Multiaddr) bool {
70121
isPublic := false
71122
ma.ForEach(a, func(c ma.Component) bool {
@@ -78,6 +129,15 @@ func IsPublicAddr(a ma.Multiaddr) bool {
78129
case ma.P_IP6:
79130
ip := net.IP(c.RawValue())
80131
isPublic = !inAddrRange(ip, Private6) && !inAddrRange(ip, Unroutable6)
132+
case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
133+
dnsAddr := c.Value()
134+
isPublic = true
135+
for _, sd := range specialUseDomains {
136+
if strings.HasSuffix(dnsAddr, sd) {
137+
isPublic = false
138+
break
139+
}
140+
}
81141
}
82142
return false
83143
})

net/private_test.go

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,59 @@
11
package manet
22

33
import (
4+
"fmt"
45
"testing"
56

67
ma "github.com/multiformats/go-multiaddr"
78
)
89

910
func TestIsPublicAddr(t *testing.T) {
10-
a, err := ma.NewMultiaddr("/ip4/192.168.1.1/tcp/80")
11-
if err != nil {
12-
t.Fatal(err)
13-
}
14-
15-
if IsPublicAddr(a) {
16-
t.Fatal("192.168.1.1 is not a public address!")
17-
}
18-
19-
if !IsPrivateAddr(a) {
20-
t.Fatal("192.168.1.1 is a private address!")
21-
}
22-
23-
a, err = ma.NewMultiaddr("/ip4/1.1.1.1/tcp/80")
24-
if err != nil {
25-
t.Fatal(err)
26-
}
27-
28-
if !IsPublicAddr(a) {
29-
t.Fatal("1.1.1.1 is a public address!")
30-
}
31-
32-
if IsPrivateAddr(a) {
33-
t.Fatal("1.1.1.1 is not a private address!")
34-
}
35-
36-
a, err = ma.NewMultiaddr("/tcp/80/ip4/1.1.1.1")
37-
if err != nil {
38-
t.Fatal(err)
39-
}
40-
41-
if IsPublicAddr(a) {
42-
t.Fatal("shouldn't consider an address that starts with /tcp/ as *public*")
43-
}
44-
45-
if IsPrivateAddr(a) {
46-
t.Fatal("shouldn't consider an address that starts with /tcp/ as *private*")
11+
tests := []struct {
12+
addr ma.Multiaddr
13+
isPublic bool
14+
isPrivate bool
15+
}{
16+
{
17+
addr: ma.StringCast("/ip4/192.168.1.1/tcp/80"),
18+
isPublic: false,
19+
isPrivate: true,
20+
},
21+
{
22+
addr: ma.StringCast("/ip4/1.1.1.1/tcp/80"),
23+
isPublic: true,
24+
isPrivate: false,
25+
},
26+
{
27+
addr: ma.StringCast("/tcp/80/ip4/1.1.1.1"),
28+
isPublic: false,
29+
isPrivate: false,
30+
},
31+
{
32+
addr: ma.StringCast("/dns/node.libp2p.io/udp/1/quic-v1"),
33+
isPublic: true,
34+
isPrivate: false,
35+
},
36+
{
37+
addr: ma.StringCast("/dnsaddr/node.libp2p.io/udp/1/quic-v1"),
38+
isPublic: true,
39+
isPrivate: false,
40+
},
41+
{
42+
addr: ma.StringCast("/dns/node.libp2p.local/udp/1/quic-v1"),
43+
isPublic: false,
44+
isPrivate: false, // You can configure .local domains in local networks to return public addrs
45+
},
46+
}
47+
for i, tt := range tests {
48+
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
49+
isPublic := IsPublicAddr(tt.addr)
50+
isPrivate := IsPrivateAddr(tt.addr)
51+
if isPublic != tt.isPublic {
52+
t.Errorf("IsPublicAddr check failed for %s: expected %t, got %t", tt.addr, tt.isPublic, isPublic)
53+
}
54+
if isPrivate != tt.isPrivate {
55+
t.Errorf("IsPrivateAddr check failed for %s: expected %t, got %t", tt.addr, tt.isPrivate, isPrivate)
56+
}
57+
})
4758
}
4859
}

0 commit comments

Comments
 (0)