github.com/MetalBlockchain/metalgo@v1.11.9/nat/no_router.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package nat 5 6 import ( 7 "errors" 8 "net" 9 "net/netip" 10 "time" 11 ) 12 13 var ( 14 _ Router = (*noRouter)(nil) 15 16 errNoRouterCantMapPorts = errors.New("can't map ports without a known router") 17 errFetchingIP = errors.New("getting outbound IP failed") 18 ) 19 20 const googleDNSServer = "8.8.8.8:80" 21 22 type noRouter struct { 23 ip netip.Addr 24 ipErr error 25 } 26 27 func (noRouter) SupportsNAT() bool { 28 return false 29 } 30 31 func (noRouter) MapPort(uint16, uint16, string, time.Duration) error { 32 return errNoRouterCantMapPorts 33 } 34 35 func (noRouter) UnmapPort(uint16, uint16) error { 36 return nil 37 } 38 39 func (r noRouter) ExternalIP() (netip.Addr, error) { 40 return r.ip, r.ipErr 41 } 42 43 func getOutboundIP() (netip.Addr, error) { 44 conn, err := net.Dial("udp", googleDNSServer) 45 if err != nil { 46 return netip.Addr{}, err 47 } 48 49 localAddr := conn.LocalAddr() 50 if err := conn.Close(); err != nil { 51 return netip.Addr{}, err 52 } 53 54 udpAddr, ok := localAddr.(*net.UDPAddr) 55 if !ok { 56 return netip.Addr{}, errFetchingIP 57 } 58 addr := udpAddr.AddrPort().Addr() 59 if addr.Is4In6() { 60 addr = addr.Unmap() 61 } 62 return addr, nil 63 } 64 65 // NewNoRouter returns a router that assumes the network is public 66 func NewNoRouter() Router { 67 ip, err := getOutboundIP() 68 return &noRouter{ 69 ip: ip, 70 ipErr: err, 71 } 72 }