Spaces:
Sleeping
Sleeping
File size: 2,927 Bytes
bb9df9e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | package node
import (
"fmt"
"log"
"net/url"
"strconv"
"strings"
)
// ss匹配规则
type Ss struct {
Param Param
Server string
Port int
Name string
Type string
}
type Param struct {
Cipher string
Password string
}
func parsingSS(s string) (string, string, string) {
/* ss url编码分为三部分:加密方式、服务器地址和端口、备注
://和@之前为第一部分 @到#之间为第二部分 #之后为第三部分
第一部分 为加密方式和密码,格式为:加密方式:密码 示例:aes-128-gcm:123456
第二部分 为服务器地址和端口,格式为:服务器地址:端口 示例:xxx.xxx:12345
第三部分 为备注,格式为:#备注 示例:#备注
*/
u, err := url.Parse(s)
if err != nil {
log.Println("ss url parse fail.", err)
return "", "", ""
}
if u.Scheme != "ss" {
log.Println("ss url parse fail, not ss url.")
return "", "", ""
}
// 处理url全编码的情况
if u.User == nil {
// 截取ss://后的字符串
raw := s[5:]
s = "ss://" + Base64Decode(raw)
u, err = url.Parse(s)
}
var auth, addr, name string
auth = u.User.String()
if u.Host != "" {
addr = u.Host
}
if u.Fragment != "" {
name = u.Fragment
}
return auth, addr, name
}
// 开发者测试
func CallSSURL() {
ss := Ss{}
// ss.Name = "测试"
ss.Server = "baidu.com"
ss.Port = 443
ss.Param.Cipher = "2022-blake3-aes-256-gcm"
ss.Param.Password = "asdasd"
fmt.Println(EncodeSSURL(ss))
}
// ss 编码输出
func EncodeSSURL(s Ss) string {
//编码格式 ss://base64(base64(method:password)@hostname:port)
p := Base64Encode(s.Param.Cipher + ":" + s.Param.Password)
// 假设备注没有使用服务器加端口命名
if s.Name == "" {
s.Name = s.Server + ":" + strconv.Itoa(s.Port)
}
param := fmt.Sprintf("%s@%s:%s#%s",
p,
s.Server,
strconv.Itoa(s.Port),
s.Name,
)
return "ss://" + param
}
func DecodeSSURL(s string) (Ss, error) {
// 解析ss链接
param, addr, name := parsingSS(s)
// base64解码
param = Base64Decode(param)
// 判断是否为空
if param == "" || addr == "" {
return Ss{}, fmt.Errorf("invalid SS URL")
}
// 解析参数
parts := strings.Split(addr, ":")
port, _ := strconv.Atoi(parts[len(parts)-1])
server := strings.Replace(ValRetIPv6Addr(addr), ":"+parts[len(parts)-1], "", -1)
cipher := strings.Split(param, ":")[0]
password := strings.Replace(param, cipher+":", "", 1)
// 如果没有备注则使用服务器加端口命名
if name == "" {
name = addr
}
// 开发环境输出结果
if CheckEnvironment() {
fmt.Println("Param:", Base64Decode(param))
fmt.Println("Server", server)
fmt.Println("Port", port)
fmt.Println("Name:", name)
fmt.Println("Cipher:", cipher)
fmt.Println("Password:", password)
}
// 返回结果
return Ss{
Param: Param{
Cipher: cipher,
Password: password,
},
Server: server,
Port: port,
Name: name,
Type: "ss",
}, nil
}
|