diff --git a/README.md b/README.md index ad6b117..f7ec473 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,7 @@ glider -config CONFIGPATH -listen :8080 -verbose ## Customize Build -You can customize and build glider by yourself if you want a smaller binary. +You can customize and build glider if you want a smaller binary. 1. Clone the source code: ```bash @@ -385,8 +385,8 @@ You can customize and build glider by yourself if you want a smaller binary. ``` 2. Customize features: - ```open `feature.go` & `feature_linux.go`, comment out the packages you don't need``` ```bash + open `feature.go` & `feature_linux.go`, comment out the packages you don't need // _ "github.com/nadoo/glider/proxy/kcp" ``` diff --git a/go.mod b/go.mod index 3856c88..0106610 100644 --- a/go.mod +++ b/go.mod @@ -10,10 +10,10 @@ require ( github.com/nadoo/ipset v0.3.0 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/xtaci/kcp-go/v5 v5.5.17 - golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae + golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977 golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect - golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c // indirect + golang.org/x/tools v0.0.0-20201002055958-0d28ed0cbe40 // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index b010fc2..577158a 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,8 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae h1:duLSQW+DZ5MsXKX7kc4rXlq6/mmxz4G6ewJuBPlhRe0= -golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977 h1:yH6opeNE+0SY+7pXT4gclZUoKHogXeC2EvOSHGOMGPU= +golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= @@ -173,8 +173,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c h1:9BSeO6440XJVa2mxIcRAndAol4g4g2KflCVGcHx9Yu8= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201002055958-0d28ed0cbe40 h1:ErPN1Z9An7dXc56pRUCKgWJkjYzc3hE+y15ky9E8qxU= +golang.org/x/tools v0.0.0-20201002055958-0d28ed0cbe40/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/proxy/ss/ss.go b/proxy/ss/ss.go index 5a53efa..193e09b 100644 --- a/proxy/ss/ss.go +++ b/proxy/ss/ss.go @@ -172,14 +172,14 @@ func (s *SS) Serve(c net.Conn) { func (s *SS) ListenAndServeUDP() { lc, err := net.ListenPacket("udp", s.addr) if err != nil { - log.F("[ss-udp] failed to listen on %s: %v", s.addr, err) + log.F("[ssu] failed to listen on %s: %v", s.addr, err) return } defer lc.Close() lc = s.PacketConn(lc) - log.F("[ss-udp] listening UDP on %s", s.addr) + log.F("[ssu] listening UDP on %s", s.addr) var nm sync.Map buf := make([]byte, proxy.UDPBufSize) @@ -189,7 +189,7 @@ func (s *SS) ListenAndServeUDP() { n, raddr, err := c.ReadFrom(buf) if err != nil { - log.F("[ss-udp] remote read error: %v", err) + log.F("[ssu] remote read error: %v", err) continue } @@ -198,7 +198,7 @@ func (s *SS) ListenAndServeUDP() { if !ok && v == nil { lpc, nextHop, err := s.proxy.DialUDP("udp", c.tgtAddr.String()) if err != nil { - log.F("[ss-udp] remote dial error: %v", err) + log.F("[ssu] remote dial error: %v", err) continue } @@ -211,7 +211,7 @@ func (s *SS) ListenAndServeUDP() { nm.Delete(raddr.String()) }() - log.F("[ss-udp] %s <-> %s", raddr, c.tgtAddr) + log.F("[ssu] %s <-> %s", raddr, c.tgtAddr) } else { pc = v.(*PktConn) @@ -219,11 +219,11 @@ func (s *SS) ListenAndServeUDP() { _, err = pc.WriteTo(buf[:n], pc.writeAddr) if err != nil { - log.F("[ss-udp] remote write error: %v", err) + log.F("[ssu] remote write error: %v", err) continue } - // log.F("[ss-udp] %s <-> %s", raddr, c.tgtAddr) + // log.F("[ssu] %s <-> %s", raddr, c.tgtAddr) } } diff --git a/proxy/trojan/packet.go b/proxy/trojan/packet.go index 309623d..5bf5910 100644 --- a/proxy/trojan/packet.go +++ b/proxy/trojan/packet.go @@ -28,6 +28,7 @@ func NewPktConn(c net.Conn, tgtAddr socks.Addr) *PktConn { } // ReadFrom implements the necessary function of net.PacketConn. +// TODO: we know that we use it in proxy.RelayUDP and the length of b is enough, check it later. func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { // ATYP, DST.ADDR, DST.PORT _, err := socks.ReadAddr(pc.Conn) @@ -50,6 +51,10 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { return 0, nil, err } + if len(b) < length { + return 0, nil, errors.New("buf size is not enough") + } + // Payload n, err := io.ReadFull(pc.Conn, b[:length]) if err != nil { @@ -69,5 +74,6 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { binary.Write(buf, binary.BigEndian, uint16(len(b))) buf.WriteString("\r\n") buf.Write(b) + return pc.Write(buf.Bytes()) } diff --git a/proxy/vless/client.go b/proxy/vless/client.go index e4233a3..6775fda 100644 --- a/proxy/vless/client.go +++ b/proxy/vless/client.go @@ -27,8 +27,8 @@ type Conn struct { rcved bool } -// NewConn returns a new vless client conn. -func NewConn(c net.Conn, uuid [16]byte, target string) (*Conn, error) { +// ClientConn returns a new vless client conn. +func ClientConn(c net.Conn, uuid [16]byte, network, target string) (*Conn, error) { atyp, addr, port, err := ParseAddr(target) if err != nil { return nil, err @@ -40,7 +40,12 @@ func NewConn(c net.Conn, uuid [16]byte, target string) (*Conn, error) { buf.WriteByte(Version) // ver buf.Write(uuid[:]) // uuid buf.WriteByte(0) // addLen - buf.WriteByte(CmdTCP) // cmd + + cmd := CmdTCP + if network == "udp" { + cmd = CmdUDP + } + buf.WriteByte(cmd) // cmd // target err = binary.Write(buf, binary.BigEndian, uint16(port)) // port diff --git a/proxy/vless/packet.go b/proxy/vless/packet.go new file mode 100644 index 0000000..c649f61 --- /dev/null +++ b/proxy/vless/packet.go @@ -0,0 +1,53 @@ +package vless + +import ( + "encoding/binary" + "errors" + "io" + "net" + + "github.com/nadoo/glider/pool" +) + +// PktConn . +type PktConn struct { + net.Conn +} + +// NewPktConn returns a PktConn. +func NewPktConn(c net.Conn) *PktConn { + return &PktConn{Conn: c} +} + +// ReadFrom implements the necessary function of net.PacketConn. +// TODO: we know that we use it in proxy.RelayUDP and the length of b is enough, check it later. +func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { + // Length + if _, err := io.ReadFull(pc.Conn, b[:2]); err != nil { + return 0, nil, err + } + length := int(binary.BigEndian.Uint16(b[:2])) + + if len(b) < length { + return 0, nil, errors.New("buf size is not enough") + } + + // Payload + n, err := io.ReadFull(pc.Conn, b[:length]) + if err != nil { + return 0, nil, err + } + + return n, nil, nil +} + +// WriteTo implements the necessary function of net.PacketConn. +func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { + buf := pool.GetWriteBuffer() + defer pool.PutWriteBuffer(buf) + + binary.Write(buf, binary.BigEndian, uint16(len(b))) + buf.Write(b) + + return pc.Write(buf.Bytes()) +} diff --git a/proxy/vless/vless.go b/proxy/vless/vless.go index 972eb95..6c18a96 100644 --- a/proxy/vless/vless.go +++ b/proxy/vless/vless.go @@ -1,7 +1,6 @@ package vless import ( - "errors" "net" "net/url" @@ -60,10 +59,15 @@ func (s *VLess) Dial(network, addr string) (net.Conn, error) { if err != nil { return nil, err } - return NewConn(rc, s.uuid, addr) + return ClientConn(rc, s.uuid, network, addr) } // DialUDP connects to the given address via the proxy. func (s *VLess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { - return nil, nil, errors.New("vless client does not support udp now") + c, err := s.Dial("udp", addr) + if err != nil { + return nil, nil, err + } + pkc := NewPktConn(c) + return pkc, nil, nil } diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index e4a4e23..cc48e56 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -14,8 +14,9 @@ import ( "strings" "time" - "github.com/nadoo/glider/pool" "golang.org/x/crypto/chacha20poly1305" + + "github.com/nadoo/glider/pool" ) // Request Options diff --git a/rule/group.go b/rule/group.go index c2dcbd7..c8bbad4 100644 --- a/rule/group.go +++ b/rule/group.go @@ -226,9 +226,8 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf [] rc, err := fwdr.Dial("tcp", website) if err != nil { + log.F("[check] %s(%d) -> %s, FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(), website, err) fwdr.Disable() - log.F("[check] %s(%d) -> %s, FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(), - website, err) return false } defer rc.Close() @@ -239,24 +238,21 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf [] _, err = io.WriteString(rc, "GET / HTTP/1.0\r\n\r\n") if err != nil { + log.F("[check] %s(%d) -> %s, FAILED. error in write: %s", fwdr.Addr(), fwdr.Priority(), website, err) fwdr.Disable() - log.F("[check] %s(%d) -> %s, FAILED. error in write: %s", fwdr.Addr(), fwdr.Priority(), - website, err) return false } _, err = io.ReadFull(rc, buf) if err != nil { + log.F("[check] %s(%d) -> %s, FAILED. error in read: %s", fwdr.Addr(), fwdr.Priority(), website, err) fwdr.Disable() - log.F("[check] %s(%d) -> %s, FAILED. error in read: %s", fwdr.Addr(), fwdr.Priority(), - website, err) return false } if !bytes.Equal([]byte("HTTP"), buf) { + log.F("[check] %s(%d) -> %s, FAILED. server response: %s", fwdr.Addr(), fwdr.Priority(), website, buf) fwdr.Disable() - log.F("[check] %s(%d) -> %s, FAILED. server response: %s", fwdr.Addr(), fwdr.Priority(), - website, buf) return false } @@ -264,15 +260,13 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf [] fwdr.SetLatency(int64(readTime)) if readTime > timeout { + log.F("[check] %s(%d) -> %s, FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(), website, readTime) fwdr.Disable() - log.F("[check] %s(%d) -> %s, FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(), - website, readTime) return false } + log.F("[check] %s(%d) -> %s, SUCCESS. elapsed time: %s", fwdr.Addr(), fwdr.Priority(), website, readTime) fwdr.Enable() - log.F("[check] %s(%d) -> %s, SUCCESS. connect time: %s", fwdr.Addr(), fwdr.Priority(), - website, readTime) return true }