From c0e51f855650fe93676bc43bec6f31649eb8cbf2 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:20:40 +0800 Subject: [PATCH] Change: use uint16 for Metadata SrcPort and DstPort --- adapter/adapter.go | 5 ++++- adapter/inbound/http.go | 7 +++---- adapter/inbound/https.go | 7 +++---- adapter/inbound/packet.go | 4 ++-- adapter/inbound/socket.go | 7 +++---- adapter/inbound/util.go | 30 +++++++++++++++--------------- adapter/outbound/snell.go | 6 ++---- adapter/outbound/util.go | 4 +--- adapter/outbound/vmess.go | 3 +-- adapter/outboundgroup/util.go | 8 +++++--- constant/metadata.go | 24 +++++++++++++++++------- rule/port.go | 10 +++++----- tunnel/tunnel.go | 6 ++---- 13 files changed, 63 insertions(+), 58 deletions(-) diff --git a/adapter/adapter.go b/adapter/adapter.go index 020fe91..7feae63 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "net/url" + "strconv" "time" "github.com/Dreamacro/clash/common/queue" @@ -194,10 +195,12 @@ func urlToMetadata(rawURL string) (addr C.Metadata, err error) { } } + p, _ := strconv.ParseUint(port, 10, 16) + addr = C.Metadata{ Host: u.Hostname(), DstIP: nil, - DstPort: port, + DstPort: C.Port(p), } return } diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 5242c8e..4344c37 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -3,7 +3,6 @@ package inbound import ( "net" "net/netip" - "strconv" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" @@ -15,14 +14,14 @@ func NewHTTP(target socks5.Addr, source net.Addr, originTarget net.Addr, conn ne metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP - if ip, port, err := parseAddr(source.String()); err == nil { + if ip, port, err := parseAddr(source); err == nil { metadata.SrcIP = ip - metadata.SrcPort = port + metadata.SrcPort = C.Port(port) } if originTarget != nil { if addrPort, err := netip.ParseAddrPort(originTarget.String()); err == nil { metadata.OriginDst = addrPort - metadata.InboundPort = strconv.Itoa(int(addrPort.Port())) + metadata.InboundPort = addrPort.Port() } } return context.NewConnContext(conn, metadata) diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index 6d39468..eae150a 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -4,7 +4,6 @@ import ( "net" "net/http" "net/netip" - "strconv" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" @@ -14,13 +13,13 @@ import ( func NewHTTPS(request *http.Request, conn net.Conn) *context.ConnContext { metadata := parseHTTPAddr(request) metadata.Type = C.HTTPCONNECT - if ip, port, err := parseAddr(conn.RemoteAddr().String()); err == nil { + if ip, port, err := parseAddr(conn.RemoteAddr()); err == nil { metadata.SrcIP = ip - metadata.SrcPort = port + metadata.SrcPort = C.Port(port) } if addrPort, err := netip.ParseAddrPort(conn.LocalAddr().String()); err == nil { metadata.OriginDst = addrPort - metadata.InboundPort = strconv.Itoa(int(addrPort.Port())) + metadata.InboundPort = addrPort.Port() } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index 2e1e728..dc1b4d1 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -24,9 +24,9 @@ func NewPacket(target socks5.Addr, originTarget net.Addr, packet C.UDPPacket, so metadata := parseSocksAddr(target) metadata.NetWork = C.UDP metadata.Type = source - if ip, port, err := parseAddr(packet.LocalAddr().String()); err == nil { + if ip, port, err := parseAddr(packet.LocalAddr()); err == nil { metadata.SrcIP = ip - metadata.SrcPort = port + metadata.SrcPort = C.Port(port) } if originTarget != nil { if addrPort, err := netip.ParseAddrPort(originTarget.String()); err == nil { diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index efe9e5a..9bec0ce 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -3,7 +3,6 @@ package inbound import ( "net" "net/netip" - "strconv" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" @@ -15,13 +14,13 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type) *context.ConnCo metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = source - if ip, port, err := parseAddr(conn.RemoteAddr().String()); err == nil { + if ip, port, err := parseAddr(conn.RemoteAddr()); err == nil { metadata.SrcIP = ip - metadata.SrcPort = port + metadata.SrcPort = C.Port(port) } if addrPort, err := netip.ParseAddrPort(conn.LocalAddr().String()); err == nil { metadata.OriginDst = addrPort - metadata.InboundPort = strconv.Itoa(int(addrPort.Port())) + metadata.InboundPort = addrPort.Port() } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/util.go b/adapter/inbound/util.go index 4f13927..6f3d4a7 100644 --- a/adapter/inbound/util.go +++ b/adapter/inbound/util.go @@ -1,11 +1,13 @@ package inbound import ( + "fmt" "net" "net/http" "strconv" "strings" + "github.com/Dreamacro/clash/common/util" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/transport/socks5" ) @@ -17,15 +19,15 @@ func parseSocksAddr(target socks5.Addr) *C.Metadata { case socks5.AtypDomainName: // trim for FQDN metadata.Host = strings.TrimRight(string(target[2:2+target[1]]), ".") - metadata.DstPort = strconv.Itoa((int(target[2+target[1]]) << 8) | int(target[2+target[1]+1])) + metadata.DstPort = C.Port((int(target[2+target[1]]) << 8) | int(target[2+target[1]+1])) case socks5.AtypIPv4: ip := net.IP(target[1 : 1+net.IPv4len]) metadata.DstIP = ip - metadata.DstPort = strconv.Itoa((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1])) + metadata.DstPort = C.Port((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1])) case socks5.AtypIPv6: ip := net.IP(target[1 : 1+net.IPv6len]) metadata.DstIP = ip - metadata.DstPort = strconv.Itoa((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1])) + metadata.DstPort = C.Port((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1])) } return metadata @@ -33,10 +35,7 @@ func parseSocksAddr(target socks5.Addr) *C.Metadata { func parseHTTPAddr(request *http.Request) *C.Metadata { host := request.URL.Hostname() - port := request.URL.Port() - if port == "" { - port = "80" - } + port, _ := strconv.ParseUint(util.EmptyOr(request.URL.Port(), "80"), 10, 16) // trim FQDN (#737) host = strings.TrimRight(host, ".") @@ -45,7 +44,7 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { NetWork: C.TCP, Host: host, DstIP: nil, - DstPort: port, + DstPort: C.Port(port), } if ip := net.ParseIP(host); ip != nil { @@ -55,12 +54,13 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { return metadata } -func parseAddr(addr string) (net.IP, string, error) { - host, port, err := net.SplitHostPort(addr) - if err != nil { - return nil, "", err +func parseAddr(addr net.Addr) (net.IP, int, error) { + switch a := addr.(type) { + case *net.TCPAddr: + return a.IP, a.Port, nil + case *net.UDPAddr: + return a.IP, a.Port, nil + default: + return nil, 0, fmt.Errorf("unknown address type %s", addr.String()) } - - ip := net.ParseIP(host) - return ip, port, nil } diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index ab79190..b8fb5a3 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -53,8 +53,7 @@ func streamConn(c net.Conn, option streamOption) *snell.Snell { // StreamConn implements C.ProxyAdapter func (s *Snell) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption}) - port, _ := strconv.ParseUint(metadata.DstPort, 10, 16) - err := snell.WriteHeader(c, metadata.String(), uint(port), s.version) + err := snell.WriteHeader(c, metadata.String(), uint(metadata.DstPort), s.version) return c, err } @@ -66,8 +65,7 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d return nil, err } - port, _ := strconv.ParseUint(metadata.DstPort, 10, 16) - if err = snell.WriteHeader(c, metadata.String(), uint(port), s.version); err != nil { + if err = snell.WriteHeader(c, metadata.String(), uint(metadata.DstPort), s.version); err != nil { c.Close() return nil, err } diff --git a/adapter/outbound/util.go b/adapter/outbound/util.go index 9166d71..83ace7b 100644 --- a/adapter/outbound/util.go +++ b/adapter/outbound/util.go @@ -2,7 +2,6 @@ package outbound import ( "net" - "strconv" "time" "github.com/Dreamacro/clash/component/resolver" @@ -25,7 +24,6 @@ func serializesSocksAddr(metadata *C.Metadata) []byte { addrType := metadata.AddrType() buf.PutUint8(uint8(addrType)) - p, _ := strconv.ParseUint(metadata.DstPort, 10, 16) switch addrType { case socks5.AtypDomainName: buf.PutUint8(uint8(len(metadata.Host))) @@ -36,7 +34,7 @@ func serializesSocksAddr(metadata *C.Metadata) []byte { buf.PutSlice(metadata.DstIP.To16()) } - buf.PutUint16be(uint16(p)) + buf.PutUint16be(uint16(metadata.DstPort)) return buf.Bytes() } diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index d5d74f4..dd3ba44 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -354,12 +354,11 @@ func parseVmessAddr(metadata *C.Metadata) *vmess.DstAddr { copy(addr[1:], []byte(metadata.Host)) } - port, _ := strconv.ParseUint(metadata.DstPort, 10, 16) return &vmess.DstAddr{ UDP: metadata.NetWork == C.UDP, AddrType: addrType, Addr: addr, - Port: uint(port), + Port: uint(metadata.DstPort), } } diff --git a/adapter/outboundgroup/util.go b/adapter/outboundgroup/util.go index 1ec0254..15cb87e 100644 --- a/adapter/outboundgroup/util.go +++ b/adapter/outboundgroup/util.go @@ -3,6 +3,7 @@ package outboundgroup import ( "fmt" "net" + "strconv" "time" C "github.com/Dreamacro/clash/constant" @@ -16,18 +17,19 @@ func addrToMetadata(rawAddress string) (addr *C.Metadata, err error) { } ip := net.ParseIP(host) + p, _ := strconv.ParseUint(port, 10, 16) if ip == nil { addr = &C.Metadata{ Host: host, DstIP: nil, - DstPort: port, + DstPort: C.Port(p), } return } else if ip4 := ip.To4(); ip4 != nil { addr = &C.Metadata{ Host: "", DstIP: ip4, - DstPort: port, + DstPort: C.Port(p), } return } @@ -35,7 +37,7 @@ func addrToMetadata(rawAddress string) (addr *C.Metadata, err error) { addr = &C.Metadata{ Host: "", DstIP: ip, - DstPort: port, + DstPort: C.Port(p), } return } diff --git a/constant/metadata.go b/constant/metadata.go index d8d9eb7..32b1e4b 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -67,9 +67,9 @@ type Metadata struct { Type Type `json:"type"` SrcIP net.IP `json:"sourceIP"` DstIP net.IP `json:"destinationIP"` - SrcPort string `json:"sourcePort"` - DstPort string `json:"destinationPort"` - InboundPort string `json:"inboundPort"` + SrcPort Port `json:"sourcePort"` + DstPort Port `json:"destinationPort"` + InboundPort uint16 `json:"inboundPort"` Host string `json:"host"` DNSMode DNSMode `json:"dnsMode"` ProcessPath string `json:"processPath"` @@ -79,11 +79,11 @@ type Metadata struct { } func (m *Metadata) RemoteAddress() string { - return net.JoinHostPort(m.String(), m.DstPort) + return net.JoinHostPort(m.String(), m.DstPort.String()) } func (m *Metadata) SourceAddress() string { - return net.JoinHostPort(m.SrcIP.String(), m.SrcPort) + return net.JoinHostPort(m.SrcIP.String(), m.SrcPort.String()) } func (m *Metadata) AddrType() int { @@ -117,10 +117,9 @@ func (m *Metadata) UDPAddr() *net.UDPAddr { if m.NetWork != UDP || m.DstIP == nil { return nil } - port, _ := strconv.ParseUint(m.DstPort, 10, 16) return &net.UDPAddr{ IP: m.DstIP, - Port: int(port), + Port: int(m.DstPort), } } @@ -137,3 +136,14 @@ func (m *Metadata) String() string { func (m *Metadata) Valid() bool { return m.Host != "" || m.DstIP != nil } + +// Port is used to compatible with old version +type Port uint16 + +func (n Port) MarshalJSON() ([]byte, error) { + return json.Marshal(n.String()) +} + +func (n Port) String() string { + return strconv.FormatUint(uint64(n), 10) +} diff --git a/rule/port.go b/rule/port.go index ea58720..3db1212 100644 --- a/rule/port.go +++ b/rule/port.go @@ -17,7 +17,7 @@ const ( type Port struct { adapter string - port string + port C.Port portType PortType } @@ -41,7 +41,7 @@ func (p *Port) Match(metadata *C.Metadata) bool { case PortTypeDest: return metadata.DstPort == p.port case PortTypeInbound: - return metadata.InboundPort == p.port + return metadata.InboundPort == uint16(p.port) default: panic(fmt.Errorf("unknown port type: %v", p.portType)) } @@ -52,7 +52,7 @@ func (p *Port) Adapter() string { } func (p *Port) Payload() string { - return p.port + return p.port.String() } func (p *Port) ShouldResolveIP() bool { @@ -64,13 +64,13 @@ func (p *Port) ShouldFindProcess() bool { } func NewPort(port string, adapter string, portType PortType) (*Port, error) { - _, err := strconv.ParseUint(port, 10, 16) + p, err := strconv.ParseUint(port, 10, 16) if err != nil { return nil, errPayload } return &Port{ adapter: adapter, - port: port, + port: C.Port(p), portType: portType, }, nil } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index bde4cba..693068c 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -6,7 +6,6 @@ import ( "net" "net/netip" "runtime" - "strconv" "sync" "time" @@ -402,10 +401,9 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { processFound = true srcIP, ok := netip.AddrFromSlice(metadata.SrcIP) - srcPort, err := strconv.ParseUint(metadata.SrcPort, 10, 16) - if ok && err == nil && metadata.OriginDst.IsValid() { + if ok && metadata.OriginDst.IsValid() { srcIP = srcIP.Unmap() - path, err := P.FindProcessPath(metadata.NetWork.String(), netip.AddrPortFrom(srcIP, uint16(srcPort)), metadata.OriginDst) + path, err := P.FindProcessPath(metadata.NetWork.String(), netip.AddrPortFrom(srcIP, uint16(metadata.SrcPort)), metadata.OriginDst) if err != nil { log.Debugln("[Process] find process %s: %v", metadata.String(), err) } else {