mirror of
https://github.com/daeuniverse/dae.git
synced 2025-02-22 12:38:34 +07:00
feat/fix: support allow_insecure and fix ws path with query
This commit is contained in:
parent
16a85e3c68
commit
7656a6ecaf
@ -353,3 +353,11 @@ func GetTagFromLinkLikePlaintext(link string) (tag string, afterTag string) {
|
||||
// Else tag is the part before colon.
|
||||
return link[:iColon], link[iColon+1:]
|
||||
}
|
||||
|
||||
func BoolToString(b bool) string {
|
||||
if b {
|
||||
return "1"
|
||||
} else {
|
||||
return "0"
|
||||
}
|
||||
}
|
||||
|
@ -39,10 +39,11 @@ type GlobalOption struct {
|
||||
CheckInterval time.Duration
|
||||
CheckTolerance time.Duration
|
||||
CheckDnsTcp bool
|
||||
AllowInsecure bool
|
||||
}
|
||||
|
||||
type InstanceOption struct {
|
||||
CheckEnabled bool
|
||||
CheckEnabled bool
|
||||
}
|
||||
|
||||
type AliveDialerSetSet map[*AliveDialerSet]int
|
||||
|
@ -3,6 +3,7 @@ package http
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mzz2017/softwind/protocol/http"
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"net"
|
||||
"net/url"
|
||||
@ -15,24 +16,25 @@ func init() {
|
||||
}
|
||||
|
||||
type HTTP struct {
|
||||
Name string `json:"name"`
|
||||
Server string `json:"server"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
SNI string `json:"sni"`
|
||||
Protocol string `json:"protocol"`
|
||||
Name string `json:"name"`
|
||||
Server string `json:"server"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
SNI string `json:"sni"`
|
||||
Protocol string `json:"protocol"`
|
||||
AllowInsecure bool `json:"allowInsecure"`
|
||||
}
|
||||
|
||||
func NewHTTP(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseHTTPURL(link)
|
||||
s, err := ParseHTTPURL(link, option)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
}
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
func ParseHTTPURL(link string, option *dialer.GlobalOption) (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)
|
||||
@ -51,13 +53,14 @@ func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
return nil, fmt.Errorf("error when parsing port: %w", err)
|
||||
}
|
||||
return &HTTP{
|
||||
Name: u.Fragment,
|
||||
Server: u.Hostname(),
|
||||
Port: port,
|
||||
Username: u.User.Username(),
|
||||
Password: pwd,
|
||||
SNI: u.Query().Get("sni"),
|
||||
Protocol: u.Scheme,
|
||||
Name: u.Fragment,
|
||||
Server: u.Hostname(),
|
||||
Port: port,
|
||||
Username: u.User.Username(),
|
||||
Password: pwd,
|
||||
SNI: u.Query().Get("sni"),
|
||||
Protocol: u.Scheme,
|
||||
AllowInsecure: option.AllowInsecure,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -67,7 +70,7 @@ func (s *HTTP) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, s.Name, s.Protocol, u.String()), nil
|
||||
return dialer.NewDialer(d, option, iOption, s.Name, s.Protocol, u.String()), nil
|
||||
}
|
||||
|
||||
func (s *HTTP) URL() url.URL {
|
||||
@ -77,7 +80,7 @@ func (s *HTTP) URL() url.URL {
|
||||
Fragment: s.Name,
|
||||
}
|
||||
if s.SNI != "" {
|
||||
u.RawQuery = url.Values{"sni": []string{s.SNI}}.Encode()
|
||||
u.RawQuery = url.Values{"sni": []string{s.SNI}, "allowInsecure": []string{common.BoolToString(s.AllowInsecure)}}.Encode()
|
||||
}
|
||||
if s.Username != "" {
|
||||
if s.Password != "" {
|
||||
|
@ -35,7 +35,7 @@ type Trojan struct {
|
||||
}
|
||||
|
||||
func NewTrojan(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseTrojanURL(link)
|
||||
s, err := ParseTrojanURL(link, option)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -48,7 +48,8 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
Scheme: "tls",
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{s.Sni},
|
||||
"sni": []string{s.Sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
}.Encode(),
|
||||
}
|
||||
var err error
|
||||
@ -65,8 +66,8 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
Scheme: "ws",
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"host": []string{s.Host},
|
||||
"path": []string{s.Path},
|
||||
"host": []string{s.Host},
|
||||
"path": []string{s.Path},
|
||||
}.Encode(),
|
||||
}
|
||||
if d, err = ws.NewWs(u.String(), d); err != nil {
|
||||
@ -78,9 +79,10 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
serviceName = "GunService"
|
||||
}
|
||||
d = &grpc.Dialer{
|
||||
NextDialer: &protocol.DialerConverter{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: s.Sni,
|
||||
NextDialer: &protocol.DialerConverter{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: s.Sni,
|
||||
AllowInsecure: s.AllowInsecure,
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(s.Encryption, "ss;") {
|
||||
@ -101,17 +103,20 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
func ParseTrojanURL(u string, option *dialer.GlobalOption) (data *Trojan, err error) {
|
||||
//trojan://password@server:port#escape(remarks)
|
||||
t, err := url.Parse(u)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid trojan format")
|
||||
return
|
||||
}
|
||||
allowInsecure := t.Query().Get("allowInsecure")
|
||||
allowInsecure, _ := strconv.ParseBool(t.Query().Get("allowInsecure"))
|
||||
if !allowInsecure && option.AllowInsecure {
|
||||
allowInsecure = true
|
||||
}
|
||||
sni := t.Query().Get("peer")
|
||||
if sni == "" {
|
||||
sni = t.Query().Get("sni")
|
||||
@ -129,7 +134,7 @@ func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
Port: port,
|
||||
Password: t.User.Username(),
|
||||
Sni: sni,
|
||||
AllowInsecure: allowInsecure == "1" || allowInsecure == "true",
|
||||
AllowInsecure: allowInsecure,
|
||||
Protocol: "trojan",
|
||||
}
|
||||
if t.Query().Get("type") != "" {
|
||||
@ -145,7 +150,6 @@ func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
if data.Type == "grpc" && data.ServiceName == "" {
|
||||
data.ServiceName = data.Path
|
||||
}
|
||||
data.AllowInsecure = false
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func NewV2Ray(option *dialer.GlobalOption, iOption dialer.InstanceOption, link s
|
||||
)
|
||||
switch {
|
||||
case strings.HasPrefix(link, "vmess://"):
|
||||
s, err = ParseVmessURL(link)
|
||||
s, err = ParseVmessURL(link, option)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -56,7 +56,7 @@ func NewV2Ray(option *dialer.GlobalOption, iOption dialer.InstanceOption, link s
|
||||
return nil, fmt.Errorf("%w: aid: %v, we only support AEAD encryption", dialer.UnexpectedFieldErr, s.Aid)
|
||||
}
|
||||
case strings.HasPrefix(link, "vless://"):
|
||||
s, err = ParseVlessURL(link)
|
||||
s, err = ParseVlessURL(link, option)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -92,8 +92,9 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
Host: net.JoinHostPort(s.Add, s.Port),
|
||||
Path: s.Path,
|
||||
RawQuery: url.Values{
|
||||
"host": []string{s.Host},
|
||||
"sni": []string{sni},
|
||||
"host": []string{s.Host},
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = ws.NewWs(u.String(), d)
|
||||
@ -110,7 +111,8 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
Scheme: "tls",
|
||||
Host: net.JoinHostPort(s.Add, s.Port),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{sni},
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = tls.NewTls(u.String(), d)
|
||||
@ -131,9 +133,10 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
serviceName = "GunService"
|
||||
}
|
||||
d = &grpc.Dialer{
|
||||
NextDialer: &protocol.DialerConverter{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: sni,
|
||||
NextDialer: &protocol.DialerConverter{Dialer: d},
|
||||
ServiceName: serviceName,
|
||||
ServerName: sni,
|
||||
AllowInsecure: s.AllowInsecure,
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: network: %v", dialer.UnexpectedFieldErr, s.Net)
|
||||
@ -147,10 +150,10 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, iOption, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseVlessURL(vless string) (data *V2Ray, err error) {
|
||||
func ParseVlessURL(vless string, option *dialer.GlobalOption) (data *V2Ray, err error) {
|
||||
u, err := url.Parse(vless)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -188,10 +191,13 @@ func ParseVlessURL(vless string) (data *V2Ray, err error) {
|
||||
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) (data *V2Ray, err error) {
|
||||
func ParseVmessURL(vmess string, option *dialer.GlobalOption) (data *V2Ray, err error) {
|
||||
var info V2Ray
|
||||
// perform base64 decoding and unmarshal to VmessInfo
|
||||
raw, err := common.Base64StdDecode(vmess[8:])
|
||||
@ -265,6 +271,9 @@ func ParseVmessURL(vmess string) (data *V2Ray, err error) {
|
||||
info.Aid = "0"
|
||||
}
|
||||
info.Protocol = "vmess"
|
||||
if option.AllowInsecure {
|
||||
info.AllowInsecure = true
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Ws is a base Ws struct
|
||||
@ -40,18 +41,17 @@ func NewWs(s string, d proxy.Dialer) (*Ws, error) {
|
||||
wsUrl := url.URL{
|
||||
Scheme: u.Scheme,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
}
|
||||
t.wsAddr = wsUrl.String()
|
||||
t.wsAddr = wsUrl.String() + u.Path
|
||||
t.wsDialer = &websocket.Dialer{
|
||||
NetDial: d.Dial,
|
||||
NetDial: d.Dial,
|
||||
//Subprotocols: []string{"binary"},
|
||||
}
|
||||
if u.Scheme == "wss" {
|
||||
if u.Query().Get("sni") != "" {
|
||||
t.wsDialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: u.Query().Get("sni"),
|
||||
}
|
||||
skipVerify, _ := strconv.ParseBool(u.Query().Get("allowInsecure"))
|
||||
t.wsDialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: u.Query().Get("sni"),
|
||||
InsecureSkipVerify: skipVerify,
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
|
@ -18,10 +18,7 @@ type Global struct {
|
||||
LogLevel string `mapstructure:"log_level" default:"info"`
|
||||
// We use DirectTcpCheckUrl to check (tcp)*(ipv4/ipv6) connectivity for direct.
|
||||
//DirectTcpCheckUrl string `mapstructure:"direct_tcp_check_url" default:"http://www.qualcomm.cn/generate_204"`
|
||||
// We use TcpCheckUrl to check (tcp)*(ipv4/ipv6) connectivity for non-direct and non-DNS packets.
|
||||
TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://cp.cloudflare.com"`
|
||||
// We use UdpCheckDns to check (tcp/udp)*(ipv4/ipv6) connectivity for DNS packets,
|
||||
// and udp*(ipv4/ipv6) connectivity for all other types of packets.
|
||||
TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://cp.cloudflare.com"`
|
||||
UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"`
|
||||
CheckInterval time.Duration `mapstructure:"check_interval" default:"30s"`
|
||||
CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"`
|
||||
@ -29,6 +26,7 @@ type Global struct {
|
||||
LanInterface []string `mapstructure:"lan_interface"`
|
||||
LanNatDirect bool `mapstructure:"lan_nat_direct" required:""`
|
||||
WanInterface []string `mapstructure:"wan_interface"`
|
||||
AllowInsecure bool `mapstructure:"allow_insecure" default:"false"`
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
|
@ -200,6 +200,9 @@ func NewControlPlane(
|
||||
checkDnsTcp = true
|
||||
}
|
||||
}
|
||||
if global.AllowInsecure {
|
||||
log.Warnln("AllowInsecure is enabled, but it is not recommended. Please make sure you have to turn it on.")
|
||||
}
|
||||
option := &dialer.GlobalOption{
|
||||
Log: log,
|
||||
TcpCheckOptionRaw: dialer.TcpCheckOptionRaw{Raw: global.TcpCheckUrl},
|
||||
@ -207,6 +210,7 @@ func NewControlPlane(
|
||||
CheckInterval: global.CheckInterval,
|
||||
CheckTolerance: global.CheckTolerance,
|
||||
CheckDnsTcp: checkDnsTcp,
|
||||
AllowInsecure: global.AllowInsecure,
|
||||
}
|
||||
outbounds := []*outbound.DialerGroup{
|
||||
outbound.NewDialerGroup(option, consts.OutboundDirect.String(),
|
||||
|
@ -42,6 +42,9 @@ global {
|
||||
# The WAN interface to bind. Use it if you want to proxy localhost.
|
||||
# Multiple interfaces split by ",".
|
||||
wan_interface: wlp5s0
|
||||
|
||||
# Allow insecure TLS certificates. It is not recommended to turn it on unless you have to.
|
||||
allow_insecure: false
|
||||
}
|
||||
|
||||
# Subscriptions defined here will be resolved as nodes and merged as a part of the global node pool.
|
||||
|
2
go.mod
2
go.mod
@ -9,7 +9,7 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/mzz2017/softwind v0.0.0-20230212082815-dee826918b06
|
||||
github.com/mzz2017/softwind v0.0.0-20230212090240-561c250bc5c4
|
||||
github.com/safchain/ethtool v0.0.0-20230116090318-67cc41908669
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
|
4
go.sum
4
go.sum
@ -69,8 +69,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mzz2017/disk-bloom v1.0.1 h1:rEF9MiXd9qMW3ibRpqcerLXULoTgRlM21yqqJl1B90M=
|
||||
github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI=
|
||||
github.com/mzz2017/softwind v0.0.0-20230212082815-dee826918b06 h1:cdXO7ciiP2ubeayuHQIWEK3eai/bNW4dAbNgyu8C558=
|
||||
github.com/mzz2017/softwind v0.0.0-20230212082815-dee826918b06/go.mod h1:K1nXwtBokwEsfOfdT/5zV6R8QabGkyhcR0iuTrRZcYY=
|
||||
github.com/mzz2017/softwind v0.0.0-20230212090240-561c250bc5c4 h1:f7nqFcMs8LaM/eLRHGeuMk/urv/U+AMNKjFylwowlwU=
|
||||
github.com/mzz2017/softwind v0.0.0-20230212090240-561c250bc5c4/go.mod h1:K1nXwtBokwEsfOfdT/5zV6R8QabGkyhcR0iuTrRZcYY=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
|
Loading…
Reference in New Issue
Block a user