mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
fix: support ss uri speed tests with ipv6 endpoints
This commit is contained in:
@@ -243,10 +243,10 @@ func buildOutboundSS(node string) (map[string]interface{}, error) {
|
||||
method = parts[0]
|
||||
password = parts[1]
|
||||
}
|
||||
hostPort := strings.Split(hostPart, ":")
|
||||
if len(hostPort) == 2 {
|
||||
host = hostPort[0]
|
||||
port, _ = strconv.Atoi(hostPort[1])
|
||||
parsedHost, parsedPort, splitErr := splitHostPortLenient(hostPart)
|
||||
if splitErr == nil {
|
||||
host = parsedHost
|
||||
port = parsedPort
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ func proxyConfigToMapping(src string) (map[string]any, error) {
|
||||
if strings.HasPrefix(l, "socks5://") {
|
||||
return parseStandardProxy(src, "socks5")
|
||||
}
|
||||
if strings.HasPrefix(l, "ss://") {
|
||||
return parseSSURIToMapping(src)
|
||||
}
|
||||
|
||||
if strings.Contains(l, "://") && !strings.Contains(l, "type:") {
|
||||
return nil, fmt.Errorf("URI 格式暂不支持: %s", l[:min(30, len(l))])
|
||||
@@ -60,6 +63,26 @@ func parseStandardProxy(src string, proxyType string) (map[string]any, error) {
|
||||
return mapping, nil
|
||||
}
|
||||
|
||||
func parseSSURIToMapping(src string) (map[string]any, error) {
|
||||
outbound, err := buildOutboundSS(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settings, ok := outbound["settings"].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("ss 节点缺少 settings")
|
||||
}
|
||||
mapping := map[string]any{
|
||||
"name": "speedtest-proxy",
|
||||
"type": "ss",
|
||||
"server": settings["address"],
|
||||
"port": settings["port"],
|
||||
"cipher": settings["method"],
|
||||
"password": settings["password"],
|
||||
}
|
||||
return mapping, nil
|
||||
}
|
||||
|
||||
func parseClashYAMLToMapping(src string) (map[string]any, error) {
|
||||
var payload interface{}
|
||||
if err := yaml.Unmarshal([]byte(src), &payload); err != nil {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -80,6 +81,44 @@ func TestProxyConfigToMappingClashYAML(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyConfigToMappingSSURI(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
userinfo := base64.RawURLEncoding.EncodeToString([]byte("aes-128-gcm:secret"))
|
||||
mapping, err := proxyConfigToMapping("ss://" + userinfo + "@ptxlv6-1.hxx.top:43001#node")
|
||||
if err != nil {
|
||||
t.Fatalf("proxyConfigToMapping returned error: %v", err)
|
||||
}
|
||||
if got := mapping["type"]; got != "ss" {
|
||||
t.Fatalf("type = %v, want ss", got)
|
||||
}
|
||||
if got := mapping["server"]; got != "ptxlv6-1.hxx.top" {
|
||||
t.Fatalf("server = %v, want ptxlv6-1.hxx.top", got)
|
||||
}
|
||||
if got := mapping["port"]; got != 43001 {
|
||||
t.Fatalf("port = %v, want 43001", got)
|
||||
}
|
||||
if got := mapping["cipher"]; got != "aes-128-gcm" {
|
||||
t.Fatalf("cipher = %v, want aes-128-gcm", got)
|
||||
}
|
||||
if got := mapping["password"]; got != "secret" {
|
||||
t.Fatalf("password = %v, want secret", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyEndpointSSURIIPv6(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
raw := base64.RawURLEncoding.EncodeToString([]byte("aes-128-gcm:secret@[2001:db8::1]:43001"))
|
||||
endpoint, err := proxyEndpoint("ss://" + raw)
|
||||
if err != nil {
|
||||
t.Fatalf("proxyEndpoint returned error: %v", err)
|
||||
}
|
||||
if endpoint != "[2001:db8::1]:43001" {
|
||||
t.Fatalf("endpoint = %q, want [2001:db8::1]:43001", endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyConfigToMappingUnsupportedURI(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -46,10 +47,31 @@ func proxyEndpoint(src string) (string, error) {
|
||||
if at := strings.LastIndex(rest, "@"); at >= 0 {
|
||||
hostport := strings.SplitN(rest[at+1:], "?", 2)[0]
|
||||
hostport = strings.SplitN(hostport, "#", 2)[0]
|
||||
return hostport, nil
|
||||
host, port, err := splitHostPortLenient(hostport)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return net.JoinHostPort(host, strconv.Itoa(port)), nil
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(l, "ss://") {
|
||||
outbound, err := buildOutboundSS(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
settings, ok := outbound["settings"].(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("ss 节点缺少 settings")
|
||||
}
|
||||
server := getMapString(settings, "address")
|
||||
port := getMapInt(settings, "port")
|
||||
if server == "" || port == 0 {
|
||||
return "", fmt.Errorf("ss 节点信息不完整")
|
||||
}
|
||||
return net.JoinHostPort(server, strconv.Itoa(port)), nil
|
||||
}
|
||||
|
||||
var payload interface{}
|
||||
if err := yaml.Unmarshal([]byte(src), &payload); err == nil {
|
||||
node := pickClashNode(payload)
|
||||
@@ -65,6 +87,31 @@ func proxyEndpoint(src string) (string, error) {
|
||||
return "", fmt.Errorf("无法解析代理地址")
|
||||
}
|
||||
|
||||
func splitHostPortLenient(hostport string) (string, int, error) {
|
||||
hostport = strings.TrimSpace(hostport)
|
||||
if hostport == "" {
|
||||
return "", 0, fmt.Errorf("缺少代理地址")
|
||||
}
|
||||
if host, portText, err := net.SplitHostPort(hostport); err == nil {
|
||||
port, convErr := strconv.Atoi(portText)
|
||||
if convErr != nil || port <= 0 || port > 65535 {
|
||||
return "", 0, fmt.Errorf("代理端口无效: %s", portText)
|
||||
}
|
||||
return strings.Trim(host, "[]"), port, nil
|
||||
}
|
||||
idx := strings.LastIndex(hostport, ":")
|
||||
if idx <= 0 || idx == len(hostport)-1 {
|
||||
return "", 0, fmt.Errorf("无法解析代理地址: %s", hostport)
|
||||
}
|
||||
host := strings.Trim(strings.TrimSpace(hostport[:idx]), "[]")
|
||||
portText := strings.TrimSpace(hostport[idx+1:])
|
||||
port, err := strconv.Atoi(portText)
|
||||
if host == "" || err != nil || port <= 0 || port > 65535 {
|
||||
return "", 0, fmt.Errorf("无法解析代理地址: %s", hostport)
|
||||
}
|
||||
return host, port, nil
|
||||
}
|
||||
|
||||
func toStringMap(input interface{}) map[string]interface{} {
|
||||
switch v := input.(type) {
|
||||
case map[string]interface{}:
|
||||
|
||||
Reference in New Issue
Block a user