mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-04 15:27:55 +07:00
feat/refactor: support the node-level proxy chain (#235)
* feat/refactor: support the chains node * docs: update example.dae * fix: order * fix: http --------- Co-authored-by: dae-bot[bot] <136105375+dae-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -40,11 +40,11 @@ func (d *blockDialer) DialUdp(addr string) (c netproxy.PacketConn, err error) {
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
|
||||
func NewBlockDialer(option *GlobalOption, dialCallback func()) *Dialer {
|
||||
return NewDialer(&blockDialer{DialCallback: dialCallback}, option, InstanceOption{CheckEnabled: false}, Property{
|
||||
func NewBlockDialer(option *GlobalOption, dialCallback func()) (netproxy.Dialer, *Property) {
|
||||
return &blockDialer{DialCallback: dialCallback}, &Property{
|
||||
Name: "block",
|
||||
Address: "",
|
||||
Protocol: "",
|
||||
Link: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ var (
|
||||
|
||||
type Dialer struct {
|
||||
*GlobalOption
|
||||
InstanceOption InstanceOption
|
||||
InstanceOption
|
||||
netproxy.Dialer
|
||||
property Property
|
||||
property *Property
|
||||
|
||||
collectionFineMu sync.Mutex
|
||||
collections [6]*collection
|
||||
@ -57,7 +57,7 @@ type Property struct {
|
||||
type AliveDialerSetSet map[*AliveDialerSet]int
|
||||
|
||||
// NewDialer is for register in general.
|
||||
func NewDialer(dialer netproxy.Dialer, option *GlobalOption, iOption InstanceOption, property Property) *Dialer {
|
||||
func NewDialer(dialer netproxy.Dialer, option *GlobalOption, iOption InstanceOption, property *Property) *Dialer {
|
||||
var collections [6]*collection
|
||||
for i := range collections {
|
||||
collections[i] = newCollection()
|
||||
@ -92,6 +92,6 @@ func (d *Dialer) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dialer) Property() Property {
|
||||
func (d *Dialer) Property() *Property {
|
||||
return d.property
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
softwindDirect "github.com/mzz2017/softwind/protocol/direct"
|
||||
)
|
||||
|
||||
func NewDirectDialer(option *GlobalOption, fullcone bool) *Dialer {
|
||||
property := Property{
|
||||
func NewDirectDialer(option *GlobalOption, fullcone bool) (netproxy.Dialer, *Property) {
|
||||
property := &Property{
|
||||
Name: "direct",
|
||||
Address: "",
|
||||
Protocol: "",
|
||||
Link: "",
|
||||
}
|
||||
if fullcone {
|
||||
return NewDialer(softwindDirect.FullconeDirect, option, InstanceOption{CheckEnabled: false}, property)
|
||||
return softwindDirect.FullconeDirect, property
|
||||
} else {
|
||||
return NewDialer(softwindDirect.SymmetricDirect, option, InstanceOption{CheckEnabled: false}, property)
|
||||
return softwindDirect.SymmetricDirect, property
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/daeuniverse/dae/common"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol/http"
|
||||
)
|
||||
|
||||
@ -28,15 +28,15 @@ type HTTP struct {
|
||||
AllowInsecure bool `json:"allowInsecure"`
|
||||
}
|
||||
|
||||
func NewHTTP(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseHTTPURL(link, option)
|
||||
func NewHTTP(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
s, err := ParseHTTPURL(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
return nil, nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func ParseHTTPURL(link string, option *dialer.GlobalOption) (data *HTTP, err error) {
|
||||
func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
|
||||
return nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
@ -54,6 +54,16 @@ func ParseHTTPURL(link string, option *dialer.GlobalOption) (data *HTTP, err err
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error when parsing port: %w", err)
|
||||
}
|
||||
allowInsecure, _ := strconv.ParseBool(u.Query().Get("allowInsecure"))
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allow_insecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allowinsecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("skipVerify"))
|
||||
}
|
||||
return &HTTP{
|
||||
Name: u.Fragment,
|
||||
Server: u.Hostname(),
|
||||
@ -62,22 +72,22 @@ func ParseHTTPURL(link string, option *dialer.GlobalOption) (data *HTTP, err err
|
||||
Password: pwd,
|
||||
SNI: u.Query().Get("sni"),
|
||||
Protocol: u.Scheme,
|
||||
AllowInsecure: option.AllowInsecure,
|
||||
AllowInsecure: allowInsecure,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *HTTP) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
func (s *HTTP) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
u := s.URL()
|
||||
d, err := http.NewHTTPProxy(&u, direct.SymmetricDirect) // HTTP Proxy does not support full-cone.
|
||||
d, err := http.NewHTTPProxy(&u, nextDialer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: u.String(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *HTTP) URL() url.URL {
|
||||
|
@ -8,11 +8,14 @@ package dialer
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/daeuniverse/dae/common"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
)
|
||||
|
||||
type FromLinkCreator func(gOption *GlobalOption, iOption InstanceOption, link string) (dialer *Dialer, err error)
|
||||
type FromLinkCreator func(gOption *GlobalOption, nextDialer netproxy.Dialer, link string) (dialer netproxy.Dialer, property *Property, err error)
|
||||
|
||||
var fromLinkCreators = make(map[string]FromLinkCreator)
|
||||
|
||||
@ -20,24 +23,55 @@ func FromLinkRegister(name string, creator FromLinkCreator) {
|
||||
fromLinkCreators[name] = creator
|
||||
}
|
||||
|
||||
func NewFromLink(gOption *GlobalOption, iOption InstanceOption, link string) (dialer *Dialer, err error) {
|
||||
func NewFromLink(gOption *GlobalOption, iOption InstanceOption, link string) (*Dialer, error) {
|
||||
/// Get overwritten name.
|
||||
overwrittenName, link := common.GetTagFromLinkLikePlaintext(link)
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
overwrittenName, linklike := common.GetTagFromLinkLikePlaintext(link)
|
||||
links := strings.Split(linklike, "->")
|
||||
d := direct.SymmetricDirect
|
||||
p := &Property{
|
||||
Name: "",
|
||||
Address: "",
|
||||
Protocol: "",
|
||||
Link: link,
|
||||
}
|
||||
if creator, ok := fromLinkCreators[u.Scheme]; ok {
|
||||
node, err := creator(gOption, iOption, link)
|
||||
for i := len(links) - 1; i >= 0; i-- {
|
||||
link := strings.TrimSpace(links[i])
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Overwrite node name using user given tag.
|
||||
if overwrittenName != "" {
|
||||
node.property.Name = overwrittenName
|
||||
creator, ok := fromLinkCreators[u.Scheme]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected link type: %v", u.Scheme)
|
||||
}
|
||||
var _property *Property
|
||||
d, _property, err = creator(gOption, d, link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create %v: %w", link, err)
|
||||
}
|
||||
if p.Name == "" {
|
||||
p.Name = _property.Name
|
||||
} else {
|
||||
p.Name = _property.Name + "->" + p.Name
|
||||
}
|
||||
if p.Protocol == "" {
|
||||
p.Protocol = _property.Protocol
|
||||
} else {
|
||||
p.Protocol = _property.Protocol + "->" + p.Protocol
|
||||
}
|
||||
if p.Address == "" {
|
||||
p.Address = _property.Address
|
||||
} else {
|
||||
p.Address = _property.Address + "->" + p.Address
|
||||
}
|
||||
return node, err
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected link type: %v", u.Scheme)
|
||||
}
|
||||
if overwrittenName != "" {
|
||||
p.Name = overwrittenName
|
||||
}
|
||||
node := NewDialer(d, gOption, iOption, p)
|
||||
// Overwrite node name using user given tag.
|
||||
if overwrittenName != "" {
|
||||
node.property.Name = overwrittenName
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/daeuniverse/dae/component/outbound/transport/simpleobfs"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/mzz2017/softwind/protocol/shadowsocks"
|
||||
)
|
||||
|
||||
@ -36,24 +35,23 @@ type Shadowsocks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksFromLink(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksFromLink(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (npd netproxy.Dialer, property *dialer.Property, err error) {
|
||||
s, err := ParseSSURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
var err error
|
||||
var d netproxy.Dialer
|
||||
d := nextDialer
|
||||
switch s.Plugin.Name {
|
||||
case "simple-obfs":
|
||||
d = direct.SymmetricDirect // Simple-obfs does not supports UDP.
|
||||
switch s.Plugin.Opts.Obfs {
|
||||
case "http", "tls":
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported obfs %v of plugin %v", s.Plugin.Opts.Obfs, s.Plugin.Name)
|
||||
return nil, nil, fmt.Errorf("unsupported obfs %v of plugin %v", s.Plugin.Opts.Obfs, s.Plugin.Name)
|
||||
}
|
||||
host := s.Plugin.Opts.Host
|
||||
if host == "" {
|
||||
@ -69,12 +67,11 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
|
||||
"uri": []string{path},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = simpleobfs.NewSimpleObfs(uSimpleObfs.String(), d)
|
||||
d, _, err = simpleobfs.NewSimpleObfs(option, d, uSimpleObfs.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
default:
|
||||
d = direct.FullconeDirect // Shadowsocks Proxy supports full-cone.
|
||||
}
|
||||
var nextDialerName string
|
||||
switch s.Cipher {
|
||||
@ -83,7 +80,7 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
|
||||
case "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "des-cfb", "bf-cfb", "cast5-cfb", "rc4-md5", "rc4-md5-6", "chacha20", "chacha20-ietf", "salsa20", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "rc4", "none", "plain":
|
||||
nextDialerName = "shadowsocks_stream"
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
||||
return nil, nil, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
||||
}
|
||||
d, err = protocol.NewDialer(nextDialerName, d, protocol.Header{
|
||||
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
@ -92,14 +89,14 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
|
||||
IsClient: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: s.ExportToURL(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseSSURL(u string) (data *Shadowsocks, err error) {
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/daeuniverse/dae/common"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/mzz2017/softwind/protocol/shadowsocks_stream"
|
||||
"github.com/mzz2017/softwind/transport/shadowsocksr/obfs"
|
||||
"github.com/mzz2017/softwind/transport/shadowsocksr/proto"
|
||||
@ -35,16 +35,16 @@ type ShadowsocksR struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksR(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksR(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
s, err := ParseSSRURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
d := direct.SymmetricDirect
|
||||
func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
d := nextDialer
|
||||
obfsDialer, err := obfs.NewDialer(d, &obfs.ObfsParam{
|
||||
ObfsHost: s.Server,
|
||||
ObfsPort: uint16(s.Port),
|
||||
@ -52,7 +52,7 @@ func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.Instan
|
||||
ObfsParam: s.ObfsParam,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
d = obfsDialer
|
||||
d, err = shadowsocks_stream.NewDialer(d, protocol.Header{
|
||||
@ -62,7 +62,7 @@ func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.Instan
|
||||
IsClient: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
d = &proto.Dialer{
|
||||
NextDialer: d,
|
||||
@ -71,12 +71,12 @@ func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.Instan
|
||||
ObfsOverhead: obfsDialer.ObfsOverhead(),
|
||||
}
|
||||
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: s.ExportToURL(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseSSRURL(u string) (data *ShadowsocksR, err error) {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol/socks5"
|
||||
)
|
||||
|
||||
@ -28,28 +28,29 @@ type Socks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewSocks(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
func NewSocks(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
s, err := ParseSocksURL(link)
|
||||
if err != nil {
|
||||
return nil, dialer.InvalidParameterErr
|
||||
return nil, nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *Socks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
func (s *Socks) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
link := s.ExportToURL()
|
||||
d := nextDialer
|
||||
switch s.Protocol {
|
||||
case "", "socks", "socks5":
|
||||
d, err := socks5.NewSocks5Dialer(link, direct.FullconeDirect) // Socks5 Proxy supports full-cone.
|
||||
d, err := socks5.NewSocks5Dialer(link, d) // Socks5 Proxy supports full-cone.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: link,
|
||||
}), nil
|
||||
}, nil
|
||||
//case "socks4", "socks4a":
|
||||
// d, err := socks4.NewSocks4Dialer(link, &proxy.Direct{})
|
||||
// if err != nil {
|
||||
@ -57,7 +58,7 @@ func (s *Socks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
// }
|
||||
// return dialer.NewDialer(d, false, s.Name, s.Protocol, link), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected protocol: %v", s.Protocol)
|
||||
return nil, nil, fmt.Errorf("unexpected protocol: %v", s.Protocol)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/daeuniverse/dae/common/netutils"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
dnsmessage "github.com/miekg/dns"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -23,7 +24,7 @@ func TestSocks5(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log := logrus.StandardLogger()
|
||||
d, err := c.Dialer(&dialer.GlobalOption{
|
||||
d, _, err := c.Dialer(&dialer.GlobalOption{
|
||||
Log: log,
|
||||
TcpCheckOptionRaw: dialer.TcpCheckOptionRaw{
|
||||
Log: log,
|
||||
@ -41,9 +42,7 @@ func TestSocks5(t *testing.T) {
|
||||
AllowInsecure: false,
|
||||
TlsImplementation: "",
|
||||
UtlsImitate: "",
|
||||
}, dialer.InstanceOption{
|
||||
CheckEnabled: false,
|
||||
})
|
||||
}, direct.SymmetricDirect)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -2,18 +2,18 @@ package trojan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daeuniverse/dae/component/outbound/transport/tls"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/daeuniverse/dae/component/outbound/transport/tls"
|
||||
|
||||
"github.com/daeuniverse/dae/common"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/daeuniverse/dae/component/outbound/transport/ws"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
"github.com/mzz2017/softwind/transport/grpc"
|
||||
)
|
||||
|
||||
@ -37,36 +37,36 @@ type Trojan struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewTrojan(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseTrojanURL(link, option)
|
||||
func NewTrojan(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
s, err := ParseTrojanURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
d := direct.FullconeDirect // Trojan Proxy supports full-cone.
|
||||
u := url.URL{
|
||||
Scheme: option.TlsImplementation,
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{s.Sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
}.Encode(),
|
||||
}
|
||||
func (s *Trojan) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
d := nextDialer
|
||||
var err error
|
||||
if s.Type != "grpc" {
|
||||
// grpc contains tls
|
||||
if d, err = tls.NewTls(u.String(), d); err != nil {
|
||||
return nil, err
|
||||
u := url.URL{
|
||||
Scheme: option.TlsImplementation,
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{s.Sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure || option.AllowInsecure)},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
}.Encode(),
|
||||
}
|
||||
if d, _, err = tls.NewTls(option, d, u.String()); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
// "tls,ws,ss,trojanc"
|
||||
switch s.Type {
|
||||
case "ws":
|
||||
u = url.URL{
|
||||
u := url.URL{
|
||||
Scheme: "ws",
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
@ -74,8 +74,8 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
"path": []string{s.Path},
|
||||
}.Encode(),
|
||||
}
|
||||
if d, err = ws.NewWs(u.String(), d); err != nil {
|
||||
return nil, err
|
||||
if d, _, err = ws.NewWs(option, d, u.String()); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case "grpc":
|
||||
serviceName := s.ServiceName
|
||||
@ -86,7 +86,7 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
NextDialer: &netproxy.ContextDialer{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: s.Sni,
|
||||
AllowInsecure: s.AllowInsecure,
|
||||
AllowInsecure: s.AllowInsecure || option.AllowInsecure,
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(s.Encryption, "ss;") {
|
||||
@ -97,7 +97,7 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
Password: fields[2],
|
||||
IsClient: false,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
if d, err = protocol.NewDialer("trojanc", d, protocol.Header{
|
||||
@ -105,17 +105,17 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
Password: s.Password,
|
||||
IsClient: true,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: s.ExportToURL(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseTrojanURL(u string, option *dialer.GlobalOption) (data *Trojan, err error) {
|
||||
func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
//trojan://password@server:port#escape(remarks)
|
||||
t, err := url.Parse(u)
|
||||
if err != nil {
|
||||
@ -123,8 +123,14 @@ func ParseTrojanURL(u string, option *dialer.GlobalOption) (data *Trojan, err er
|
||||
return
|
||||
}
|
||||
allowInsecure, _ := strconv.ParseBool(t.Query().Get("allowInsecure"))
|
||||
if !allowInsecure && option.AllowInsecure {
|
||||
allowInsecure = true
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allow_insecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allowinsecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("skipVerify"))
|
||||
}
|
||||
sni := t.Query().Get("peer")
|
||||
if sni == "" {
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/daeuniverse/dae/common"
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"github.com/mzz2017/softwind/protocol"
|
||||
"github.com/mzz2017/softwind/protocol/direct"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -33,16 +33,16 @@ type Tuic struct {
|
||||
UdpRelayMode string
|
||||
}
|
||||
|
||||
func NewTuic(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseTuicURL(link, option)
|
||||
func NewTuic(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
s, err := ParseTuicURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *Tuic) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
d := direct.FullconeDirect // Tuic Proxy supports full-cone.
|
||||
func (s *Tuic) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
|
||||
d := nextDialer
|
||||
var err error
|
||||
var flags protocol.Flags
|
||||
if s.UdpRelayMode == "quic" {
|
||||
@ -51,23 +51,28 @@ func (s *Tuic) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption
|
||||
if d, err = protocol.NewDialer("tuic", d, protocol.Header{
|
||||
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Feature1: s.CongestionControl,
|
||||
TlsConfig: &tls.Config{NextProtos: s.Alpn, MinVersion: tls.VersionTLS13, ServerName: s.Sni, InsecureSkipVerify: s.AllowInsecure},
|
||||
User: s.User,
|
||||
Password: s.Password,
|
||||
IsClient: true,
|
||||
Flags: flags,
|
||||
TlsConfig: &tls.Config{
|
||||
NextProtos: s.Alpn,
|
||||
MinVersion: tls.VersionTLS13,
|
||||
ServerName: s.Sni,
|
||||
InsecureSkipVerify: s.AllowInsecure || option.AllowInsecure,
|
||||
},
|
||||
User: s.User,
|
||||
Password: s.Password,
|
||||
IsClient: true,
|
||||
Flags: flags,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Name,
|
||||
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
Protocol: s.Protocol,
|
||||
Link: s.ExportToURL(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseTuicURL(u string, option *dialer.GlobalOption) (data *Tuic, err error) {
|
||||
func ParseTuicURL(u string) (data *Tuic, err error) {
|
||||
//trojan://password@server:port#escape(remarks)
|
||||
t, err := url.Parse(u)
|
||||
if err != nil {
|
||||
@ -85,8 +90,11 @@ func ParseTuicURL(u string, option *dialer.GlobalOption) (data *Tuic, err error)
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allow_insecure"))
|
||||
}
|
||||
if !allowInsecure && option.AllowInsecure {
|
||||
allowInsecure = true
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allowinsecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(t.Query().Get("skipVerify"))
|
||||
}
|
||||
sni := t.Query().Get("peer")
|
||||
if sni == "" {
|
||||
|
@ -44,40 +44,37 @@ type V2Ray struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewV2Ray(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
func NewV2Ray(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
var (
|
||||
s *V2Ray
|
||||
err error
|
||||
)
|
||||
switch {
|
||||
case strings.HasPrefix(link, "vmess://"):
|
||||
s, err = ParseVmessURL(link, option)
|
||||
s, err = ParseVmessURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if s.Aid != "0" && s.Aid != "" {
|
||||
return nil, fmt.Errorf("%w: aid: %v, we only support AEAD encryption", dialer.UnexpectedFieldErr, s.Aid)
|
||||
return nil, nil, fmt.Errorf("%w: aid: %v, we only support AEAD encryption", dialer.UnexpectedFieldErr, s.Aid)
|
||||
}
|
||||
case strings.HasPrefix(link, "vless://"):
|
||||
s, err = ParseVlessURL(link, option)
|
||||
s, err = ParseVlessURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
default:
|
||||
return nil, dialer.InvalidParameterErr
|
||||
return nil, nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
return s.Dialer(option, nextDialer)
|
||||
}
|
||||
|
||||
func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (data *dialer.Dialer, err error) {
|
||||
var d netproxy.Dialer
|
||||
func (s *V2Ray) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (npd netproxy.Dialer, property *dialer.Property, err error) {
|
||||
d := nextDialer
|
||||
switch s.Protocol {
|
||||
case "vmess":
|
||||
d = direct.FullconeDirect // VMess Proxy supports full-cone.
|
||||
case "vless":
|
||||
d = direct.SymmetricDirect // VLESS Proxy does not yet support full-cone by softwind.
|
||||
case "vmess", "vless":
|
||||
default:
|
||||
return nil, fmt.Errorf("V2Ray.Dialer: unexpected protocol: %v", s.Protocol)
|
||||
return nil, nil, fmt.Errorf("V2Ray.Dialer: unexpected protocol: %v", s.Protocol)
|
||||
}
|
||||
|
||||
switch strings.ToLower(s.Net) {
|
||||
@ -97,12 +94,12 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
RawQuery: url.Values{
|
||||
"host": []string{s.Host},
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure || option.AllowInsecure)},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = ws.NewWs(u.String(), d)
|
||||
d, _, err = ws.NewWs(option, d, u.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
case "tcp":
|
||||
if s.TLS == "tls" || s.TLS == "xtls" {
|
||||
@ -115,17 +112,17 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
Host: net.JoinHostPort(s.Add, s.Port),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure || option.AllowInsecure)},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = tls.NewTls(u.String(), d)
|
||||
d, _, err = tls.NewTls(option, d, u.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
if s.Type != "none" && s.Type != "" {
|
||||
return nil, fmt.Errorf("%w: type: %v", dialer.UnexpectedFieldErr, s.Type)
|
||||
return nil, nil, fmt.Errorf("%w: type: %v", dialer.UnexpectedFieldErr, s.Type)
|
||||
}
|
||||
case "grpc":
|
||||
sni := s.SNI
|
||||
@ -140,7 +137,7 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
NextDialer: &netproxy.ContextDialer{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: sni,
|
||||
AllowInsecure: s.AllowInsecure,
|
||||
AllowInsecure: s.AllowInsecure || option.AllowInsecure,
|
||||
}
|
||||
case "http", "http2", "h2":
|
||||
sni := s.SNI
|
||||
@ -157,7 +154,7 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
Path: s.Path,
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure || option.AllowInsecure)},
|
||||
"tlsImplementation": []string{option.TlsImplementation},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
"host": []string{s.Host},
|
||||
@ -167,10 +164,10 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
}
|
||||
d, err = http.NewHTTPProxy(&u, direct.SymmetricDirect)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: network: %v", dialer.UnexpectedFieldErr, s.Net)
|
||||
return nil, nil, fmt.Errorf("%w: network: %v", dialer.UnexpectedFieldErr, s.Net)
|
||||
}
|
||||
|
||||
if d, err = protocol.NewDialer(s.Protocol, d, protocol.Header{
|
||||
@ -180,17 +177,17 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
IsClient: true,
|
||||
//Flags: protocol.Flags_VMess_UsePacketAddr,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, dialer.Property{
|
||||
return d, &dialer.Property{
|
||||
Name: s.Ps,
|
||||
Address: net.JoinHostPort(s.Add, s.Port),
|
||||
Protocol: s.Protocol,
|
||||
Link: s.ExportToURL(),
|
||||
}), nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseVlessURL(vless string, option *dialer.GlobalOption) (data *V2Ray, err error) {
|
||||
func ParseVlessURL(vless string) (data *V2Ray, err error) {
|
||||
u, err := url.Parse(vless)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -228,13 +225,10 @@ func ParseVlessURL(vless string, option *dialer.GlobalOption) (data *V2Ray, err
|
||||
if data.Type == "mkcp" || data.Type == "kcp" {
|
||||
data.Path = u.Query().Get("seed")
|
||||
}
|
||||
if option.AllowInsecure {
|
||||
data.AllowInsecure = true
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func ParseVmessURL(vmess string, option *dialer.GlobalOption) (data *V2Ray, err error) {
|
||||
func ParseVmessURL(vmess string) (data *V2Ray, err error) {
|
||||
var info V2Ray
|
||||
// perform base64 decoding and unmarshal to VmessInfo
|
||||
raw, err := common.Base64StdDecode(vmess[8:])
|
||||
@ -252,7 +246,7 @@ func ParseVmessURL(vmess string, option *dialer.GlobalOption) (data *V2Ray, err
|
||||
s := strings.Split(vmess[8:], "?")[0]
|
||||
s, err = common.Base64StdDecode(s)
|
||||
if err != nil {
|
||||
s, err = common.Base64UrlDecode(s)
|
||||
s, _ = common.Base64UrlDecode(s)
|
||||
}
|
||||
subMatch := re.FindStringSubmatch(s)
|
||||
if subMatch == nil {
|
||||
@ -310,9 +304,6 @@ func ParseVmessURL(vmess string, option *dialer.GlobalOption) (data *V2Ray, err
|
||||
info.Aid = "0"
|
||||
}
|
||||
info.Protocol = "vmess"
|
||||
if option.AllowInsecure {
|
||||
info.AllowInsecure = true
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ func NewDialerSetFromLinks(option *dialer.GlobalOption, tagToNodeList map[string
|
||||
for _, node := range nodes {
|
||||
d, err := dialer.NewFromLink(option, dialer.InstanceOption{CheckEnabled: false}, node)
|
||||
if err != nil {
|
||||
option.Log.Infof("failed to parse node: %v: %v", node, err)
|
||||
option.Log.Infof("failed to parse node: %v", err)
|
||||
continue
|
||||
}
|
||||
s.dialers = append(s.dialers, d)
|
||||
|
@ -13,6 +13,9 @@ import (
|
||||
_ "github.com/daeuniverse/dae/component/outbound/dialer/trojan"
|
||||
_ "github.com/daeuniverse/dae/component/outbound/dialer/tuic"
|
||||
_ "github.com/daeuniverse/dae/component/outbound/dialer/v2ray"
|
||||
_ "github.com/daeuniverse/dae/component/outbound/transport/simpleobfs"
|
||||
_ "github.com/daeuniverse/dae/component/outbound/transport/tls"
|
||||
_ "github.com/daeuniverse/dae/component/outbound/transport/ws"
|
||||
_ "github.com/mzz2017/softwind/protocol/shadowsocks"
|
||||
_ "github.com/mzz2017/softwind/protocol/trojanc"
|
||||
_ "github.com/mzz2017/softwind/protocol/tuic"
|
||||
|
7
component/outbound/transport/simpleobfs/dialer.go
Normal file
7
component/outbound/transport/simpleobfs/dialer.go
Normal file
@ -0,0 +1,7 @@
|
||||
package simpleobfs
|
||||
|
||||
import "github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
|
||||
func init() {
|
||||
dialer.FromLinkRegister("simpleobfs", NewSimpleObfs)
|
||||
}
|
@ -2,10 +2,12 @@ package simpleobfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
)
|
||||
|
||||
type ObfsType int
|
||||
@ -25,14 +27,14 @@ type SimpleObfs struct {
|
||||
}
|
||||
|
||||
// NewSimpleobfs returns a simpleobfs proxy.
|
||||
func NewSimpleObfs(s string, d netproxy.Dialer) (*SimpleObfs, error) {
|
||||
u, err := url.Parse(s)
|
||||
func NewSimpleObfs(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("simpleobfs: %w", err)
|
||||
return nil, nil, fmt.Errorf("simpleobfs: %w", err)
|
||||
}
|
||||
|
||||
t := &SimpleObfs{
|
||||
dialer: d,
|
||||
dialer: nextDialer,
|
||||
addr: u.Host,
|
||||
}
|
||||
query := u.Query()
|
||||
@ -46,14 +48,19 @@ func NewSimpleObfs(s string, d netproxy.Dialer) (*SimpleObfs, error) {
|
||||
case "tls":
|
||||
t.obfstype = TLS
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported obfs type %v", obfstype)
|
||||
return nil, nil, fmt.Errorf("unsupported obfs type %v", obfstype)
|
||||
}
|
||||
t.host = query.Get("host")
|
||||
t.path = query.Get("path")
|
||||
if t.path == "" {
|
||||
t.path = query.Get("uri")
|
||||
}
|
||||
return t, nil
|
||||
return t, &dialer.Property{
|
||||
Name: u.Fragment,
|
||||
Address: t.addr,
|
||||
Protocol: "simpleobfs(" + obfstype + ")",
|
||||
Link: link,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SimpleObfs) Dial(network, addr string) (c netproxy.Conn, err error) {
|
||||
|
8
component/outbound/transport/tls/dialer.go
Normal file
8
component/outbound/transport/tls/dialer.go
Normal file
@ -0,0 +1,8 @@
|
||||
package tls
|
||||
|
||||
import "github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
|
||||
func init() {
|
||||
dialer.FromLinkRegister("tls", NewTls)
|
||||
dialer.FromLinkRegister("utls", NewTls)
|
||||
}
|
@ -4,7 +4,10 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
utls "github.com/refraction-networking/utls"
|
||||
)
|
||||
@ -22,36 +25,57 @@ type Tls struct {
|
||||
}
|
||||
|
||||
// NewTls returns a Tls infra.
|
||||
func NewTls(s string, d netproxy.Dialer) (*Tls, error) {
|
||||
u, err := url.Parse(s)
|
||||
func NewTls(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NewTls: %w", err)
|
||||
}
|
||||
|
||||
t := &Tls{
|
||||
dialer: d,
|
||||
addr: u.Host,
|
||||
tlsImplentation: u.Scheme,
|
||||
return nil, nil, fmt.Errorf("NewTls: %w", err)
|
||||
}
|
||||
|
||||
query := u.Query()
|
||||
t.serverName = query.Get("sni")
|
||||
t.utlsImitate = query.Get("utlsImitate")
|
||||
|
||||
// skipVerify
|
||||
if query.Get("allowInsecure") == "true" || query.Get("allowInsecure") == "1" ||
|
||||
query.Get("skipVerify") == "true" || query.Get("skipVerify") == "1" {
|
||||
t.skipVerify = true
|
||||
tlsImplentation := u.Scheme
|
||||
utlsImitate := query.Get("utlsImitate")
|
||||
if tlsImplentation == "tls" && option.TlsImplementation != "" {
|
||||
tlsImplentation = option.TlsImplementation
|
||||
utlsImitate = option.UtlsImitate
|
||||
}
|
||||
t := &Tls{
|
||||
dialer: nextDialer,
|
||||
addr: u.Host,
|
||||
tlsImplentation: tlsImplentation,
|
||||
utlsImitate: utlsImitate,
|
||||
serverName: query.Get("sni"),
|
||||
}
|
||||
if t.serverName == "" {
|
||||
t.serverName = u.Hostname()
|
||||
}
|
||||
|
||||
// skipVerify
|
||||
allowInsecure, _ := strconv.ParseBool(u.Query().Get("allowInsecure"))
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allow_insecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allowinsecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("skipVerify"))
|
||||
}
|
||||
t.skipVerify = allowInsecure || option.AllowInsecure
|
||||
t.tlsConfig = &tls.Config{
|
||||
ServerName: t.serverName,
|
||||
InsecureSkipVerify: t.skipVerify,
|
||||
}
|
||||
if len(query.Get("alpn")) > 0 {
|
||||
t.tlsConfig.NextProtos = strings.Split(query.Get("alpn"), ",")
|
||||
}
|
||||
|
||||
return t, nil
|
||||
return t, &dialer.Property{
|
||||
Name: u.Fragment,
|
||||
Address: t.addr,
|
||||
Protocol: tlsImplentation,
|
||||
Link: link,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Tls) Dial(network, addr string) (c netproxy.Conn, err error) {
|
||||
@ -61,7 +85,7 @@ func (s *Tls) Dial(network, addr string) (c netproxy.Conn, err error) {
|
||||
}
|
||||
switch magicNetwork.Network {
|
||||
case "tcp":
|
||||
rc, err := s.dialer.Dial(network, addr)
|
||||
rc, err := s.dialer.Dial(network, s.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[Tls]: dial to %s: %w", s.addr, err)
|
||||
}
|
||||
|
10
component/outbound/transport/ws/dialer.go
Normal file
10
component/outbound/transport/ws/dialer.go
Normal file
@ -0,0 +1,10 @@
|
||||
package ws
|
||||
|
||||
import (
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dialer.FromLinkRegister("ws", NewWs)
|
||||
dialer.FromLinkRegister("wss", NewWs)
|
||||
}
|
@ -7,7 +7,9 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/daeuniverse/dae/component/outbound/dialer"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
)
|
||||
@ -21,14 +23,14 @@ type Ws struct {
|
||||
}
|
||||
|
||||
// NewWs returns a Ws infra.
|
||||
func NewWs(s string, d netproxy.Dialer) (*Ws, error) {
|
||||
u, err := url.Parse(s)
|
||||
func NewWs(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NewWs: %w", err)
|
||||
return nil, nil, fmt.Errorf("NewWs: %w", err)
|
||||
}
|
||||
|
||||
t := &Ws{
|
||||
dialer: d,
|
||||
dialer: nextDialer,
|
||||
}
|
||||
|
||||
query := u.Query()
|
||||
@ -45,13 +47,31 @@ func NewWs(s string, d netproxy.Dialer) (*Ws, error) {
|
||||
}
|
||||
t.wsAddr = wsUrl.String() + u.Path
|
||||
if u.Scheme == "wss" {
|
||||
skipVerify, _ := strconv.ParseBool(query.Get("allowInsecure"))
|
||||
allowInsecure, _ := strconv.ParseBool(u.Query().Get("allowInsecure"))
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allow_insecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("allowinsecure"))
|
||||
}
|
||||
if !allowInsecure {
|
||||
allowInsecure, _ = strconv.ParseBool(u.Query().Get("skipVerify"))
|
||||
}
|
||||
// TODO: utls
|
||||
t.tlsClientConfig = &tls.Config{
|
||||
ServerName: query.Get("sni"),
|
||||
InsecureSkipVerify: skipVerify,
|
||||
InsecureSkipVerify: allowInsecure || option.AllowInsecure,
|
||||
}
|
||||
if len(query.Get("alpn")) > 0 {
|
||||
t.tlsClientConfig.NextProtos = strings.Split(query.Get("alpn"), ",")
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
return t, &dialer.Property{
|
||||
Name: u.Fragment,
|
||||
Address: wsUrl.Host,
|
||||
Protocol: u.Scheme,
|
||||
Link: link,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Ws) Dial(network, addr string) (c netproxy.Conn, err error) {
|
||||
|
@ -256,15 +256,19 @@ func NewControlPlane(
|
||||
sniffingTimeout = 0
|
||||
}
|
||||
disableKernelAliveCallback := dialMode != consts.DialMode_Ip
|
||||
_direct, directProperty := dialer.NewDirectDialer(option, true)
|
||||
direct := dialer.NewDialer(_direct, option, dialer.InstanceOption{CheckEnabled: false}, directProperty)
|
||||
_block, blockProperty := dialer.NewBlockDialer(option, func() { /*Dialer Outbound*/ })
|
||||
block := dialer.NewDialer(_block, option, dialer.InstanceOption{CheckEnabled: false}, blockProperty)
|
||||
outbounds := []*outbound.DialerGroup{
|
||||
outbound.NewDialerGroup(option, consts.OutboundDirect.String(),
|
||||
[]*dialer.Dialer{dialer.NewDirectDialer(option, true)}, []*dialer.Annotation{{}},
|
||||
[]*dialer.Dialer{direct}, []*dialer.Annotation{{}},
|
||||
outbound.DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Fixed,
|
||||
FixedIndex: 0,
|
||||
}, core.outboundAliveChangeCallback(0, disableKernelAliveCallback)),
|
||||
outbound.NewDialerGroup(option, consts.OutboundBlock.String(),
|
||||
[]*dialer.Dialer{dialer.NewBlockDialer(option, func() { /*Dialer Outbound*/ })}, []*dialer.Annotation{{}},
|
||||
[]*dialer.Dialer{block}, []*dialer.Annotation{{}},
|
||||
outbound.DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Fixed,
|
||||
FixedIndex: 0,
|
||||
|
@ -112,6 +112,7 @@ node {
|
||||
mylink: 'ss://LINK'
|
||||
node1: 'vmess://LINK'
|
||||
node2: 'vless://LINK'
|
||||
chains: 'tuic://LINK -> vmess://LINK'
|
||||
}
|
||||
|
||||
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/dns.md for full examples.
|
||||
|
2
go.mod
2
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/miekg/dns v1.1.55
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/mzz2017/softwind v0.0.0-20230722080658-973f985df174
|
||||
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8
|
||||
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
|
||||
github.com/safchain/ethtool v0.3.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
|
4
go.sum
4
go.sum
@ -91,8 +91,8 @@ github.com/mzz2017/disk-bloom v1.0.1 h1:rEF9MiXd9qMW3ibRpqcerLXULoTgRlM21yqqJl1B
|
||||
github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI=
|
||||
github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7 h1:9zmZilN02x3byMB2X3x+B4iyKHkucv70WA4hsyZkjo8=
|
||||
github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7/go.mod h1:3H6d55CEofIWWr3gQThiB27+hA3WG5tATtPovzEYPAA=
|
||||
github.com/mzz2017/softwind v0.0.0-20230722080658-973f985df174 h1:I4JKJSOCxUtFgiMB5VpoqdC70tncD1UkKd2Qvi5/A0o=
|
||||
github.com/mzz2017/softwind v0.0.0-20230722080658-973f985df174/go.mod h1:Fz8fgR7/dbnfR6RLpeOMkUDyebq4xShdmjj+cE5jnJ4=
|
||||
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8 h1:T/VA4g5qkPeZFvZ+gkx4SK9wijDSOgFwumEZAxdHZ8U=
|
||||
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8/go.mod h1:Fz8fgR7/dbnfR6RLpeOMkUDyebq4xShdmjj+cE5jnJ4=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
|
Reference in New Issue
Block a user