123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- package constant
- import (
- "encoding/json"
- "fmt"
- "net"
- "net/netip"
- "strconv"
- "github.com/metacubex/mihomo/transport/socks5"
- )
- // Socks addr type
- const (
- TCP NetWork = iota
- UDP
- ALLNet
- InvalidNet = 0xff
- )
- const (
- HTTP Type = iota
- HTTPS
- SOCKS4
- SOCKS5
- SHADOWSOCKS
- VMESS
- REDIR
- TPROXY
- TUNNEL
- TUN
- TUIC
- HYSTERIA2
- INNER
- )
- type NetWork int
- func (n NetWork) String() string {
- switch n {
- case TCP:
- return "tcp"
- case UDP:
- return "udp"
- case ALLNet:
- return "all"
- default:
- return "invalid"
- }
- }
- func (n NetWork) MarshalJSON() ([]byte, error) {
- return json.Marshal(n.String())
- }
- type Type int
- func (t Type) String() string {
- switch t {
- case HTTP:
- return "HTTP"
- case HTTPS:
- return "HTTPS"
- case SOCKS4:
- return "Socks4"
- case SOCKS5:
- return "Socks5"
- case SHADOWSOCKS:
- return "ShadowSocks"
- case VMESS:
- return "Vmess"
- case REDIR:
- return "Redir"
- case TPROXY:
- return "TProxy"
- case TUNNEL:
- return "Tunnel"
- case TUN:
- return "Tun"
- case TUIC:
- return "Tuic"
- case HYSTERIA2:
- return "Hysteria2"
- case INNER:
- return "Inner"
- default:
- return "Unknown"
- }
- }
- func ParseType(t string) (*Type, error) {
- var res Type
- switch t {
- case "HTTP":
- res = HTTP
- case "HTTPS":
- res = HTTPS
- case "SOCKS4":
- res = SOCKS4
- case "SOCKS5":
- res = SOCKS5
- case "SHADOWSOCKS":
- res = SHADOWSOCKS
- case "VMESS":
- res = VMESS
- case "REDIR":
- res = REDIR
- case "TPROXY":
- res = TPROXY
- case "TUNNEL":
- res = TUNNEL
- case "TUN":
- res = TUN
- case "TUIC":
- res = TUIC
- case "HYSTERIA2":
- res = HYSTERIA2
- case "INNER":
- res = INNER
- default:
- return nil, fmt.Errorf("unknown type: %s", t)
- }
- return &res, nil
- }
- func (t Type) MarshalJSON() ([]byte, error) {
- return json.Marshal(t.String())
- }
- // Metadata is used to store connection address
- type Metadata struct {
- NetWork NetWork `json:"network"`
- Type Type `json:"type"`
- SrcIP netip.Addr `json:"sourceIP"`
- DstIP netip.Addr `json:"destinationIP"`
- DstGeoIP []string `json:"destinationGeoIP"` // can be nil if never queried, empty slice if got no result
- DstIPASN string `json:"destinationIPASN"`
- SrcPort uint16 `json:"sourcePort,string"` // `,string` is used to compatible with old version json output
- DstPort uint16 `json:"destinationPort,string"` // `,string` is used to compatible with old version json output
- InIP netip.Addr `json:"inboundIP"`
- InPort uint16 `json:"inboundPort,string"` // `,string` is used to compatible with old version json output
- InName string `json:"inboundName"`
- InUser string `json:"inboundUser"`
- Host string `json:"host"`
- DNSMode DNSMode `json:"dnsMode"`
- Uid uint32 `json:"uid"`
- Process string `json:"process"`
- ProcessPath string `json:"processPath"`
- SpecialProxy string `json:"specialProxy"`
- SpecialRules string `json:"specialRules"`
- RemoteDst string `json:"remoteDestination"`
- DSCP uint8 `json:"dscp"`
- RawSrcAddr net.Addr `json:"-"`
- RawDstAddr net.Addr `json:"-"`
- // Only domain rule
- SniffHost string `json:"sniffHost"`
- }
- func (m *Metadata) RemoteAddress() string {
- return net.JoinHostPort(m.String(), strconv.FormatUint(uint64(m.DstPort), 10))
- }
- func (m *Metadata) SourceAddress() string {
- return net.JoinHostPort(m.SrcIP.String(), strconv.FormatUint(uint64(m.SrcPort), 10))
- }
- func (m *Metadata) SourceAddrPort() netip.AddrPort {
- return netip.AddrPortFrom(m.SrcIP.Unmap(), m.SrcPort)
- }
- func (m *Metadata) SourceDetail() string {
- if m.Type == INNER {
- return fmt.Sprintf("%s", MihomoName)
- }
- switch {
- case m.Process != "" && m.Uid != 0:
- return fmt.Sprintf("%s(%s, uid=%d)", m.SourceAddress(), m.Process, m.Uid)
- case m.Uid != 0:
- return fmt.Sprintf("%s(uid=%d)", m.SourceAddress(), m.Uid)
- case m.Process != "":
- return fmt.Sprintf("%s(%s)", m.SourceAddress(), m.Process)
- default:
- return fmt.Sprintf("%s", m.SourceAddress())
- }
- }
- func (m *Metadata) SourceValid() bool {
- return m.SrcPort != 0 && m.SrcIP.IsValid()
- }
- func (m *Metadata) AddrType() int {
- switch true {
- case m.Host != "" || !m.DstIP.IsValid():
- return socks5.AtypDomainName
- case m.DstIP.Is4():
- return socks5.AtypIPv4
- default:
- return socks5.AtypIPv6
- }
- }
- func (m *Metadata) Resolved() bool {
- return m.DstIP.IsValid()
- }
- func (m *Metadata) RuleHost() string {
- if len(m.SniffHost) == 0 {
- return m.Host
- } else {
- return m.SniffHost
- }
- }
- // Pure is used to solve unexpected behavior
- // when dialing proxy connection in DNSMapping mode.
- func (m *Metadata) Pure() *Metadata {
- if (m.DNSMode == DNSMapping || m.DNSMode == DNSHosts) && m.DstIP.IsValid() {
- copyM := *m
- copyM.Host = ""
- return ©M
- }
- return m
- }
- func (m *Metadata) AddrPort() netip.AddrPort {
- return netip.AddrPortFrom(m.DstIP.Unmap(), m.DstPort)
- }
- func (m *Metadata) UDPAddr() *net.UDPAddr {
- if m.NetWork != UDP || !m.DstIP.IsValid() {
- return nil
- }
- return net.UDPAddrFromAddrPort(m.AddrPort())
- }
- func (m *Metadata) String() string {
- if m.Host != "" {
- return m.Host
- } else if m.DstIP.IsValid() {
- return m.DstIP.String()
- } else {
- return "<nil>"
- }
- }
- func (m *Metadata) Valid() bool {
- return m.Host != "" || m.DstIP.IsValid()
- }
- func (m *Metadata) SetRemoteAddr(addr net.Addr) error {
- if addr == nil {
- return nil
- }
- if rawAddr, ok := addr.(interface{ RawAddr() net.Addr }); ok {
- if rawAddr := rawAddr.RawAddr(); rawAddr != nil {
- if err := m.SetRemoteAddr(rawAddr); err == nil {
- return nil
- }
- }
- }
- if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { // *net.TCPAddr, *net.UDPAddr, M.Socksaddr
- if addrPort := addr.AddrPort(); addrPort.Port() != 0 {
- m.DstPort = addrPort.Port()
- if addrPort.IsValid() { // sing's M.Socksaddr maybe return an invalid AddrPort if it's a DomainName
- m.DstIP = addrPort.Addr().Unmap()
- return nil
- } else {
- if addr, ok := addr.(interface{ AddrString() string }); ok { // must be sing's M.Socksaddr
- m.Host = addr.AddrString() // actually is M.Socksaddr.Fqdn
- return nil
- }
- }
- }
- }
- return m.SetRemoteAddress(addr.String())
- }
- func (m *Metadata) SetRemoteAddress(rawAddress string) error {
- host, port, err := net.SplitHostPort(rawAddress)
- if err != nil {
- return err
- }
- var uint16Port uint16
- if port, err := strconv.ParseUint(port, 10, 16); err == nil {
- uint16Port = uint16(port)
- }
- if ip, err := netip.ParseAddr(host); err != nil {
- m.Host = host
- m.DstIP = netip.Addr{}
- } else {
- m.Host = ""
- m.DstIP = ip.Unmap()
- }
- m.DstPort = uint16Port
- return nil
- }
|