mirror of
https://github.com/nitezs/sub2sing-box.git
synced 2024-12-23 22:14:41 -05:00
✨ 兼容shadowsocks的plugin (#8)
This commit is contained in:
parent
9e50b30af6
commit
7792c99f19
@ -2,6 +2,7 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sub2sing-box/constant"
|
"sub2sing-box/constant"
|
||||||
"sub2sing-box/model"
|
"sub2sing-box/model"
|
||||||
@ -9,90 +10,78 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
||||||
if !strings.HasPrefix(proxy, constant.ShadowsocksPrefix) {
|
link, err := url.Parse(proxy)
|
||||||
|
if err != nil {
|
||||||
|
return model.Outbound{}, &ParseError{
|
||||||
|
Type: ErrInvalidStruct,
|
||||||
|
Message: "url parse error",
|
||||||
|
Raw: proxy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server := link.Hostname()
|
||||||
|
if server == "" {
|
||||||
|
return model.Outbound{}, &ParseError{
|
||||||
|
Type: ErrInvalidStruct,
|
||||||
|
Message: "missing server host",
|
||||||
|
Raw: proxy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if link.Scheme+"://" != constant.ShadowsocksPrefix {
|
||||||
return model.Outbound{}, &ParseError{Type: ErrInvalidPrefix, Raw: proxy}
|
return model.Outbound{}, &ParseError{Type: ErrInvalidPrefix, Raw: proxy}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy = strings.TrimPrefix(proxy, constant.ShadowsocksPrefix)
|
port, err := strconv.Atoi(link.Port())
|
||||||
urlParts := strings.SplitN(proxy, "@", 2)
|
|
||||||
if len(urlParts) != 2 {
|
|
||||||
return model.Outbound{}, &ParseError{
|
|
||||||
Type: ErrInvalidStruct,
|
|
||||||
Message: "missing character '@' in url",
|
|
||||||
Raw: proxy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(urlParts[0], ":") {
|
|
||||||
decoded, err := util.DecodeBase64(urlParts[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return model.Outbound{}, &ParseError{
|
return model.Outbound{}, &ParseError{
|
||||||
Type: ErrInvalidStruct,
|
Type: ErrInvalidStruct,
|
||||||
Message: "invalid base64 encoded",
|
Message: "missing server port",
|
||||||
Raw: proxy,
|
Raw: proxy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
urlParts[0] = decoded
|
|
||||||
}
|
user, err := util.DecodeBase64(link.User.Username())
|
||||||
credentials := strings.SplitN(urlParts[0], ":", 2)
|
if user == "" {
|
||||||
if len(credentials) != 2 {
|
|
||||||
return model.Outbound{}, &ParseError{
|
return model.Outbound{}, &ParseError{
|
||||||
Type: ErrInvalidStruct,
|
Type: ErrInvalidStruct,
|
||||||
Message: "missing server host or port",
|
Message: "missing method and password",
|
||||||
Raw: proxy,
|
Raw: proxy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
method, password := credentials[0], credentials[1]
|
methodAndPass := strings.SplitN(user, ":", 2)
|
||||||
|
if len(methodAndPass) != 2 {
|
||||||
serverInfoAndTag := strings.SplitN(urlParts[1], "#", 2)
|
|
||||||
serverAndPort := serverInfoAndTag[0]
|
|
||||||
|
|
||||||
lastColonIndex := strings.LastIndex(serverAndPort, ":")
|
|
||||||
if lastColonIndex == -1 {
|
|
||||||
return model.Outbound{}, &ParseError{
|
return model.Outbound{}, &ParseError{
|
||||||
Type: ErrInvalidStruct,
|
Type: ErrInvalidStruct,
|
||||||
Message: "missing port in address",
|
Message: "missing method and password",
|
||||||
Raw: proxy,
|
Raw: proxy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server := serverAndPort[:lastColonIndex]
|
query := link.Query()
|
||||||
portStr := serverAndPort[lastColonIndex+1:]
|
pluginStr := query.Get("plugin")
|
||||||
|
plugin := ""
|
||||||
port, err := ParsePort(portStr)
|
options := ""
|
||||||
if err != nil {
|
if pluginStr != "" {
|
||||||
return model.Outbound{}, &ParseError{
|
arr := strings.SplitN(pluginStr, ";", 2)
|
||||||
Type: ErrInvalidPort,
|
if len(arr) == 2 {
|
||||||
Message: err.Error(),
|
plugin = arr[0]
|
||||||
Raw: proxy,
|
options = arr[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var remarks string
|
|
||||||
if len(serverInfoAndTag) == 2 {
|
|
||||||
unescape, err := url.QueryUnescape(serverInfoAndTag[1])
|
|
||||||
if err != nil {
|
|
||||||
return model.Outbound{}, &ParseError{
|
|
||||||
Type: ErrInvalidStruct,
|
|
||||||
Message: "cannot unescape remarks",
|
|
||||||
Raw: proxy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
remarks = strings.TrimSpace(unescape)
|
|
||||||
} else {
|
|
||||||
remarks = strings.TrimSpace(server + ":" + portStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{
|
||||||
Type: "shadowsocks",
|
Type: "shadowsocks",
|
||||||
Tag: remarks,
|
Tag: link.Fragment,
|
||||||
ShadowsocksOptions: model.ShadowsocksOutboundOptions{
|
ShadowsocksOptions: model.ShadowsocksOutboundOptions{
|
||||||
ServerOptions: model.ServerOptions{
|
ServerOptions: model.ServerOptions{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPort: port,
|
ServerPort: uint16(port),
|
||||||
},
|
},
|
||||||
Method: method,
|
Method: methodAndPass[0],
|
||||||
Password: password,
|
Password: methodAndPass[1],
|
||||||
|
Plugin: plugin,
|
||||||
|
PluginOptions: options,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user