github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/node/parser/vmess.go (about) 1 package parser 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "log/slog" 9 "net" 10 "strconv" 11 12 "github.com/Asutorufa/yuhaiin/pkg/log" 13 "github.com/Asutorufa/yuhaiin/pkg/protos/node/point" 14 "github.com/Asutorufa/yuhaiin/pkg/protos/node/protocol" 15 "github.com/Asutorufa/yuhaiin/pkg/protos/node/subscribe" 16 ) 17 18 func init() { 19 store.Store(subscribe.Type_vmess, func(data []byte) (*point.Point, error) { 20 //ParseLink parse vmess link 21 // eg: vmess://eyJob3N0IjoiIiwicGF0aCI6IiIsInRscyI6IiIsInZlcmlmeV9jZXJ0Ijp0cnV 22 // lLCJhZGQiOiIxMjcuMC4wLjEiLCJwb3J0IjowLCJhaWQiOjIsIm5ldCI6InRjcC 23 // IsInR5cGUiOiJub25lIiwidiI6IjIiLCJwcyI6Im5hbWUiLCJpZCI6ImNjY2MtY 24 // 2NjYy1kZGRkLWFhYS00NmExYWFhYWFhIiwiY2xhc3MiOjF9Cg 25 26 n := struct { 27 // address 28 Address string `json:"add,omitempty"` 29 Port any `json:"port,omitempty"` 30 // uuid 31 Uuid string `json:"id,omitempty"` 32 Security string `json:"security,omitempty"` 33 // alter id 34 AlterId any `json:"aid,omitempty"` 35 36 // name 37 Ps string `json:"ps,omitempty"` 38 Remark string `json:"remark,omitempty"` 39 40 // (tcp\kcp\ws\h2\quic) 41 Net string `json:"net,omitempty"` 42 43 // fake type [(none\http\srtp\utp\wechat-video) *tcp or kcp or QUIC] 44 Type string `json:"type,omitempty"` 45 HeaderType string `json:"headerType,omitempty"` 46 47 Tls string `json:"tls,omitempty"` 48 Sni string `json:"sni,omitempty"` 49 VerifyCert bool `json:"verify_cert,omitempty"` 50 51 // 1)http host(cut up with (,) ) 52 // 2)ws host 53 // 3)h2 host 54 // 4)QUIC security 55 Host string `json:"host,omitempty"` 56 // 1)ws path 57 // 2)h2 path 58 // 3)QUIC key/Kcp seed 59 Path string `json:"path,omitempty"` 60 61 V string `json:"v,omitempty"` 62 Class int64 `json:"class,omitempty"` 63 }{} 64 65 data = bytes.TrimRight(bytes.TrimSpace(bytes.TrimPrefix(data, []byte("vmess://"))), "=") 66 dst := make([]byte, base64.RawStdEncoding.DecodedLen(len(data))) 67 _, err := base64.RawStdEncoding.Decode(dst, data) 68 if err != nil { 69 log.Warn("base64 decode failed", slog.String("data", string(data)), slog.Any("err", err)) 70 } 71 if err := json.Unmarshal(trimJSON(dst, '{', '}'), &n); err != nil { 72 return nil, err 73 } 74 75 if n.Ps == "" { 76 n.Ps = n.Remark 77 } 78 79 if n.Host == "" { 80 n.Host = net.JoinHostPort(n.Address, fmt.Sprint(n.Port)) 81 } 82 83 if n.HeaderType == "" { 84 n.HeaderType = n.Type 85 } 86 87 port, err := strconv.ParseUint(fmt.Sprint(n.Port), 10, 16) 88 if err != nil { 89 return nil, fmt.Errorf("vmess port is not a number: %w", err) 90 } 91 92 simple := &protocol.Protocol_Simple{ 93 Simple: &protocol.Simple{ 94 Host: n.Address, 95 Port: int32(port), 96 }, 97 } 98 99 tlsProtocol := &protocol.Protocol{Protocol: &protocol.Protocol_None{None: &protocol.None{}}} 100 101 if n.Tls == "tls" { 102 if n.Sni == "" { 103 n.Sni, _, err = net.SplitHostPort(n.Host) 104 if err != nil { 105 log.Warn("split host and port failed", "err", err) 106 n.Sni = n.Host 107 } 108 } 109 110 tlsProtocol = &protocol.Protocol{ 111 Protocol: &protocol.Protocol_Tls{ 112 Tls: &protocol.TlsConfig{ 113 114 ServerNames: []string{n.Sni}, 115 InsecureSkipVerify: !n.VerifyCert, 116 Enable: true, 117 CaCert: nil, 118 }, 119 }, 120 } 121 } 122 123 switch n.HeaderType { 124 case "none": 125 default: 126 return nil, fmt.Errorf("vmess type is not supported: %v", n.Type) 127 } 128 129 var netProtocol *protocol.Protocol 130 switch n.Net { 131 case "ws": 132 netProtocol = &protocol.Protocol{ 133 Protocol: &protocol.Protocol_Websocket{ 134 Websocket: &protocol.Websocket{ 135 Host: n.Host, 136 Path: n.Path, 137 }, 138 }, 139 } 140 case "tcp": 141 netProtocol = &protocol.Protocol{Protocol: &protocol.Protocol_None{None: &protocol.None{}}} 142 default: 143 return nil, fmt.Errorf("vmess net is not supported: %v", n.Net) 144 } 145 146 return &point.Point{ 147 Name: "[vmess]" + n.Ps, 148 Origin: point.Origin_remote, 149 Protocols: []*protocol.Protocol{ 150 { 151 Protocol: simple, 152 }, 153 tlsProtocol, 154 netProtocol, 155 { 156 Protocol: &protocol.Protocol_Vmess{ 157 Vmess: &protocol.Vmess{ 158 Uuid: n.Uuid, 159 AlterId: fmt.Sprint(n.AlterId), 160 Security: n.Security, 161 }, 162 }, 163 }, 164 }, 165 }, nil 166 }) 167 }