github.com/sagernet/sing-box@v1.9.0-rc.20/transport/sip003/v2ray.go (about) 1 package sip003 2 3 import ( 4 "context" 5 "net" 6 "strconv" 7 8 "github.com/sagernet/sing-box/adapter" 9 "github.com/sagernet/sing-box/common/tls" 10 C "github.com/sagernet/sing-box/constant" 11 "github.com/sagernet/sing-box/option" 12 "github.com/sagernet/sing-box/transport/v2ray" 13 "github.com/sagernet/sing-vmess" 14 E "github.com/sagernet/sing/common/exceptions" 15 M "github.com/sagernet/sing/common/metadata" 16 N "github.com/sagernet/sing/common/network" 17 ) 18 19 func init() { 20 RegisterPlugin("v2ray-plugin", newV2RayPlugin) 21 } 22 23 func newV2RayPlugin(ctx context.Context, pluginOpts Args, router adapter.Router, dialer N.Dialer, serverAddr M.Socksaddr) (Plugin, error) { 24 var tlsOptions option.OutboundTLSOptions 25 if _, loaded := pluginOpts.Get("tls"); loaded { 26 tlsOptions.Enabled = true 27 } 28 if certPath, certLoaded := pluginOpts.Get("cert"); certLoaded { 29 tlsOptions.CertificatePath = certPath 30 } 31 if certRaw, certLoaded := pluginOpts.Get("certRaw"); certLoaded { 32 certHead := "-----BEGIN CERTIFICATE-----" 33 certTail := "-----END CERTIFICATE-----" 34 fixedCert := certHead + "\n" + certRaw + "\n" + certTail 35 tlsOptions.Certificate = []string{fixedCert} 36 } 37 38 mode := "websocket" 39 if modeOpt, loaded := pluginOpts.Get("mode"); loaded { 40 mode = modeOpt 41 } 42 43 host := "cloudfront.com" 44 path := "/" 45 46 if hostOpt, loaded := pluginOpts.Get("host"); loaded { 47 host = hostOpt 48 tlsOptions.ServerName = hostOpt 49 } 50 if pathOpt, loaded := pluginOpts.Get("path"); loaded { 51 path = pathOpt 52 } 53 54 var tlsClient tls.Config 55 var err error 56 if tlsOptions.Enabled { 57 tlsClient, err = tls.NewClient(ctx, serverAddr.AddrString(), tlsOptions) 58 if err != nil { 59 return nil, err 60 } 61 } 62 63 var mux int 64 var transportOptions option.V2RayTransportOptions 65 switch mode { 66 case "websocket": 67 transportOptions = option.V2RayTransportOptions{ 68 Type: C.V2RayTransportTypeWebsocket, 69 WebsocketOptions: option.V2RayWebsocketOptions{ 70 Headers: map[string]option.Listable[string]{ 71 "Host": []string{host}, 72 }, 73 Path: path, 74 }, 75 } 76 if muxOpt, loaded := pluginOpts.Get("mux"); loaded { 77 muxVal, err := strconv.Atoi(muxOpt) 78 if err != nil { 79 return nil, E.Cause(err, "parse mux value") 80 } 81 mux = muxVal 82 } else { 83 mux = 1 84 } 85 case "quic": 86 transportOptions = option.V2RayTransportOptions{ 87 Type: C.V2RayTransportTypeQUIC, 88 } 89 default: 90 return nil, E.New("v2ray-plugin: unknown mode: " + mode) 91 } 92 93 transport, err := v2ray.NewClientTransport(context.Background(), dialer, serverAddr, transportOptions, tlsClient) 94 if err != nil { 95 return nil, err 96 } 97 98 if mux > 0 { 99 return &v2rayMuxWrapper{transport}, nil 100 } 101 102 return transport, nil 103 } 104 105 var _ Plugin = (*v2rayMuxWrapper)(nil) 106 107 type v2rayMuxWrapper struct { 108 adapter.V2RayClientTransport 109 } 110 111 func (w *v2rayMuxWrapper) DialContext(ctx context.Context) (net.Conn, error) { 112 conn, err := w.V2RayClientTransport.DialContext(ctx) 113 if err != nil { 114 return nil, err 115 } 116 return vmess.NewMuxConnWrapper(conn, vmess.MuxDestination), nil 117 }