github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/p2p/netaddress.go (about) 1 // Modified for Tendermint 2 // Originally Copyright (c) 2013-2014 Conformal Systems LLC. 3 // https://github.com/conformal/btcd/blob/master/LICENSE 4 5 package p2p 6 7 import ( 8 "encoding/hex" 9 "flag" 10 "fmt" 11 "net" 12 "strconv" 13 "strings" 14 "time" 15 16 "github.com/pkg/errors" 17 ) 18 19 // NetAddress defines information about a peer on the network 20 // including its ID, IP address, and port. 21 type NetAddress struct { 22 ID ID `json:"id"` 23 IP net.IP `json:"ip"` 24 Port uint16 `json:"port"` 25 26 // TODO: 27 // Name string `json:"name"` // optional DNS name 28 29 // memoize .String() 30 str string 31 } 32 33 // IDAddressString returns id@hostPort. It strips the leading 34 // protocol from protocolHostPort if it exists. 35 func IDAddressString(id ID, protocolHostPort string) string { 36 hostPort := removeProtocolIfDefined(protocolHostPort) 37 return fmt.Sprintf("%s@%s", id, hostPort) 38 } 39 40 // NewNetAddress returns a new NetAddress using the provided TCP 41 // address. When testing, other net.Addr (except TCP) will result in 42 // using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will 43 // panic. Panics if ID is invalid. 44 // TODO: socks proxies? 45 func NewNetAddress(id ID, addr net.Addr) *NetAddress { 46 tcpAddr, ok := addr.(*net.TCPAddr) 47 if !ok { 48 if flag.Lookup("test.v") == nil { // normal run 49 panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) 50 } else { // in testing 51 netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) 52 netAddr.ID = id 53 return netAddr 54 } 55 } 56 57 if err := validateID(id); err != nil { 58 panic(fmt.Sprintf("Invalid ID %v: %v (addr: %v)", id, err, addr)) 59 } 60 61 ip := tcpAddr.IP 62 port := uint16(tcpAddr.Port) 63 na := NewNetAddressIPPort(ip, port) 64 na.ID = id 65 return na 66 } 67 68 // NewNetAddressString returns a new NetAddress using the provided address in 69 // the form of "ID@IP:Port". 70 // Also resolves the host if host is not an IP. 71 // Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup) 72 func NewNetAddressString(addr string) (*NetAddress, error) { 73 addrWithoutProtocol := removeProtocolIfDefined(addr) 74 spl := strings.Split(addrWithoutProtocol, "@") 75 if len(spl) != 2 { 76 return nil, ErrNetAddressNoID{addr} 77 } 78 79 // get ID 80 if err := validateID(ID(spl[0])); err != nil { 81 return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} 82 } 83 var id ID 84 id, addrWithoutProtocol = ID(spl[0]), spl[1] 85 86 // get host and port 87 host, portStr, err := net.SplitHostPort(addrWithoutProtocol) 88 if err != nil { 89 return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} 90 } 91 if len(host) == 0 { 92 return nil, ErrNetAddressInvalid{ 93 addrWithoutProtocol, 94 errors.New("host is empty")} 95 } 96 97 ip := net.ParseIP(host) 98 if ip == nil { 99 ips, err := net.LookupIP(host) 100 if err != nil { 101 return nil, ErrNetAddressLookup{host, err} 102 } 103 ip = ips[0] 104 } 105 106 port, err := strconv.ParseUint(portStr, 10, 16) 107 if err != nil { 108 return nil, ErrNetAddressInvalid{portStr, err} 109 } 110 111 na := NewNetAddressIPPort(ip, uint16(port)) 112 na.ID = id 113 return na, nil 114 } 115 116 // NewNetAddressStrings returns an array of NetAddress'es build using 117 // the provided strings. 118 func NewNetAddressStrings(addrs []string) ([]*NetAddress, []error) { 119 netAddrs := make([]*NetAddress, 0) 120 errs := make([]error, 0) 121 for _, addr := range addrs { 122 netAddr, err := NewNetAddressString(addr) 123 if err != nil { 124 errs = append(errs, err) 125 } else { 126 netAddrs = append(netAddrs, netAddr) 127 } 128 } 129 return netAddrs, errs 130 } 131 132 // NewNetAddressIPPort returns a new NetAddress using the provided IP 133 // and port number. 134 func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress { 135 return &NetAddress{ 136 IP: ip, 137 Port: port, 138 } 139 } 140 141 // Equals reports whether na and other are the same addresses, 142 // including their ID, IP, and Port. 143 func (na *NetAddress) Equals(other interface{}) bool { 144 if o, ok := other.(*NetAddress); ok { 145 return na.String() == o.String() 146 } 147 return false 148 } 149 150 // Same returns true is na has the same non-empty ID or DialString as other. 151 func (na *NetAddress) Same(other interface{}) bool { 152 if o, ok := other.(*NetAddress); ok { 153 if na.DialString() == o.DialString() { 154 return true 155 } 156 if na.ID != "" && na.ID == o.ID { 157 return true 158 } 159 } 160 return false 161 } 162 163 // String representation: <ID>@<IP>:<PORT> 164 func (na *NetAddress) String() string { 165 if na == nil { 166 return "<nil-NetAddress>" 167 } 168 if na.str == "" { 169 addrStr := na.DialString() 170 if na.ID != "" { 171 addrStr = IDAddressString(na.ID, addrStr) 172 } 173 na.str = addrStr 174 } 175 return na.str 176 } 177 178 func (na *NetAddress) DialString() string { 179 if na == nil { 180 return "<nil-NetAddress>" 181 } 182 return net.JoinHostPort( 183 na.IP.String(), 184 strconv.FormatUint(uint64(na.Port), 10), 185 ) 186 } 187 188 // Dial calls net.Dial on the address. 189 func (na *NetAddress) Dial() (net.Conn, error) { 190 conn, err := net.Dial("tcp", na.DialString()) 191 if err != nil { 192 return nil, err 193 } 194 return conn, nil 195 } 196 197 // DialTimeout calls net.DialTimeout on the address. 198 func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { 199 conn, err := net.DialTimeout("tcp", na.DialString(), timeout) 200 if err != nil { 201 return nil, err 202 } 203 return conn, nil 204 } 205 206 // Routable returns true if the address is routable. 207 func (na *NetAddress) Routable() bool { 208 if err := na.Valid(); err != nil { 209 return false 210 } 211 // TODO(oga) bitcoind doesn't include RFC3849 here, but should we? 212 return !(na.RFC1918() || na.RFC3927() || na.RFC4862() || 213 na.RFC4193() || na.RFC4843() || na.Local()) 214 } 215 216 // For IPv4 these are either a 0 or all bits set address. For IPv6 a zero 217 // address or one that matches the RFC3849 documentation address format. 218 func (na *NetAddress) Valid() error { 219 if err := validateID(na.ID); err != nil { 220 return errors.Wrap(err, "invalid ID") 221 } 222 223 if na.IP == nil { 224 return errors.New("no IP") 225 } 226 if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) { 227 return errors.New("invalid IP") 228 } 229 return nil 230 } 231 232 // HasID returns true if the address has an ID. 233 // NOTE: It does not check whether the ID is valid or not. 234 func (na *NetAddress) HasID() bool { 235 return string(na.ID) != "" 236 } 237 238 // Local returns true if it is a local address. 239 func (na *NetAddress) Local() bool { 240 return na.IP.IsLoopback() || zero4.Contains(na.IP) 241 } 242 243 // ReachabilityTo checks whenever o can be reached from na. 244 func (na *NetAddress) ReachabilityTo(o *NetAddress) int { 245 const ( 246 Unreachable = 0 247 Default = iota 248 Teredo 249 Ipv6Weak 250 Ipv4 251 Ipv6Strong 252 ) 253 switch { 254 case !na.Routable(): 255 return Unreachable 256 case na.RFC4380(): 257 switch { 258 case !o.Routable(): 259 return Default 260 case o.RFC4380(): 261 return Teredo 262 case o.IP.To4() != nil: 263 return Ipv4 264 default: // ipv6 265 return Ipv6Weak 266 } 267 case na.IP.To4() != nil: 268 if o.Routable() && o.IP.To4() != nil { 269 return Ipv4 270 } 271 return Default 272 default: /* ipv6 */ 273 var tunnelled bool 274 // Is our v6 is tunnelled? 275 if o.RFC3964() || o.RFC6052() || o.RFC6145() { 276 tunnelled = true 277 } 278 switch { 279 case !o.Routable(): 280 return Default 281 case o.RFC4380(): 282 return Teredo 283 case o.IP.To4() != nil: 284 return Ipv4 285 case tunnelled: 286 // only prioritise ipv6 if we aren't tunnelling it. 287 return Ipv6Weak 288 } 289 return Ipv6Strong 290 } 291 } 292 293 // RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) 294 // RFC3849: IPv6 Documentation address (2001:0DB8::/32) 295 // RFC3927: IPv4 Autoconfig (169.254.0.0/16) 296 // RFC3964: IPv6 6to4 (2002::/16) 297 // RFC4193: IPv6 unique local (FC00::/7) 298 // RFC4380: IPv6 Teredo tunneling (2001::/32) 299 // RFC4843: IPv6 ORCHID: (2001:10::/28) 300 // RFC4862: IPv6 Autoconfig (FE80::/64) 301 // RFC6052: IPv6 well known prefix (64:FF9B::/96) 302 // RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96 303 var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)} 304 var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)} 305 var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)} 306 var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)} 307 var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)} 308 var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)} 309 var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)} 310 var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)} 311 var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)} 312 var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)} 313 var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)} 314 var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)} 315 var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)} 316 var ( 317 // onionCatNet defines the IPv6 address block used to support Tor. 318 // bitcoind encodes a .onion address as a 16 byte number by decoding the 319 // address prior to the .onion (i.e. the key hash) base32 into a ten 320 // byte number. It then stores the first 6 bytes of the address as 321 // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. 322 // 323 // This is the same range used by OnionCat, which is part part of the 324 // RFC4193 unique local IPv6 range. 325 // 326 // In summary the format is: 327 // { magic 6 bytes, 10 bytes base32 decode of key hash } 328 onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128) 329 ) 330 331 // ipNet returns a net.IPNet struct given the passed IP address string, number 332 // of one bits to include at the start of the mask, and the total number of bits 333 // for the mask. 334 func ipNet(ip string, ones, bits int) net.IPNet { 335 return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)} 336 } 337 338 func (na *NetAddress) RFC1918() bool { 339 return rfc1918_10.Contains(na.IP) || 340 rfc1918_192.Contains(na.IP) || 341 rfc1918_172.Contains(na.IP) 342 } 343 func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) } 344 func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) } 345 func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) } 346 func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) } 347 func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) } 348 func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) } 349 func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) } 350 func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) } 351 func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) } 352 func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) } 353 354 func removeProtocolIfDefined(addr string) string { 355 if strings.Contains(addr, "://") { 356 return strings.Split(addr, "://")[1] 357 } 358 return addr 359 360 } 361 362 func validateID(id ID) error { 363 if len(id) == 0 { 364 return errors.New("no ID") 365 } 366 idBytes, err := hex.DecodeString(string(id)) 367 if err != nil { 368 return err 369 } 370 if len(idBytes) != IDByteLength { 371 return fmt.Errorf("invalid hex length - got %d, expected %d", len(idBytes), IDByteLength) 372 } 373 return nil 374 }