diff --git a/metadata/metadata.go b/metadata/metadata.go index 63755db..0e2a0da 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -2,26 +2,34 @@ package metadata import ( "net" - "strconv" + "net/netip" ) // Metadata contains metadata of transport protocol sessions. type Metadata struct { - Network Network `json:"network"` - SrcIP net.IP `json:"sourceIP"` - MidIP net.IP `json:"dialerIP"` - DstIP net.IP `json:"destinationIP"` - SrcPort uint16 `json:"sourcePort"` - MidPort uint16 `json:"dialerPort"` - DstPort uint16 `json:"destinationPort"` + Network Network `json:"network"` + SrcIP netip.Addr `json:"sourceIP"` + MidIP netip.Addr `json:"dialerIP"` + DstIP netip.Addr `json:"destinationIP"` + SrcPort uint16 `json:"sourcePort"` + MidPort uint16 `json:"dialerPort"` + DstPort uint16 `json:"destinationPort"` +} + +func (m *Metadata) DestinationAddrPort() netip.AddrPort { + return netip.AddrPortFrom(m.DstIP, m.DstPort) } func (m *Metadata) DestinationAddress() string { - return net.JoinHostPort(m.DstIP.String(), strconv.FormatUint(uint64(m.DstPort), 10)) + return m.DestinationAddrPort().String() +} + +func (m *Metadata) SourceAddrPort() netip.AddrPort { + return netip.AddrPortFrom(m.SrcIP, m.SrcPort) } func (m *Metadata) SourceAddress() string { - return net.JoinHostPort(m.SrcIP.String(), strconv.FormatUint(uint64(m.SrcPort), 10)) + return m.SourceAddrPort().String() } func (m *Metadata) Addr() net.Addr { @@ -29,23 +37,17 @@ func (m *Metadata) Addr() net.Addr { } func (m *Metadata) TCPAddr() *net.TCPAddr { - if m.Network != TCP || m.DstIP == nil { + if m.Network != TCP || !m.DstIP.IsValid() { return nil } - return &net.TCPAddr{ - IP: m.DstIP, - Port: int(m.DstPort), - } + return net.TCPAddrFromAddrPort(m.DestinationAddrPort()) } func (m *Metadata) UDPAddr() *net.UDPAddr { - if m.Network != UDP || m.DstIP == nil { + if m.Network != UDP || !m.DstIP.IsValid() { return nil } - return &net.UDPAddr{ - IP: m.DstIP, - Port: int(m.DstPort), - } + return net.UDPAddrFromAddrPort(m.DestinationAddrPort()) } // Addr implements the net.Addr interface. diff --git a/proxy/relay.go b/proxy/relay.go index b9858d1..2fba60a 100644 --- a/proxy/relay.go +++ b/proxy/relay.go @@ -243,7 +243,7 @@ func serializeRelayAddr(m *M.Metadata) *relay.AddrFeature { Host: m.DstIP.String(), Port: m.DstPort, } - if m.DstIP.To4() != nil { + if m.DstIP.Is4() { af.AType = relay.AddrIPv4 } else { af.AType = relay.AddrIPv6 diff --git a/proxy/socks5.go b/proxy/socks5.go index bdc9b04..290adae 100644 --- a/proxy/socks5.go +++ b/proxy/socks5.go @@ -186,5 +186,5 @@ func (pc *socksPacketConn) Close() error { } func serializeSocksAddr(m *M.Metadata) socks5.Addr { - return socks5.SerializeAddr("", m.DstIP, m.DstPort) + return socks5.SerializeAddr("", m.DstIP.AsSlice(), m.DstPort) } diff --git a/tunnel/addr.go b/tunnel/addr.go index eb7ed57..0db7444 100644 --- a/tunnel/addr.go +++ b/tunnel/addr.go @@ -2,26 +2,37 @@ package tunnel import ( "net" - "strconv" + "net/netip" + + "gvisor.dev/gvisor/pkg/tcpip" ) -// parseAddr parses net.Addr to IP and port. -func parseAddr(addr net.Addr) (net.IP, uint16) { - switch v := addr.(type) { - case *net.TCPAddr: - return v.IP, uint16(v.Port) - case *net.UDPAddr: - return v.IP, uint16(v.Port) - case nil: - return nil, 0 - default: - return parseAddrString(addr.String()) +// parseNetAddr parses net.Addr to IP and port. +func parseNetAddr(addr net.Addr) (netip.Addr, uint16) { + if addr == nil { + return netip.Addr{}, 0 } + if v, ok := addr.(interface { + AddrPort() netip.AddrPort + }); ok { + ap := v.AddrPort() + return ap.Addr(), ap.Port() + } + return parseAddrString(addr.String()) } // parseAddrString parses address string to IP and port. -func parseAddrString(addr string) (net.IP, uint16) { - host, port, _ := net.SplitHostPort(addr) - portInt, _ := strconv.ParseUint(port, 10, 16) - return net.ParseIP(host), uint16(portInt) +// It doesn't do any name resolution. +func parseAddrString(s string) (netip.Addr, uint16) { + ap, err := netip.ParseAddrPort(s) + if err != nil { + return netip.Addr{}, 0 + } + return ap.Addr(), ap.Port() +} + +// parseTCPIPAddress parses tcpip.Address to netip.Addr. +func parseTCPIPAddress(addr tcpip.Address) netip.Addr { + ip, _ := netip.AddrFromSlice(addr.AsSlice()) + return ip } diff --git a/tunnel/tcp.go b/tunnel/tcp.go index 90e6235..45af37c 100644 --- a/tunnel/tcp.go +++ b/tunnel/tcp.go @@ -20,9 +20,9 @@ func (t *Tunnel) handleTCPConn(originConn adapter.TCPConn) { id := originConn.ID() metadata := &M.Metadata{ Network: M.TCP, - SrcIP: net.IP(id.RemoteAddress.AsSlice()), + SrcIP: parseTCPIPAddress(id.RemoteAddress), SrcPort: id.RemotePort, - DstIP: net.IP(id.LocalAddress.AsSlice()), + DstIP: parseTCPIPAddress(id.LocalAddress), DstPort: id.LocalPort, } @@ -34,7 +34,7 @@ func (t *Tunnel) handleTCPConn(originConn adapter.TCPConn) { log.Warnf("[TCP] dial %s: %v", metadata.DestinationAddress(), err) return } - metadata.MidIP, metadata.MidPort = parseAddr(remoteConn.LocalAddr()) + metadata.MidIP, metadata.MidPort = parseNetAddr(remoteConn.LocalAddr()) remoteConn = statistic.NewTCPTracker(remoteConn, metadata, t.manager) defer remoteConn.Close() diff --git a/tunnel/udp.go b/tunnel/udp.go index f92af64..667a92b 100644 --- a/tunnel/udp.go +++ b/tunnel/udp.go @@ -20,9 +20,9 @@ func (t *Tunnel) handleUDPConn(uc adapter.UDPConn) { id := uc.ID() metadata := &M.Metadata{ Network: M.UDP, - SrcIP: net.IP(id.RemoteAddress.AsSlice()), + SrcIP: parseTCPIPAddress(id.RemoteAddress), SrcPort: id.RemotePort, - DstIP: net.IP(id.LocalAddress.AsSlice()), + DstIP: parseTCPIPAddress(id.LocalAddress), DstPort: id.LocalPort, } @@ -31,7 +31,7 @@ func (t *Tunnel) handleUDPConn(uc adapter.UDPConn) { log.Warnf("[UDP] dial %s: %v", metadata.DestinationAddress(), err) return } - metadata.MidIP, metadata.MidPort = parseAddr(pc.LocalAddr()) + metadata.MidIP, metadata.MidPort = parseNetAddr(pc.LocalAddr()) pc = statistic.NewUDPTracker(pc, metadata, t.manager) defer pc.Close()