Merge from remote branch

This commit is contained in:
yaling888
2021-10-28 11:36:11 +08:00
86 changed files with 1065 additions and 461 deletions

View File

@ -36,12 +36,24 @@ func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) {
// DialContext implements C.ProxyAdapter
func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
conn, err := p.ProxyAdapter.DialContext(ctx, metadata)
if err != nil {
p.alive.Store(false)
}
p.alive.Store(err == nil)
return conn, err
}
// DialUDP implements C.ProxyAdapter
func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout)
defer cancel()
return p.ListenPacketContext(ctx, metadata)
}
// ListenPacketContext implements C.ProxyAdapter
func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata)
p.alive.Store(err == nil)
return pc, err
}
// DelayHistory implements C.Proxy
func (p *Proxy) DelayHistory() []C.DelayHistory {
queue := p.history.Copy()

View File

@ -1,6 +1,7 @@
package outbound
import (
"context"
"encoding/json"
"errors"
"net"
@ -30,8 +31,8 @@ func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
return c, errors.New("no support")
}
// DialUDP implements C.ProxyAdapter
func (b *Base) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
// ListenPacketContext implements C.ProxyAdapter
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
return nil, errors.New("no support")
}

View File

@ -22,9 +22,9 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
return NewConn(c, d), nil
}
// DialUDP implements C.ProxyAdapter
func (d *Direct) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
// ListenPacketContext implements C.ProxyAdapter
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(ctx, "udp", "")
if err != nil {
return nil, err
}

View File

@ -19,8 +19,8 @@ func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
return NewConn(&NopConn{}, r), nil
}
// DialUDP implements C.ProxyAdapter
func (r *Reject) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
// ListenPacketContext implements C.ProxyAdapter
func (r *Reject) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
return nil, errors.New("match reject rule")
}

View File

@ -87,9 +87,9 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_
return NewConn(c, ss), err
}
// DialUDP implements C.ProxyAdapter
func (ss *ShadowSocks) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
// ListenPacketContext implements C.ProxyAdapter
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(ctx, "udp", "")
if err != nil {
return nil, err
}

View File

@ -72,9 +72,9 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata)
return NewConn(c, ssr), err
}
// DialUDP implements C.ProxyAdapter
func (ssr *ShadowSocksR) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
// ListenPacketContext implements C.ProxyAdapter
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := dialer.ListenPacket(ctx, "udp", "")
if err != nil {
return nil, err
}

View File

