mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
vless: added udp support
This commit is contained in:
parent
bc68535dcd
commit
b323a62ce6
@ -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"
|
||||
```
|
||||
|
||||
|
4
go.mod
4
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
|
||||
)
|
||||
|
||||
|
8
go.sum
8
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=
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
|
53
proxy/vless/packet.go
Normal file
53
proxy/vless/packet.go
Normal file
@ -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())
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -14,8 +14,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nadoo/glider/pool"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
"github.com/nadoo/glider/pool"
|
||||
)
|
||||
|
||||
// Request Options
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user