github.com/metacubex/mihomo@v1.18.5/transport/vmess/vmess.go (about) 1 package vmess 2 3 import ( 4 "fmt" 5 "net" 6 "runtime" 7 8 "github.com/metacubex/mihomo/common/utils" 9 10 "github.com/gofrs/uuid/v5" 11 "github.com/zhangyunhao116/fastrand" 12 ) 13 14 // Version of vmess 15 const Version byte = 1 16 17 // Request Options 18 const ( 19 OptionChunkStream byte = 1 20 OptionChunkMasking byte = 4 21 ) 22 23 // Security type vmess 24 type Security = byte 25 26 // Cipher types 27 const ( 28 SecurityAES128GCM Security = 3 29 SecurityCHACHA20POLY1305 Security = 4 30 SecurityNone Security = 5 31 ) 32 33 // CipherMapping return 34 var CipherMapping = map[string]byte{ 35 "none": SecurityNone, 36 "aes-128-gcm": SecurityAES128GCM, 37 "chacha20-poly1305": SecurityCHACHA20POLY1305, 38 } 39 40 // Command types 41 const ( 42 CommandTCP byte = 1 43 CommandUDP byte = 2 44 ) 45 46 // Addr types 47 const ( 48 AtypIPv4 byte = 1 49 AtypDomainName byte = 2 50 AtypIPv6 byte = 3 51 ) 52 53 // DstAddr store destination address 54 type DstAddr struct { 55 UDP bool 56 AddrType byte 57 Addr []byte 58 Port uint 59 } 60 61 // Client is vmess connection generator 62 type Client struct { 63 user []*ID 64 uuid *uuid.UUID 65 security Security 66 isAead bool 67 } 68 69 // Config of vmess 70 type Config struct { 71 UUID string 72 AlterID uint16 73 Security string 74 Port string 75 HostName string 76 IsAead bool 77 } 78 79 // StreamConn return a Conn with net.Conn and DstAddr 80 func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) { 81 r := fastrand.Intn(len(c.user)) 82 return newConn(conn, c.user[r], dst, c.security, c.isAead) 83 } 84 85 // NewClient return Client instance 86 func NewClient(config Config) (*Client, error) { 87 uid, err := utils.UUIDMap(config.UUID) 88 if err != nil { 89 return nil, err 90 } 91 92 var security Security 93 switch config.Security { 94 case "aes-128-gcm": 95 security = SecurityAES128GCM 96 case "chacha20-poly1305": 97 security = SecurityCHACHA20POLY1305 98 case "none": 99 security = SecurityNone 100 case "auto": 101 security = SecurityCHACHA20POLY1305 102 if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" { 103 security = SecurityAES128GCM 104 } 105 default: 106 return nil, fmt.Errorf("unknown security type: %s", config.Security) 107 } 108 109 return &Client{ 110 user: newAlterIDs(newID(&uid), config.AlterID), 111 uuid: &uid, 112 security: security, 113 isAead: config.IsAead, 114 }, nil 115 }