mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-20 08:47:16 +08:00
fix(link): strip query and trailing slash when parsing ss:// port (#5895)
* fix(link): strip query and trailing slash when parsing ss:// port Subscription-provided Shadowsocks links use the SIP002 form ss://userinfo@host:port[/][?plugin=...]#tag. parseShadowsocks only stripped the #fragment, so a "?plugin=" / "?type=" query and the optional trailing slash leaked into the host:port split, strconv.Atoi failed, and the port was silently set to 0 (the error was discarded). Direct link import was unaffected because it runs through the frontend parser, which already handles this. Strip the query and the trailing slash before splitting host:port, mirroring the frontend outbound-link-parser and the SIP002 grammar. This complements #5432, which fixed the SS2022 generation side. Add table-driven parseShadowsocks tests covering modern, legacy, base64url userinfo, the SIP002 slash+plugin form, and SIP022 percent-encoded userinfo with a dual-key password. * fix(link): surface ss:// port parse errors instead of defaulting to 0 The modern and legacy Shadowsocks branches discarded the strconv.Atoi error when reading the port, silently yielding port 0 for any malformed host:port. Return a parse error instead, matching defaultPort's existing pattern in this file, so a bad link is skipped by ParseSubscriptionBody rather than injected as an unusable port-0 outbound.
This commit is contained in:
@@ -338,12 +338,15 @@ func parseShadowsocks(link string) (*ParseResult, error) {
|
||||
remark, _ = url.QueryUnescape(link[i+1:])
|
||||
link = link[:i]
|
||||
}
|
||||
if i := strings.Index(link, "?"); i >= 0 {
|
||||
link = link[:i]
|
||||
}
|
||||
core := strings.TrimPrefix(link, "ss://")
|
||||
at := strings.Index(core, "@")
|
||||
if at >= 0 {
|
||||
// modern
|
||||
userB64 := core[:at]
|
||||
hp := core[at+1:]
|
||||
hp := strings.TrimRight(core[at+1:], "/")
|
||||
userInfo, err := base64DecodeFlexible(userB64)
|
||||
if err != nil {
|
||||
// SIP022 (2022-blake3-*) userinfo is percent-encoded, not base64.
|
||||
@@ -358,7 +361,10 @@ func parseShadowsocks(link string) (*ParseResult, error) {
|
||||
return nil, fmt.Errorf("bad ss host:port")
|
||||
}
|
||||
host := hp[:colon]
|
||||
port, _ := strconv.Atoi(hp[colon+1:])
|
||||
port, err := strconv.Atoi(hp[colon+1:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad ss port %q: %w", hp[colon+1:], err)
|
||||
}
|
||||
method, pass := splitMethodPass(userInfo)
|
||||
identity := "ss:" + method + ":" + pass + "@" + host + ":" + strconv.Itoa(port)
|
||||
ob := Outbound{
|
||||
@@ -388,7 +394,10 @@ func parseShadowsocks(link string) (*ParseResult, error) {
|
||||
return nil, fmt.Errorf("bad legacy ss hp")
|
||||
}
|
||||
host := hp[:colon]
|
||||
port, _ := strconv.Atoi(hp[colon+1:])
|
||||
port, err := strconv.Atoi(hp[colon+1:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad legacy ss port %q: %w", hp[colon+1:], err)
|
||||
}
|
||||
method, pass := splitMethodPass(userInfo)
|
||||
identity := "ss:" + method + ":" + pass + "@" + host + ":" + strconv.Itoa(port)
|
||||
ob := Outbound{
|
||||
|
||||
Reference in New Issue
Block a user