p2p/net/identify: clump addr observers into groups
Different mutliaddrs is not enough. Nodes may share transports. NAT port mappings will likely only work on the base IP/TCP port pair. We go one step further, and require different root (IP) addrs. Just in case some NATs group by IP. In practice, this is what we want: use addresses only if hosts that are on different parts of the network have seen this address.
Juan Batiz-Benet committed
Jun 7, 2015 at 17:00 UTC
500bb51759503cf5481d7150c8a4a1d791ba9078
2 files changed
+29
-3
p2p/protocol/identify/obsaddr.go
+16
-2
@@ -85,11 +85,25 @@ func (oas *ObservedAddrSet) Add(addr ma.Multiaddr, observer ma.Multiaddr) {
85
oas.addrs[s] = oa
86
}
87
88
- // Add current observer.
89
- oa.SeenBy[observer.String()] = struct{}{}
88
+ // mark the observer
89
+ oa.SeenBy[observerGroup(observer)] = struct{}{}
90
oa.LastSeen = time.Now()
91
}
92
93
+// observerGroup is a function that determines what part of
94
+// a multiaddr counts as a different observer. for example,
95
+// two ipfs nodes at the same IP/TCP transport would get
96
+// the exact same NAT mapping; they would count as the
97
+// same observer. This may protect against NATs who assign
98
+// different ports to addresses at different IP hosts, but
99
+// not TCP ports.
100
+//
101
+// Here, we use the root multiaddr address. This is mostly
102
+// IP addresses. In practice, this is what we want.
103
+func observerGroup(m ma.Multiaddr) string {
104
+ return ma.Split(m)[0].String()
105
+}
106
+
107
func (oas *ObservedAddrSet) SetTTL(ttl time.Duration) {
108
oas.Lock()
109
defer oas.Unlock()
p2p/protocol/identify/obsaddr_test.go
+13
-1
@@ -38,7 +38,8 @@ func TestObsAddrSet(t *testing.T) {
38
a3 := m("/ip4/1.2.3.4/tcp/1233")
39
a4 := m("/ip4/1.2.3.4/tcp/1234")
40
a5 := m("/ip4/1.2.3.4/tcp/1235")
41
- a6 := m("/ip4/1.2.3.4/tcp/1236")
41
+ a6 := m("/ip4/1.2.3.6/tcp/1236")
42
+ a7 := m("/ip4/1.2.3.7/tcp/1237")
43
44
oas := ObservedAddrSet{}
45
@@ -63,7 +64,15 @@ func TestObsAddrSet(t *testing.T) {
64
t.Error("addrs should _still_ be empty (same obs)")
65
}
66
67
+ // different observer, but same observer group.
68
oas.Add(a1, a5)
69
+ oas.Add(a2, a5)
70
+ oas.Add(a3, a5)
71
+ if !addrsMarch(oas.Addrs(), nil) {
72
+ t.Error("addrs should _still_ be empty (same obs group)")
73
+ }
74
+
75
+ oas.Add(a1, a6)
76
if !addrsMarch(oas.Addrs(), []ma.Multiaddr{a1}) {
77
t.Error("addrs should only have a1")
78
}
@@ -74,6 +83,9 @@ func TestObsAddrSet(t *testing.T) {
83
oas.Add(a2, a6)
84
oas.Add(a1, a6)
85
oas.Add(a1, a6)
86
+ oas.Add(a2, a7)
87
+ oas.Add(a1, a7)
88
+ oas.Add(a1, a7)
89
if !addrsMarch(oas.Addrs(), []ma.Multiaddr{a1, a2}) {
90
t.Error("addrs should only have a1, a2")
91
}