github.com/xxf098/lite-proxy@v0.15.1-0.20230422081941-12c69f323218/config/shadowsocksr.go (about)

     1  package config
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"net/url"
     7  	"regexp"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/xxf098/lite-proxy/outbound"
    12  	"github.com/xxf098/lite-proxy/utils"
    13  )
    14  
    15  var (
    16  	NotSSRLink error = errors.New("not a shadowsocksR link")
    17  )
    18  
    19  func SSRLinkToSSROption(link string) (*outbound.ShadowSocksROption, error) {
    20  	regex := regexp.MustCompile(`^ssr://([A-Za-z0-9+-=/_]+)`)
    21  	res := regex.FindAllStringSubmatch(link, 1)
    22  	b64 := ""
    23  	if len(res) > 0 && len(res[0]) > 1 {
    24  		b64 = res[0][1]
    25  	}
    26  	uri, err := utils.DecodeB64(b64)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  	parts := strings.SplitN(uri, "/?", 2)
    31  	links := strings.Split(parts[0], ":")
    32  	if len(links) != 6 || len(parts) != 2 {
    33  		return nil, NotSSRLink
    34  	}
    35  	port, err := strconv.Atoi(links[1])
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	pass, err := utils.DecodeB64(links[5])
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	cipher := links[3]
    44  	if cipher == "none" {
    45  		cipher = "dummy"
    46  	}
    47  	ssrOption := &outbound.ShadowSocksROption{
    48  		Name:     "ssr",
    49  		Server:   links[0],
    50  		Port:     port,
    51  		Protocol: links[2],
    52  		Cipher:   cipher,
    53  		Obfs:     links[4],
    54  		Password: pass,
    55  		UDP:      false,
    56  		Remarks:  "",
    57  	}
    58  	query := strings.ReplaceAll(parts[1], "+", "%2B")
    59  	if rawQuery, err := url.ParseQuery(query); err == nil {
    60  		obfsparam, err := utils.DecodeB64(rawQuery.Get("obfsparam"))
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		ssrOption.ObfsParam = obfsparam
    65  		if obfsparam == "" {
    66  			obfsparam, err := utils.DecodeB64(rawQuery.Get("obfs-param"))
    67  			if err != nil {
    68  				return nil, err
    69  			}
    70  			ssrOption.ObfsParam = obfsparam
    71  		}
    72  		protoparam, err := utils.DecodeB64(rawQuery.Get("protoparam"))
    73  		if err != nil {
    74  			return nil, err
    75  		}
    76  		ssrOption.ProtocolParam = protoparam
    77  		remarks, err := utils.DecodeB64(rawQuery.Get("remarks"))
    78  		if err == nil {
    79  			if remarks == "" {
    80  				remarks = net.JoinHostPort(ssrOption.Server, strconv.Itoa(ssrOption.Port))
    81  			}
    82  			ssrOption.Remarks = remarks
    83  			ssrOption.Name = remarks
    84  		}
    85  	}
    86  	return ssrOption, nil
    87  }
    88  
    89  func init() {
    90  	outbound.RegisterDialerCreator("ssr", func(link string) (outbound.Dialer, error) {
    91  		ssOption, err := SSRLinkToSSROption(link)
    92  		if err != nil {
    93  			return nil, err
    94  		}
    95  		return outbound.NewShadowSocksR(ssOption)
    96  	})
    97  }