mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add shadowsocksr outbound
This commit is contained in:
parent
ce567ffdde
commit
9913e0e025
2
Makefile
2
Makefile
|
@ -64,7 +64,7 @@ test:
|
||||||
@go test -v . && \
|
@go test -v . && \
|
||||||
pushd test && \
|
pushd test && \
|
||||||
go mod tidy && \
|
go mod tidy && \
|
||||||
go test -v -tags with_quic,with_wireguard,with_grpc,with_ech,with_utls . && \
|
go test -v -tags with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_shadowsocksr . && \
|
||||||
popd
|
popd
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -1,24 +1,25 @@
|
||||||
package constant
|
package constant
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeTun = "tun"
|
TypeTun = "tun"
|
||||||
TypeRedirect = "redirect"
|
TypeRedirect = "redirect"
|
||||||
TypeTProxy = "tproxy"
|
TypeTProxy = "tproxy"
|
||||||
TypeDirect = "direct"
|
TypeDirect = "direct"
|
||||||
TypeBlock = "block"
|
TypeBlock = "block"
|
||||||
TypeDNS = "dns"
|
TypeDNS = "dns"
|
||||||
TypeSocks = "socks"
|
TypeSocks = "socks"
|
||||||
TypeHTTP = "http"
|
TypeHTTP = "http"
|
||||||
TypeMixed = "mixed"
|
TypeMixed = "mixed"
|
||||||
TypeShadowsocks = "shadowsocks"
|
TypeShadowsocks = "shadowsocks"
|
||||||
TypeVMess = "vmess"
|
TypeVMess = "vmess"
|
||||||
TypeTrojan = "trojan"
|
TypeTrojan = "trojan"
|
||||||
TypeNaive = "naive"
|
TypeNaive = "naive"
|
||||||
TypeWireGuard = "wireguard"
|
TypeWireGuard = "wireguard"
|
||||||
TypeHysteria = "hysteria"
|
TypeHysteria = "hysteria"
|
||||||
TypeTor = "tor"
|
TypeTor = "tor"
|
||||||
TypeSSH = "ssh"
|
TypeSSH = "ssh"
|
||||||
TypeShadowTLS = "shadowtls"
|
TypeShadowTLS = "shadowtls"
|
||||||
|
TypeShadowsocksR = "shadowsocksr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -23,6 +23,7 @@ require (
|
||||||
github.com/refraction-networking/utls v1.1.2
|
github.com/refraction-networking/utls v1.1.2
|
||||||
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
|
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0
|
||||||
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -143,6 +143,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTYRwpwvEm3nc4eRdxk6vtRbouLVZAzk=
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTYRwpwvEm3nc4eRdxk6vtRbouLVZAzk=
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0 h1:lQ4RFWY/wBYmXl/zJJCwQbhiEIbgEqC7j+nhZYkgwmU=
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0/go.mod h1:xSHLCsdgy5QIozXFEv6uDgMWzyrRdFFjr3TgL+juu6g=
|
||||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f h1:w1TJq7Lw3It35tDyMsZLtYz4T2msf1UK9JxC85L5+sk=
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f h1:w1TJq7Lw3It35tDyMsZLtYz4T2msf1UK9JxC85L5+sk=
|
||||||
|
@ -192,6 +194,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
||||||
|
@ -245,6 +248,7 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -264,6 +268,7 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
|
||||||
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
|
|
@ -8,20 +8,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type _Outbound struct {
|
type _Outbound struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
DirectOptions DirectOutboundOptions `json:"-"`
|
DirectOptions DirectOutboundOptions `json:"-"`
|
||||||
SocksOptions SocksOutboundOptions `json:"-"`
|
SocksOptions SocksOutboundOptions `json:"-"`
|
||||||
HTTPOptions HTTPOutboundOptions `json:"-"`
|
HTTPOptions HTTPOutboundOptions `json:"-"`
|
||||||
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
||||||
VMessOptions VMessOutboundOptions `json:"-"`
|
VMessOptions VMessOutboundOptions `json:"-"`
|
||||||
TrojanOptions TrojanOutboundOptions `json:"-"`
|
TrojanOptions TrojanOutboundOptions `json:"-"`
|
||||||
WireGuardOptions WireGuardOutboundOptions `json:"-"`
|
WireGuardOptions WireGuardOutboundOptions `json:"-"`
|
||||||
HysteriaOptions HysteriaOutboundOptions `json:"-"`
|
HysteriaOptions HysteriaOutboundOptions `json:"-"`
|
||||||
TorOptions TorOutboundOptions `json:"-"`
|
TorOptions TorOutboundOptions `json:"-"`
|
||||||
SSHOptions SSHOutboundOptions `json:"-"`
|
SSHOptions SSHOutboundOptions `json:"-"`
|
||||||
ShadowTLSOptions ShadowTLSOutboundOptions `json:"-"`
|
ShadowTLSOptions ShadowTLSOutboundOptions `json:"-"`
|
||||||
SelectorOptions SelectorOutboundOptions `json:"-"`
|
ShadowsocksROptions ShadowsocksROutboundOptions `json:"-"`
|
||||||
|
SelectorOptions SelectorOutboundOptions `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Outbound _Outbound
|
type Outbound _Outbound
|
||||||
|
@ -53,6 +54,8 @@ func (h Outbound) MarshalJSON() ([]byte, error) {
|
||||||
v = h.SSHOptions
|
v = h.SSHOptions
|
||||||
case C.TypeShadowTLS:
|
case C.TypeShadowTLS:
|
||||||
v = h.ShadowTLSOptions
|
v = h.ShadowTLSOptions
|
||||||
|
case C.TypeShadowsocksR:
|
||||||
|
v = h.ShadowsocksROptions
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
v = h.SelectorOptions
|
v = h.SelectorOptions
|
||||||
default:
|
default:
|
||||||
|
@ -92,6 +95,8 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||||
v = &h.SSHOptions
|
v = &h.SSHOptions
|
||||||
case C.TypeShadowTLS:
|
case C.TypeShadowTLS:
|
||||||
v = &h.ShadowTLSOptions
|
v = &h.ShadowTLSOptions
|
||||||
|
case C.TypeShadowsocksR:
|
||||||
|
v = &h.ShadowsocksROptions
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
v = &h.SelectorOptions
|
v = &h.SelectorOptions
|
||||||
default:
|
default:
|
||||||
|
|
13
option/shadowsocksr.go
Normal file
13
option/shadowsocksr.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package option
|
||||||
|
|
||||||
|
type ShadowsocksROutboundOptions struct {
|
||||||
|
DialerOptions
|
||||||
|
ServerOptions
|
||||||
|
Method string `json:"method"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Obfs string `json:"obfs,omitempty"`
|
||||||
|
ObfsParam string `json:"obfs_param,omitempty"`
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
ProtocolParam string `json:"protocol_param,omitempty"`
|
||||||
|
Network NetworkList `json:"network,omitempty"`
|
||||||
|
}
|
|
@ -41,6 +41,8 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o
|
||||||
return NewSSH(ctx, router, logger, options.Tag, options.SSHOptions)
|
return NewSSH(ctx, router, logger, options.Tag, options.SSHOptions)
|
||||||
case C.TypeShadowTLS:
|
case C.TypeShadowTLS:
|
||||||
return NewShadowTLS(ctx, router, logger, options.Tag, options.ShadowTLSOptions)
|
return NewShadowTLS(ctx, router, logger, options.Tag, options.ShadowTLSOptions)
|
||||||
|
case C.TypeShadowsocksR:
|
||||||
|
return NewShadowsocksR(ctx, router, logger, options.Tag, options.ShadowsocksROptions)
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
return NewSelector(router, logger, options.Tag, options.SelectorOptions)
|
return NewSelector(router, logger, options.Tag, options.SelectorOptions)
|
||||||
default:
|
default:
|
||||||
|
|
140
outbound/shadowsocksr.go
Normal file
140
outbound/shadowsocksr.go
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
//go:build with_shadowsocksr
|
||||||
|
|
||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/shadowsocksr"
|
||||||
|
"github.com/sagernet/shadowsocksr/obfs"
|
||||||
|
"github.com/sagernet/shadowsocksr/protocol"
|
||||||
|
"github.com/sagernet/shadowsocksr/ssr"
|
||||||
|
"github.com/sagernet/shadowsocksr/streamCipher"
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-shadowsocks"
|
||||||
|
"github.com/sagernet/sing-shadowsocks/shadowimpl"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ adapter.Outbound = (*ShadowsocksR)(nil)
|
||||||
|
|
||||||
|
type ShadowsocksR struct {
|
||||||
|
myOutboundAdapter
|
||||||
|
dialer N.Dialer
|
||||||
|
serverAddr M.Socksaddr
|
||||||
|
method shadowsocks.Method
|
||||||
|
cipher string
|
||||||
|
password string
|
||||||
|
obfs string
|
||||||
|
obfsParams *ssr.ServerInfo
|
||||||
|
protocol string
|
||||||
|
protocolParams *ssr.ServerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
|
||||||
|
outbound := &ShadowsocksR{
|
||||||
|
myOutboundAdapter: myOutboundAdapter{
|
||||||
|
protocol: C.TypeShadowsocksR,
|
||||||
|
network: options.Network.Build(),
|
||||||
|
router: router,
|
||||||
|
logger: logger,
|
||||||
|
tag: tag,
|
||||||
|
},
|
||||||
|
dialer: dialer.New(router, options.DialerOptions),
|
||||||
|
serverAddr: options.ServerOptions.Build(),
|
||||||
|
cipher: options.Method,
|
||||||
|
password: options.Password,
|
||||||
|
obfs: options.Obfs,
|
||||||
|
protocol: options.Protocol,
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
outbound.method, err = shadowimpl.FetchMethod(options.Method, options.Password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, err = streamCipher.NewStreamCipher(options.Method, options.Password); err != nil {
|
||||||
|
return nil, E.New(strings.ToLower(err.Error()))
|
||||||
|
}
|
||||||
|
if obfs.NewObfs(options.Obfs) == nil {
|
||||||
|
return nil, E.New("unknown obfs: " + options.Obfs)
|
||||||
|
}
|
||||||
|
outbound.obfsParams = &ssr.ServerInfo{
|
||||||
|
Host: outbound.serverAddr.AddrString(),
|
||||||
|
Port: outbound.serverAddr.Port,
|
||||||
|
TcpMss: 1460,
|
||||||
|
Param: options.ObfsParam,
|
||||||
|
}
|
||||||
|
if protocol.NewProtocol(options.Protocol) == nil {
|
||||||
|
return nil, E.New("unknown protocol: " + options.Protocol)
|
||||||
|
}
|
||||||
|
outbound.protocolParams = &ssr.ServerInfo{
|
||||||
|
Host: outbound.serverAddr.AddrString(),
|
||||||
|
Port: outbound.serverAddr.Port,
|
||||||
|
TcpMss: 1460,
|
||||||
|
Param: options.Protocol,
|
||||||
|
}
|
||||||
|
if outbound.method == nil {
|
||||||
|
outbound.network = common.Filter(outbound.network, func(it string) bool { return it == N.NetworkTCP })
|
||||||
|
}
|
||||||
|
return outbound, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
switch network {
|
||||||
|
case N.NetworkTCP:
|
||||||
|
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
||||||
|
conn, err := h.dialer.DialContext(ctx, network, h.serverAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cipher, err := streamCipher.NewStreamCipher(h.cipher, h.password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.New(strings.ToLower(err.Error()))
|
||||||
|
}
|
||||||
|
ssConn := shadowsocksr.NewSSTCPConn(conn, cipher)
|
||||||
|
ssConn.IObfs = obfs.NewObfs(h.obfs)
|
||||||
|
ssConn.IObfs.SetServerInfo(h.obfsParams)
|
||||||
|
ssConn.IProtocol = protocol.NewProtocol(h.protocol)
|
||||||
|
ssConn.IProtocol.SetServerInfo(h.protocolParams)
|
||||||
|
err = M.SocksaddrSerializer.WriteAddrPort(ssConn, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "write request")
|
||||||
|
}
|
||||||
|
return ssConn, nil
|
||||||
|
case N.NetworkUDP:
|
||||||
|
conn, err := h.ListenPacket(ctx, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &bufio.BindPacketConn{PacketConn: conn, Addr: destination}, nil
|
||||||
|
default:
|
||||||
|
return nil, E.Extend(N.ErrUnknownNetwork, network)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ShadowsocksR) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
|
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return h.method.DialPacketConn(outConn), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ShadowsocksR) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ShadowsocksR) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
|
}
|
16
outbound/shadowsocksr_stub.go
Normal file
16
outbound/shadowsocksr_stub.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//go:build !with_shadowsocksr
|
||||||
|
|
||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (adapter.Outbound, error) {
|
||||||
|
return nil, E.New(`ShadowsocksR is not included in this build, rebuild with -tags with_shadowsocksr`)
|
||||||
|
}
|
|
@ -53,8 +53,8 @@ func testSuit(t *testing.T, clientPort uint16, testPort uint16) {
|
||||||
dialUDP := func() (net.PacketConn, error) {
|
dialUDP := func() (net.PacketConn, error) {
|
||||||
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
||||||
}
|
}
|
||||||
// require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||||
// require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
||||||
require.NoError(t, testLargeDataWithConn(t, testPort, dialTCP))
|
require.NoError(t, testLargeDataWithConn(t, testPort, dialTCP))
|
||||||
require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
|
||||||
|
|
||||||
|
@ -80,6 +80,8 @@ func testSuitSimple(t *testing.T, clientPort uint16, testPort uint16) {
|
||||||
}
|
}
|
||||||
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||||
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
||||||
|
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||||
|
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSuitWg(t *testing.T, clientPort uint16, testPort uint16) {
|
func testSuitWg(t *testing.T, clientPort uint16, testPort uint16) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ const (
|
||||||
ImageHysteria = "tobyxdd/hysteria:latest"
|
ImageHysteria = "tobyxdd/hysteria:latest"
|
||||||
ImageNginx = "nginx:stable"
|
ImageNginx = "nginx:stable"
|
||||||
ImageShadowTLS = "ghcr.io/ihciah/shadow-tls:latest"
|
ImageShadowTLS = "ghcr.io/ihciah/shadow-tls:latest"
|
||||||
|
ImageShadowsocksR = "teddysun/shadowsocks-r:latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allImages = []string{
|
var allImages = []string{
|
||||||
|
@ -49,6 +50,7 @@ var allImages = []string{
|
||||||
ImageHysteria,
|
ImageHysteria,
|
||||||
ImageNginx,
|
ImageNginx,
|
||||||
ImageShadowTLS,
|
ImageShadowTLS,
|
||||||
|
ImageShadowsocksR,
|
||||||
}
|
}
|
||||||
|
|
||||||
var localIP = netip.MustParseAddr("127.0.0.1")
|
var localIP = netip.MustParseAddr("127.0.0.1")
|
||||||
|
|
19
test/config/shadowsocksr.json
Normal file
19
test/config/shadowsocksr.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"server": "0.0.0.0",
|
||||||
|
"server_ipv6": "::",
|
||||||
|
"server_port": 10000,
|
||||||
|
"local_address": "127.0.0.1",
|
||||||
|
"local_port": 1080,
|
||||||
|
"password": "password0",
|
||||||
|
"timeout": 120,
|
||||||
|
"method": "aes-256-cfb",
|
||||||
|
"protocol": "origin",
|
||||||
|
"protocol_param": "",
|
||||||
|
"obfs": "plain",
|
||||||
|
"obfs_param": "",
|
||||||
|
"redirect": "",
|
||||||
|
"dns_ipv6": false,
|
||||||
|
"fast_open": true,
|
||||||
|
"workers": 1,
|
||||||
|
"forbidden_ip": ""
|
||||||
|
}
|
|
@ -66,8 +66,9 @@ require (
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb // indirect
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb // indirect
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0 // indirect
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 // indirect
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 // indirect
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb // indirect
|
github.com/sagernet/sing-tun v0.0.0-20220911034209-c7dd5d457e24 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f // indirect
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
|
|
|
@ -163,6 +163,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTYRwpwvEm3nc4eRdxk6vtRbouLVZAzk=
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTYRwpwvEm3nc4eRdxk6vtRbouLVZAzk=
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0 h1:lQ4RFWY/wBYmXl/zJJCwQbhiEIbgEqC7j+nhZYkgwmU=
|
||||||
|
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0/go.mod h1:xSHLCsdgy5QIozXFEv6uDgMWzyrRdFFjr3TgL+juu6g=
|
||||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f h1:w1TJq7Lw3It35tDyMsZLtYz4T2msf1UK9JxC85L5+sk=
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f h1:w1TJq7Lw3It35tDyMsZLtYz4T2msf1UK9JxC85L5+sk=
|
||||||
|
@ -171,8 +173,8 @@ github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFx
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb h1:/swVU2mgwDwZ9l67v1Sim1ias/ZmriGTxQLnMakPhtQ=
|
github.com/sagernet/sing-tun v0.0.0-20220911034209-c7dd5d457e24 h1:LsmPeFvj4GhiV5Y7Rm8I845XysdxVN4MQmfZ36P5bmw=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
github.com/sagernet/sing-tun v0.0.0-20220911034209-c7dd5d457e24/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f h1:6l9aXZqAl1JqXJWi89KHpWnM/moQUPGG+XiwMc+yD0A=
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f h1:6l9aXZqAl1JqXJWi89KHpWnM/moQUPGG+XiwMc+yD0A=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
|
||||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
||||||
|
@ -216,6 +218,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
||||||
|
@ -295,6 +298,7 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
|
||||||
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
|
|
@ -9,9 +9,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHysteriaSelf(t *testing.T) {
|
func TestHysteriaSelf(t *testing.T) {
|
||||||
if !C.QUIC_AVAILABLE {
|
|
||||||
t.Skip("QUIC not included")
|
|
||||||
}
|
|
||||||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
|
@ -84,9 +81,6 @@ func TestHysteriaSelf(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHysteriaInbound(t *testing.T) {
|
func TestHysteriaInbound(t *testing.T) {
|
||||||
if !C.QUIC_AVAILABLE {
|
|
||||||
t.Skip("QUIC not included")
|
|
||||||
}
|
|
||||||
caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
|
@ -120,13 +114,10 @@ func TestHysteriaInbound(t *testing.T) {
|
||||||
caPem: "/etc/hysteria/ca.pem",
|
caPem: "/etc/hysteria/ca.pem",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
testSuit(t, clientPort, testPort)
|
testSuitSimple(t, clientPort, testPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHysteriaOutbound(t *testing.T) {
|
func TestHysteriaOutbound(t *testing.T) {
|
||||||
if !C.QUIC_AVAILABLE {
|
|
||||||
t.Skip("QUIC not included")
|
|
||||||
}
|
|
||||||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
startDockerContainer(t, DockerOptions{
|
startDockerContainer(t, DockerOptions{
|
||||||
Image: ImageHysteria,
|
Image: ImageHysteria,
|
||||||
|
|
|
@ -99,9 +99,6 @@ func TestNaiveInbound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNaiveHTTP3Inbound(t *testing.T) {
|
func TestNaiveHTTP3Inbound(t *testing.T) {
|
||||||
if !C.QUIC_AVAILABLE {
|
|
||||||
t.Skip("QUIC not included")
|
|
||||||
}
|
|
||||||
caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
|
|
48
test/shadowsocksr_test.go
Normal file
48
test/shadowsocksr_test.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShadowsocksR(t *testing.T) {
|
||||||
|
startDockerContainer(t, DockerOptions{
|
||||||
|
Image: ImageShadowsocksR,
|
||||||
|
Ports: []uint16{serverPort, testPort},
|
||||||
|
Bind: map[string]string{
|
||||||
|
"shadowsocksr.json": "/etc/shadowsocks-r/config.json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
startInstance(t, option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeMixed,
|
||||||
|
MixedOptions: option.HTTPMixedInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.ListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: clientPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbounds: []option.Outbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeShadowsocksR,
|
||||||
|
ShadowsocksROptions: option.ShadowsocksROutboundOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "127.0.0.1",
|
||||||
|
ServerPort: serverPort,
|
||||||
|
},
|
||||||
|
Method: "aes-256-cfb",
|
||||||
|
Password: "password0",
|
||||||
|
Obfs: "plain",
|
||||||
|
Protocol: "origin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testSuit(t, clientPort, testPort)
|
||||||
|
}
|
|
@ -19,6 +19,9 @@ type Plugin interface {
|
||||||
var plugins map[string]PluginConstructor
|
var plugins map[string]PluginConstructor
|
||||||
|
|
||||||
func RegisterPlugin(name string, constructor PluginConstructor) {
|
func RegisterPlugin(name string, constructor PluginConstructor) {
|
||||||
|
if plugins == nil {
|
||||||
|
plugins = make(map[string]PluginConstructor)
|
||||||
|
}
|
||||||
plugins[name] = constructor
|
plugins[name] = constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue