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  }