@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"strconv"
@ -77,10 +76,8 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Co
return NewConn(c, ss), nil
}
// DialUDP implements C.ProxyAdapter
func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
defer cancel()
// ListenPacketContext implements C.ProxyAdapter
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
if err != nil {
err = fmt.Errorf("%s connect error: %w", ss.addr, err)
@ -110,13 +107,13 @@ func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
return
}
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
pc, err := dialer.ListenPacket(ctx, "udp", "")
if err != nil {
return
}
go func() {
io.Copy(ioutil.Discard, c)
io.Copy(io.Discard, c)
c.Close()
// A UDP association terminates when the TCP connection that the UDP
// ASSOCIATE request arrived on terminates. RFC1928

View File

@ -5,6 +5,7 @@ import (
"crypto/tls"
"fmt"
"net"
"net/http"
"strconv"
"github.com/Dreamacro/clash/component/dialer"
@ -18,6 +19,7 @@ import (
type Trojan struct {
*Base
instance *trojan.Trojan
option *TrojanOption
// for gun mux
gunTLSConfig *tls.Config
@ -36,6 +38,34 @@ type TrojanOption struct {
UDP bool `proxy:"udp,omitempty"`
Network string `proxy:"network,omitempty"`
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
}
func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) {
if t.option.Network == "ws" {
host, port, _ := net.SplitHostPort(t.addr)
wsOpts := &trojan.WebsocketOption{
Host: host,
Port: port,
Path: t.option.WSOpts.Path,
}
if t.option.SNI != "" {
wsOpts.Host = t.option.SNI
}
if len(t.option.WSOpts.Headers) != 0 {
header := http.Header{}
for key, value := range t.option.WSOpts.Headers {
header.Add(key, value)
}
wsOpts.Headers = header
}
return t.instance.StreamWebsocketConn(c, wsOpts)
}
return t.instance.StreamConn(c)
}
// StreamConn implements C.ProxyAdapter
@ -44,7 +74,7 @@ func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
if t.transport != nil {
c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig)
} else {
c, err = t.instance.StreamConn(c)
c, err = t.plainStream(c)
}
if err != nil {
@ -88,8 +118,8 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con
return NewConn(c, t), err
}
// DialUDP implements C.ProxyAdapter
func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
// ListenPacketContext implements C.ProxyAdapter
func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
var c net.Conn
// grpc transport
@ -100,15 +130,13 @@ func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
}
defer safeConnClose(c, err)
} else {
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
defer cancel()
c, err = dialer.DialContext(ctx, "tcp", t.addr)
if err != nil {
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
}
defer safeConnClose(c, err)
tcpKeepAlive(c)
c, err = t.instance.StreamConn(c)
c, err = t.plainStream(c)
if err != nil {
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
}
@ -145,6 +173,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
udp: option.UDP,
},
instance: trojan.New(tOption),
option: &option,
}
if option.Network == "grpc" {

View File

@ -79,8 +79,16 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
if v.option.TLS {
wsOpts.TLS = true
wsOpts.SkipCertVerify = v.option.SkipCertVerify
wsOpts.ServerName = v.option.ServerName
wsOpts.TLSConfig = &tls.Config{
ServerName: host,
InsecureSkipVerify: v.option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
}
if v.option.ServerName != "" {
wsOpts.TLSConfig.ServerName = v.option.ServerName
} else if host := wsOpts.Headers.Get("Host"); host != "" {
wsOpts.TLSConfig.ServerName = host
}
}
c, err = vmess.StreamWebsocketConn(c, wsOpts)
case "http":

View File

@ -31,23 +31,25 @@ type Vmess struct {
}
type VmessOption struct {
Name string `proxy:"name"`
Server string `proxy:"server"`
Port int `proxy:"port"`
UUID string `proxy:"uuid"`
AlterID int `proxy:"alterId"`
Cipher string `proxy:"cipher"`
TLS bool `proxy:"tls,omitempty"`
UDP bool `proxy:"udp,omitempty"`
Network string `proxy:"network,omitempty"`
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
WSPath string `proxy:"ws-path,omitempty"`
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
ServerName string `proxy:"servername,omitempty"`
Name string `proxy:"name"`
Server string `proxy:"server"`
Port int `proxy:"port"`
UUID string `proxy:"uuid"`
AlterID int `proxy:"alterId"`
Cipher string `proxy:"cipher"`
UDP bool `proxy:"udp,omitempty"`
Network string `proxy:"network,omitempty"`
TLS bool `proxy:"tls,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
ServerName string `proxy:"servername,omitempty"`
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
// TODO: remove these until 2022
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
WSPath string `proxy:"ws-path,omitempty"`
}
type HTTPOptions struct {
@ -103,8 +105,16 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
if v.option.TLS {
wsOpts.TLS = true
wsOpts.SkipCertVerify = v.option.SkipCertVerify
wsOpts.ServerName = v.option.ServerName
wsOpts.TLSConfig = &tls.Config{
ServerName: host,
InsecureSkipVerify: v.option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
}
if v.option.ServerName != "" {
wsOpts.TLSConfig.ServerName = v.option.ServerName
} else if host := wsOpts.Headers.Get("Host"); host != "" {
wsOpts.TLSConfig.ServerName = host
}
}
c, err = vmess.StreamWebsocketConn(c, wsOpts)
case "http":
@ -213,8 +223,8 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
return NewConn(c, v), err
}
// DialUDP implements C.ProxyAdapter
func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
// ListenPacketContext implements C.ProxyAdapter
func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
if !metadata.Resolved() {
ip, err := resolver.ResolveIP(metadata.Host)
@ -235,8 +245,6 @@ func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
} else {
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
defer cancel()
c, err = dialer.DialContext(ctx, "tcp", v.addr)
if err != nil {
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())

View File

@ -32,10 +32,10 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
return c, err
}
// DialUDP implements C.ProxyAdapter
func (f *Fallback) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
// ListenPacketContext implements C.ProxyAdapter
func (f *Fallback) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
proxy := f.findAliveProxy(true)
pc, err := proxy.DialUDP(metadata)
pc, err := proxy.ListenPacketContext(ctx, metadata)
if err == nil {
pc.AppendToChains(f)
}

View File

@ -82,8 +82,8 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c
return
}
// DialUDP implements C.ProxyAdapter
func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error) {
// ListenPacketContext implements C.ProxyAdapter
func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (pc C.PacketConn, err error) {
defer func() {
if err == nil {
pc.AppendToChains(lb)
@ -91,8 +91,7 @@ func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error
}()
proxy := lb.Unwrap(metadata)
return proxy.DialUDP(metadata)
return proxy.ListenPacketContext(ctx, metadata)
}
// SupportUDP implements C.ProxyAdapter

View File

@ -28,9 +28,9 @@ func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
return c, err
}
// DialUDP implements C.ProxyAdapter
func (s *Selector) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
pc, err := s.selectedProxy(true).DialUDP(metadata)
// ListenPacketContext implements C.ProxyAdapter
func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata)
if err == nil {
pc.AppendToChains(s)
}

View File

@ -42,9 +42,9 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Co
return c, err
}
// DialUDP implements C.ProxyAdapter
func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
pc, err := u.fast(true).DialUDP(metadata)
// ListenPacketContext implements C.ProxyAdapter
func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
pc, err := u.fast(true).ListenPacketContext(ctx, metadata)
if err == nil {
pc.AppendToChains(u)
}

View File

@ -3,7 +3,6 @@ package provider
import (
"bytes"
"crypto/md5"
"io/ioutil"
"os"
"path/filepath"
"time"
@ -13,8 +12,8 @@ import (
)
var (
fileMode os.FileMode = 0666
dirMode os.FileMode = 0755
fileMode os.FileMode = 0o666
dirMode os.FileMode = 0o755
)
type parser = func([]byte) (interface{}, error)
@ -45,7 +44,7 @@ func (f *fetcher) Initial() (interface{}, error) {
isLocal bool
)
if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil {
buf, err = ioutil.ReadFile(f.vehicle.Path())
buf, err = os.ReadFile(f.vehicle.Path())
modTime := stat.ModTime()
f.updatedAt = &modTime
isLocal = true
@ -165,7 +164,7 @@ func safeWrite(path string, buf []byte) error {
}
}
return ioutil.WriteFile(path, buf, fileMode)
return os.WriteFile(path, buf, fileMode)
}
func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher {

View File

@ -10,9 +10,7 @@ import (
types "github.com/Dreamacro/clash/constant/provider"
)
var (
errVehicleType = errors.New("unsupport vehicle type")
)
var errVehicleType = errors.New("unsupport vehicle type")
type healthCheckSchema struct {
Enable bool `provider:"enable"`

View File

@ -2,10 +2,11 @@ package provider
import (
"context"
"io/ioutil"
"io"
"net"
"net/http"
"net/url"
"os"
"time"
"github.com/Dreamacro/clash/component/dialer"
@ -25,7 +26,7 @@ func (f *FileVehicle) Path() string {
}
func (f *FileVehicle) Read() ([]byte, error) {
return ioutil.ReadFile(f.path)
return os.ReadFile(f.path)
}
func NewFileVehicle(path string) *FileVehicle {
@ -84,7 +85,7 @@ func (h *HTTPVehicle) Read() ([]byte, error) {
}
defer resp.Body.Close()
buf, err := ioutil.ReadAll(resp.Body)
buf, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}