mirror of
https://github.com/v2rayA/v2rayA.git
synced 2024-11-25 16:34:19 +08:00
Provide a new implement way of shadowsocks plugin. (#604)
This commit is contained in:
parent
d35f5d99e0
commit
e1a5f8cfe3
3
.gitignore
vendored
3
.gitignore
vendored
@ -33,3 +33,6 @@ node_modules
|
|||||||
/PKGBUILD
|
/PKGBUILD
|
||||||
/go.mod
|
/go.mod
|
||||||
/go.sum
|
/go.sum
|
||||||
|
|
||||||
|
# Virtualenv
|
||||||
|
.env
|
||||||
|
@ -289,6 +289,32 @@
|
|||||||
<option value="v2ray-plugin">v2ray-plugin</option>
|
<option value="v2ray-plugin">v2ray-plugin</option>
|
||||||
</b-select>
|
</b-select>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
<b-field
|
||||||
|
v-if="ss.plugin === 'simple-obfs' || ss.plugin === 'v2ray-plugin'"
|
||||||
|
label-position="on-border"
|
||||||
|
class="with-icon-alert"
|
||||||
|
>
|
||||||
|
<template slot="label">
|
||||||
|
Impl
|
||||||
|
<b-tooltip
|
||||||
|
type="is-dark"
|
||||||
|
:label="$t('setting.messages.ssPluginImpl')"
|
||||||
|
multilined
|
||||||
|
position="is-right"
|
||||||
|
>
|
||||||
|
<b-icon
|
||||||
|
size="is-samll"
|
||||||
|
icon=" iconfont icon-help-circle-outline"
|
||||||
|
style="position:relative;top:2px;right:3px;font-weight:normal"
|
||||||
|
/>
|
||||||
|
</b-tooltip>
|
||||||
|
</template>
|
||||||
|
<b-select ref="ss_plugin_impl" v-model="ss.impl" expanded>
|
||||||
|
<option value="">{{ $t("setting.options.default") }}</option>
|
||||||
|
<option value="chained">chained</option>
|
||||||
|
<option value="transport">transport</option>
|
||||||
|
</b-select>
|
||||||
|
</b-field>
|
||||||
<b-field
|
<b-field
|
||||||
v-show="ss.plugin === 'simple-obfs'"
|
v-show="ss.plugin === 'simple-obfs'"
|
||||||
label="Obfs"
|
label="Obfs"
|
||||||
@ -753,7 +779,8 @@ export default {
|
|||||||
server: "",
|
server: "",
|
||||||
port: "",
|
port: "",
|
||||||
name: "",
|
name: "",
|
||||||
protocol: "ss"
|
protocol: "ss",
|
||||||
|
impl: ""
|
||||||
},
|
},
|
||||||
ssr: {
|
ssr: {
|
||||||
method: "aes-128-cfb",
|
method: "aes-128-cfb",
|
||||||
@ -936,7 +963,8 @@ export default {
|
|||||||
name: u.hash,
|
name: u.hash,
|
||||||
obfs: "http",
|
obfs: "http",
|
||||||
plugin: "",
|
plugin: "",
|
||||||
protocol: "ss"
|
protocol: "ss",
|
||||||
|
impl: ""
|
||||||
};
|
};
|
||||||
if (u.params.plugin) {
|
if (u.params.plugin) {
|
||||||
u.params.plugin = decodeURIComponent(u.params.plugin);
|
u.params.plugin = decodeURIComponent(u.params.plugin);
|
||||||
@ -972,6 +1000,8 @@ export default {
|
|||||||
break;
|
break;
|
||||||
case "tls":
|
case "tls":
|
||||||
obj.tls = "tls";
|
obj.tls = "tls";
|
||||||
|
case "impl":
|
||||||
|
obj.impl = a[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1159,12 +1189,18 @@ export default {
|
|||||||
}
|
}
|
||||||
plugin.push("path=" + srcObj.path);
|
plugin.push("path=" + srcObj.path);
|
||||||
}
|
}
|
||||||
|
if (srcObj.impl) {
|
||||||
|
plugin.push("impl=" + srcObj.impl);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
plugin.push("obfs=" + srcObj.obfs);
|
plugin.push("obfs=" + srcObj.obfs);
|
||||||
plugin.push("obfs-host=" + srcObj.host);
|
plugin.push("obfs-host=" + srcObj.host);
|
||||||
if (srcObj.obfs === "http") {
|
if (srcObj.obfs === "http") {
|
||||||
plugin.push("obfs-path=" + srcObj.path);
|
plugin.push("obfs-path=" + srcObj.path);
|
||||||
}
|
}
|
||||||
|
if (srcObj.impl) {
|
||||||
|
plugin.push("impl=" + srcObj.impl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tmp += `?plugin=${encodeURIComponent(plugin.join(";"))}`;
|
tmp += `?plugin=${encodeURIComponent(plugin.join(";"))}`;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,10 @@ export default {
|
|||||||
<p>TCP: {tcpPorts}</p>
|
<p>TCP: {tcpPorts}</p>
|
||||||
<p>UDP: {udpPorts}</p>`,
|
<p>UDP: {udpPorts}</p>`,
|
||||||
grpcShouldWithTls: `gRPC must be with TLS`
|
grpcShouldWithTls: `gRPC must be with TLS`
|
||||||
|
ssPluginImpl:
|
||||||
|
"★default: 'transport' for simple-obfs, 'chained' for v2ray-plugin." +
|
||||||
|
"★chained: shadowsocks traffic will be redirect to standalone plugin." +
|
||||||
|
"★transport: processed by the transport layer of v2ray/xray core directly."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
customAddressPort: {
|
customAddressPort: {
|
||||||
|
@ -159,6 +159,10 @@ export default {
|
|||||||
<p>TCP: {tcpPorts}</p>
|
<p>TCP: {tcpPorts}</p>
|
||||||
<p>UDP: {udpPorts}</p>`,
|
<p>UDP: {udpPorts}</p>`,
|
||||||
grpcShouldWithTls: `gRPC必须启用TLS`
|
grpcShouldWithTls: `gRPC必须启用TLS`
|
||||||
|
ssPluginImpl:
|
||||||
|
"★默认:使用 simple-obfs 时为等效传输层,v2ray-plugin 时为链式。" +
|
||||||
|
"★链式:shadowsocks 流量会被转发至独立的插件。" +
|
||||||
|
"★等效传输层:直接由 v2ray/xray 核心的传输层处理。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
customAddressPort: {
|
customAddressPort: {
|
||||||
|
@ -106,12 +106,7 @@ func ParseSSURL(u string) (data *Shadowsocks, err error) {
|
|||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shadowsocks) Configuration(info PriorInfo) (c Configuration, err error) {
|
func (s *Shadowsocks) ConfigurationMC(info PriorInfo) (c Configuration, err error) {
|
||||||
switch s.Cipher {
|
|
||||||
case "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "plain", "none":
|
|
||||||
default:
|
|
||||||
return c, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
|
||||||
}
|
|
||||||
v2rayServer := coreObj.Server{
|
v2rayServer := coreObj.Server{
|
||||||
Address: s.Server,
|
Address: s.Server,
|
||||||
Port: s.Port,
|
Port: s.Port,
|
||||||
@ -213,6 +208,148 @@ func (s *Shadowsocks) Configuration(info PriorInfo) (c Configuration, err error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shadowsocks) ConfigurationMT(info PriorInfo) (c Configuration, err error) {
|
||||||
|
v2rayServer := coreObj.Server{
|
||||||
|
Address: s.Server,
|
||||||
|
Port: s.Port,
|
||||||
|
Method: s.Cipher,
|
||||||
|
Password: s.Password,
|
||||||
|
}
|
||||||
|
udpSupport := true
|
||||||
|
var v2StreamSettings *coreObj.StreamSettings
|
||||||
|
var v2Mux *coreObj.Mux
|
||||||
|
switch s.Plugin.Name {
|
||||||
|
case "simple-obfs":
|
||||||
|
host := s.Plugin.Opts.Host
|
||||||
|
if host == "" {
|
||||||
|
host = "cloudflare.com"
|
||||||
|
}
|
||||||
|
path := s.Plugin.Opts.Path
|
||||||
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
v2StreamSettings = &coreObj.StreamSettings{}
|
||||||
|
tcpSettings := coreObj.TCPSettings{
|
||||||
|
Header: coreObj.TCPHeader{
|
||||||
|
Type: "http",
|
||||||
|
Request: coreObj.HTTPRequest{
|
||||||
|
Version: "1.1",
|
||||||
|
Method: "GET",
|
||||||
|
Path: strings.Split(path, ","),
|
||||||
|
Headers: coreObj.HTTPReqHeader{
|
||||||
|
Host: strings.Split(host, ","),
|
||||||
|
UserAgent: []string{
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/527.36 (KHTML, like Gecko) Chrome/55.2883.75 Safari/537.36",
|
||||||
|
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.46",
|
||||||
|
},
|
||||||
|
AcceptEncoding: []string{"gzip, deflate"},
|
||||||
|
Connection: []string{"keep-alive"},
|
||||||
|
Pragma: "no-cache",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Response: coreObj.HTTPResponse{
|
||||||
|
Version: "1.1",
|
||||||
|
Status: "200",
|
||||||
|
Reason: "OK",
|
||||||
|
Headers: coreObj.HTTPRespHeader {
|
||||||
|
ContentType: []string{"application/octet-stream", "video/mpeg"},
|
||||||
|
TransferEncoding: []string{"chunked"},
|
||||||
|
Connection: []string{"keep-alive"},
|
||||||
|
Pragma: "no-cache",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
switch s.Plugin.Opts.Obfs {
|
||||||
|
case "http":
|
||||||
|
v2StreamSettings.Network = "tcp"
|
||||||
|
v2StreamSettings.TCPSettings = &tcpSettings
|
||||||
|
case "tls":
|
||||||
|
v2StreamSettings.Security = "tls"
|
||||||
|
v2StreamSettings.TLSSettings = &coreObj.TLSSettings{}
|
||||||
|
// SNI
|
||||||
|
v2StreamSettings.TLSSettings.ServerName = host
|
||||||
|
default:
|
||||||
|
return c, fmt.Errorf("unsupported obfs %v of plugin %v", s.Plugin.Opts.Obfs, s.Plugin.Name)
|
||||||
|
}
|
||||||
|
case "v2ray-plugin":
|
||||||
|
v2StreamSettings = &coreObj.StreamSettings{}
|
||||||
|
host := s.Plugin.Opts.Host
|
||||||
|
if host == "" {
|
||||||
|
host = "cloudflare.com"
|
||||||
|
}
|
||||||
|
path := s.Plugin.Opts.Path
|
||||||
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
if s.Plugin.Opts.Tls == "tls" {
|
||||||
|
v2StreamSettings.Security = "tls"
|
||||||
|
v2StreamSettings.TLSSettings = &coreObj.TLSSettings{}
|
||||||
|
// SNI
|
||||||
|
v2StreamSettings.TLSSettings.ServerName = host
|
||||||
|
}
|
||||||
|
v2Mux = &coreObj.Mux{
|
||||||
|
Enabled: true,
|
||||||
|
Concurrency: 1,
|
||||||
|
}
|
||||||
|
switch s.Plugin.Opts.Obfs {
|
||||||
|
case "quic":
|
||||||
|
return c, fmt.Errorf("quic is not yet supported")
|
||||||
|
default:
|
||||||
|
// "websocket" or ""
|
||||||
|
v2StreamSettings.Network = "ws"
|
||||||
|
v2StreamSettings.WsSettings = &coreObj.WsSettings{
|
||||||
|
Path: path,
|
||||||
|
Headers: coreObj.Headers{
|
||||||
|
Host: host,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "":
|
||||||
|
// no plugin
|
||||||
|
default:
|
||||||
|
return c, fmt.Errorf("unsupported plugin %v", s.Plugin.Name)
|
||||||
|
}
|
||||||
|
return Configuration{
|
||||||
|
CoreOutbound: coreObj.OutboundObject{
|
||||||
|
Tag: info.Tag,
|
||||||
|
Protocol: "shadowsocks",
|
||||||
|
Settings: coreObj.Settings{
|
||||||
|
Servers: []coreObj.Server{v2rayServer},
|
||||||
|
},
|
||||||
|
StreamSettings: v2StreamSettings,
|
||||||
|
Mux: v2Mux,
|
||||||
|
},
|
||||||
|
UDPSupport: udpSupport,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shadowsocks) Configuration(info PriorInfo) (c Configuration, err error) {
|
||||||
|
switch s.Cipher {
|
||||||
|
case "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "plain", "none":
|
||||||
|
default:
|
||||||
|
return c, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
||||||
|
}
|
||||||
|
// check shadowsocks plugin implementation
|
||||||
|
ssPluginImpl := s.Plugin.Opts.Impl
|
||||||
|
if ssPluginImpl == "" {
|
||||||
|
switch s.Plugin.Name {
|
||||||
|
case "simple-obfs":
|
||||||
|
ssPluginImpl = "transport"
|
||||||
|
default:
|
||||||
|
ssPluginImpl = "chained"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch ssPluginImpl {
|
||||||
|
case "chained":
|
||||||
|
return s.ConfigurationMC(info)
|
||||||
|
case "transport":
|
||||||
|
return s.ConfigurationMT(info)
|
||||||
|
default:
|
||||||
|
return c, fmt.Errorf("unsupported shadowsocks plugin implementation: %v", ssPluginImpl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shadowsocks) ExportToURL() string {
|
func (s *Shadowsocks) ExportToURL() string {
|
||||||
// sip002
|
// sip002
|
||||||
u := &url.URL{
|
u := &url.URL{
|
||||||
@ -273,6 +410,7 @@ type Sip003Opts struct {
|
|||||||
Obfs string `json:"obfs"`
|
Obfs string `json:"obfs"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Path string `json:"uri"`
|
Path string `json:"uri"`
|
||||||
|
Impl string `json:"impl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSip003Opts(opts string) Sip003Opts {
|
func ParseSip003Opts(opts string) Sip003Opts {
|
||||||
@ -296,6 +434,8 @@ func ParseSip003Opts(opts string) Sip003Opts {
|
|||||||
sip003Opts.Path = a[1]
|
sip003Opts.Path = a[1]
|
||||||
case "obfs-host", "host":
|
case "obfs-host", "host":
|
||||||
sip003Opts.Host = a[1]
|
sip003Opts.Host = a[1]
|
||||||
|
case "impl":
|
||||||
|
sip003Opts.Impl = a[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sip003Opts
|
return sip003Opts
|
||||||
@ -326,6 +466,9 @@ func (s *Sip003) String() string {
|
|||||||
if s.Opts.Path != "" {
|
if s.Opts.Path != "" {
|
||||||
list = append(list, "obfs-uri="+s.Opts.Path)
|
list = append(list, "obfs-uri="+s.Opts.Path)
|
||||||
}
|
}
|
||||||
|
if s.Opts.Impl != "" {
|
||||||
|
list = append(list, "impl="+s.Opts.Impl)
|
||||||
|
}
|
||||||
case "v2ray-plugin":
|
case "v2ray-plugin":
|
||||||
if s.Opts.Tls != "" {
|
if s.Opts.Tls != "" {
|
||||||
list = append(list, "tls")
|
list = append(list, "tls")
|
||||||
@ -339,6 +482,9 @@ func (s *Sip003) String() string {
|
|||||||
if s.Opts.Path != "" {
|
if s.Opts.Path != "" {
|
||||||
list = append(list, "path="+s.Opts.Path)
|
list = append(list, "path="+s.Opts.Path)
|
||||||
}
|
}
|
||||||
|
if s.Opts.Impl != "" {
|
||||||
|
list = append(list, "impl="+s.Opts.Impl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(list, ";")
|
return strings.Join(list, ";")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user