Files
Zakk 0de4b2c4a4 fix: refuse Shadowsocks links whose cipher the core does not accept
A Shadowsocks link with a stream cipher (rc4-md5, aes-128-cfb, aes-256-cfb,
chacha20-ietf) or with none/plain imported without complaint and failed at
core start with "unknown cipher method", so the user saw a broken core rather
than a refused node. xray-core dropped the stream ciphers in 2021 and never
took none or plain in the shadowsocks outbound; these are also the ciphers
ShadowsocksR providers hand out.

ParseSSURL now refuses them with LINK_UNSUPPORTED_CIPHER, which NewFromLink
passes through instead of calling the link malformed; subscriptions skip such
nodes with a warning as they skip other unparseable ones, and the Clash
importer goes through the same parser. The node form drops none and plain and
offers xchacha20-ietf-poly1305, which the core does accept. The six locales
carry the message, and the quick-start pages say which ciphers work.
2026-09-23 21:01:56 +10:00

119 lines
3.6 KiB
Go

package serverObj
import (
"errors"
"fmt"
"net/url"
"strings"
"github.com/v2rayA/v2rayA/common"
"github.com/v2rayA/v2rayA/conf"
"github.com/v2rayA/v2rayA/kernel/coreObj"
"github.com/v2rayA/v2rayA/kernel/v2ray/where"
)
var ErrInvalidParameter = fmt.Errorf("malformed server link")
type ServerObj interface {
Configuration(info PriorInfo) (c Configuration, err error)
ExportToURL() string
NeedPluginPort() bool
ProtoToShow() string
GetProtocol() string
GetHostname() string
GetPort() int
GetName() string
SetName(name string)
}
type Configuration struct {
CoreOutbound coreObj.OutboundObject
ExtraOutbounds []coreObj.OutboundObject
PluginChain string // The first is a server plugin, and the others are client plugins. Split by ",".
UDPSupport bool
PluginManagerServerLink string
}
type PriorInfo struct {
Variant where.Variant
CoreVersion string
Tag string
PluginPort int
Backend string // effective backend: "v2ray" or "" (daeuniverse/system default)
}
// BackendGetter is implemented by server types that support backend selection.
type BackendGetter interface {
GetBackend() string
}
func (info *PriorInfo) PluginObj() coreObj.OutboundObject {
return coreObj.OutboundObject{
Tag: info.Tag,
Protocol: "socks",
Settings: coreObj.Settings{
Servers: []coreObj.Server{
{
Address: "127.0.0.1",
Port: info.PluginPort,
},
}},
}
}
type FromLinkCreator func(link string) (ServerObj, error)
type EmptyCreator func() (ServerObj, error)
var fromLinkCreators = make(map[string]FromLinkCreator)
var emptyCreators = make(map[string]EmptyCreator)
func FromLinkRegister(name string, creator FromLinkCreator) {
fromLinkCreators[name] = creator
}
func EmptyRegister(name string, creator EmptyCreator) {
emptyCreators[name] = creator
}
func New(name string) (ServerObj, error) {
if creator, ok := emptyCreators[name]; ok {
return creator()
} else if pm := conf.GetEnvironmentConfig().PluginManager; pm != "" {
// we do not support to override build-in protocols
creator := emptyCreators[PluginManagerScheme]
return creator()
} else {
return nil, fmt.Errorf("%q links are not supported; supported schemes: vmess, vless, ss, trojan, trojan-go, socks5, http, https, http-proxy, https-proxy, hysteria2, hy2, tuic, juicity, anytls, wireguard", name)
}
}
func NewFromLink(name string, link string) (ServerObj, error) {
if name == "ssr" || name == "shadowsocksr" {
return nil, common.Coded("LINK_UNSUPPORTED_SCHEME", fmt.Errorf("%s", ssrUnsupported), map[string]interface{}{"scheme": name})
}
if creator, ok := fromLinkCreators[name]; ok {
obj, err := creator(link)
var coded *common.CodedError
if errors.As(err, &coded) {
return nil, err
}
if err != nil {
return nil, common.Coded("LINK_MALFORMED", err, map[string]interface{}{
"protocol": name,
"detail": strings.TrimPrefix(err.Error(), ErrInvalidParameter.Error()+": "),
})
}
return obj, nil
} else if pm := conf.GetEnvironmentConfig().PluginManager; pm != "" {
// we do not support to override build-in protocols
creator := fromLinkCreators[PluginManagerScheme]
return creator(link)
} else {
return nil, common.Coded("LINK_UNSUPPORTED_SCHEME", fmt.Errorf("%q links are not supported; supported schemes: vmess, vless, ss, trojan, trojan-go, socks5, http, https, http-proxy, https-proxy, hysteria2, hy2, tuic, juicity, anytls, wireguard", name), map[string]interface{}{"scheme": name})
}
}
func setValue(values *url.Values, key string, value string) {
if value == "" {
return
}
values.Set(key, value)
}