mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
udp: remove uottun and optimize udp implementation
This commit is contained in:
parent
78e03d7fbf
commit
d510ea45b0
@ -63,7 +63,6 @@ we can set up local listeners as proxy servers, and forward requests to internet
|
||||
|simple-obfs | | |√| |transport client only
|
||||
|tcptun |√| | | |transport server only
|
||||
|udptun | |√| | |transport server only
|
||||
|uottun | |√| | |transport server only
|
||||
|redir |√| | | |linux only
|
||||
|redir6 |√| | | |linux only(ipv6)
|
||||
|reject | | |√|√|reject all requests
|
||||
@ -144,7 +143,7 @@ glider 0.12.0 usage:
|
||||
verbose mode
|
||||
|
||||
Available schemes:
|
||||
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcptun udptun uottun tls unix kcp
|
||||
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcptun udptun tls unix kcp
|
||||
forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tls ws unix kcp simple-obfs
|
||||
|
||||
Socks5 scheme:
|
||||
@ -299,9 +298,6 @@ Examples:
|
||||
./glider -listen udptun://:53=8.8.8.8:53 -forward ss://method:pass@1.1.1.1:8443
|
||||
-listen on :53 and forward all udp requests to 8.8.8.8:53 via remote ss server.
|
||||
|
||||
./glider -listen uottun://:53=8.8.8.8:53 -forward ss://method:pass@1.1.1.1:8443
|
||||
-listen on :53 and forward all udp requests via udp over tcp tunnel.
|
||||
|
||||
./glider -listen socks5://:1080 -listen http://:8080 -forward ss://method:pass@1.1.1.1:8443
|
||||
-listen on :1080 as socks5 server, :8080 as http proxy server, forward all requests via remote ss server.
|
||||
|
||||
|
@ -131,7 +131,7 @@ func usage() {
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
fmt.Fprintf(w, "Available schemes:\n")
|
||||
fmt.Fprintf(w, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcptun udptun uottun tls unix kcp\n")
|
||||
fmt.Fprintf(w, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcptun udptun tls unix kcp\n")
|
||||
fmt.Fprintf(w, " forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tls ws unix kcp simple-obfs\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
@ -313,9 +313,6 @@ func usage() {
|
||||
fmt.Fprintf(w, " "+app+" -listen udptun://:53=8.8.8.8:53 -forward ss://method:pass@1.1.1.1:8443\n")
|
||||
fmt.Fprintf(w, " -listen on :53 and forward all udp requests to 8.8.8.8:53 via remote ss server.\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, " "+app+" -listen uottun://:53=8.8.8.8:53 -forward ss://method:pass@1.1.1.1:8443\n")
|
||||
fmt.Fprintf(w, " -listen on :53 and forward all udp requests via udp over tcp tunnel.\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, " "+app+" -listen socks5://:1080 -listen http://:8080 -forward ss://method:pass@1.1.1.1:8443\n")
|
||||
fmt.Fprintf(w, " -listen on :1080 as socks5 server, :8080 as http proxy server, forward all requests via remote ss server.\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
@ -57,9 +57,6 @@ listen=socks5://:1080
|
||||
# listen on 1083 as a udp tunnel, all requests to :1083 will be forward to 1.1.1.1:53
|
||||
# listen=udptun://:1083=1.1.1.1:53
|
||||
|
||||
# listen on 1084 as a udp over tcp tunnel, all requests to :1084 will be forward to 1.1.1.1:53
|
||||
# listen=uottun://:1084=1.1.1.1:53
|
||||
|
||||
# http over tls (HTTPS proxy)
|
||||
# listen=tls://:443?cert=crtFilePath&key=keyFilePath,http://
|
||||
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
_ "github.com/nadoo/glider/proxy/tls"
|
||||
_ "github.com/nadoo/glider/proxy/trojan"
|
||||
_ "github.com/nadoo/glider/proxy/udptun"
|
||||
_ "github.com/nadoo/glider/proxy/uottun"
|
||||
_ "github.com/nadoo/glider/proxy/vless"
|
||||
_ "github.com/nadoo/glider/proxy/vmess"
|
||||
_ "github.com/nadoo/glider/proxy/ws"
|
||||
|
6
go.mod
6
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.6.1
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb // indirect
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 // indirect
|
||||
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 // indirect
|
||||
golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc // indirect
|
||||
golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
)
|
||||
|
||||
|
12
go.sum
12
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-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/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=
|
||||
@ -167,8 +167,8 @@ golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc h1:HVFDs9bKvTxP6bh1Rj9MCSo+UmafQtI8ZWDPVwVk9g4=
|
||||
golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -177,8 +177,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-20201011145850-ed2f50202694 h1:BANdcOVw3KTuUiyfDp7wrzCpkCe8UP3lowugJngxBTg=
|
||||
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752 h1:2ntEwh02rqo2jSsrYmp4yKHHjh0CbXP3ZtSUetSB+q8=
|
||||
golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752/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=
|
||||
|
@ -67,10 +67,6 @@ func (d *Direct) Dial(network, addr string) (c net.Conn, err error) {
|
||||
}
|
||||
|
||||
func (d *Direct) dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
||||
if network == "uot" {
|
||||
network = "udp"
|
||||
}
|
||||
|
||||
var la net.Addr
|
||||
switch network {
|
||||
case "tcp":
|
||||
|
@ -45,14 +45,14 @@ var Errors = []error{
|
||||
errors.New("socks5UDPAssociate"),
|
||||
}
|
||||
|
||||
// Addr .
|
||||
// Addr represents a SOCKS address as defined in RFC 1928 section 5.
|
||||
type Addr []byte
|
||||
|
||||
// String serializes SOCKS address a to string form.
|
||||
func (a Addr) String() string {
|
||||
var host, port string
|
||||
|
||||
switch ATYP(a[0]) { // address type
|
||||
switch a[0] { // address type
|
||||
case ATypDomain:
|
||||
host = string(a[2 : 2+int(a[1])])
|
||||
port = strconv.Itoa((int(a[2+int(a[1])]) << 8) | int(a[2+int(a[1])+1]))
|
||||
@ -67,16 +67,6 @@ func (a Addr) String() string {
|
||||
return net.JoinHostPort(host, port)
|
||||
}
|
||||
|
||||
// UoT returns whether it is udp over tcp
|
||||
func UoT(b byte) bool {
|
||||
return b&0x8 == 0x8
|
||||
}
|
||||
|
||||
// ATYP returns the address type
|
||||
func ATYP(b byte) int {
|
||||
return int(b &^ 0x8)
|
||||
}
|
||||
|
||||
// ReadAddrBuf reads just enough bytes from r to get a valid Addr.
|
||||
func ReadAddrBuf(r io.Reader, b []byte) (Addr, error) {
|
||||
if len(b) < MaxAddrLen {
|
||||
@ -87,7 +77,7 @@ func ReadAddrBuf(r io.Reader, b []byte) (Addr, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch ATYP(b[0]) {
|
||||
switch b[0] {
|
||||
case ATypDomain:
|
||||
_, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length
|
||||
if err != nil {
|
||||
@ -118,7 +108,7 @@ func SplitAddr(b []byte) Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch ATYP(b[0]) {
|
||||
switch b[0] {
|
||||
case ATypDomain:
|
||||
if len(b) < 2 {
|
||||
return nil
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"github.com/nadoo/glider/log"
|
||||
"github.com/nadoo/glider/pool"
|
||||
"github.com/nadoo/glider/proxy/socks"
|
||||
)
|
||||
@ -40,7 +39,7 @@ func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHea
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
continue
|
||||
}
|
||||
log.F("[socks5] dialudp udp associate end")
|
||||
// log.F("[socks5] dialudp udp associate end")
|
||||
return
|
||||
}
|
||||
}()
|
||||
@ -98,14 +97,19 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
return pc.PacketConn.WriteTo(b, addr)
|
||||
}
|
||||
|
||||
buf := pool.GetBuffer(3 + len(pc.tgtAddr) + len(b))
|
||||
defer pool.PutBuffer(buf)
|
||||
buf := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(buf)
|
||||
|
||||
copy(buf, []byte{0, 0, 0})
|
||||
copy(buf[3:], pc.tgtAddr)
|
||||
copy(buf[3+len(pc.tgtAddr):], b)
|
||||
buf.Write([]byte{0, 0, 0})
|
||||
tgtLen, _ := buf.Write(pc.tgtAddr)
|
||||
buf.Write(b)
|
||||
|
||||
return pc.PacketConn.WriteTo(buf, pc.writeAddr)
|
||||
n, err := pc.PacketConn.WriteTo(buf.Bytes(), pc.writeAddr)
|
||||
if n > tgtLen+3 {
|
||||
return n - tgtLen - 3, err
|
||||
}
|
||||
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Close .
|
||||
|
@ -139,7 +139,7 @@ func (s *Socks5) ListenAndServeUDP() {
|
||||
nm.Delete(raddr.String())
|
||||
}()
|
||||
|
||||
log.F("[socks5u] %s <-> %s", raddr, c.tgtAddr)
|
||||
log.F("[socks5u] %s <-> %s via %s", raddr, c.tgtAddr, nextHop)
|
||||
|
||||
} else {
|
||||
pc = v.(*PktConn)
|
||||
|
@ -29,10 +29,6 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) {
|
||||
return nil, errors.New("[ss] unable to parse address: " + addr)
|
||||
}
|
||||
|
||||
if network == "uot" {
|
||||
target[0] = target[0] | 0x8
|
||||
}
|
||||
|
||||
c, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
log.F("[ss] dial to %s error: %s", s.addr, err)
|
||||
|
@ -67,11 +67,16 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
return pc.PacketConn.WriteTo(b, addr)
|
||||
}
|
||||
|
||||
buf := pool.GetBuffer(len(pc.tgtAddr) + len(b))
|
||||
pool.PutBuffer(buf)
|
||||
buf := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(buf)
|
||||
|
||||
copy(buf, pc.tgtAddr)
|
||||
copy(buf[len(pc.tgtAddr):], b)
|
||||
tgtLen, _ := buf.Write(pc.tgtAddr)
|
||||
buf.Write(b)
|
||||
|
||||
return pc.PacketConn.WriteTo(buf, pc.writeAddr)
|
||||
n, err := pc.PacketConn.WriteTo(buf.Bytes(), pc.writeAddr)
|
||||
if n > tgtLen {
|
||||
return n - tgtLen, err
|
||||
}
|
||||
|
||||
return 0, err
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/nadoo/glider/log"
|
||||
"github.com/nadoo/glider/pool"
|
||||
"github.com/nadoo/glider/proxy"
|
||||
"github.com/nadoo/glider/proxy/socks"
|
||||
)
|
||||
@ -60,45 +59,8 @@ func (s *SS) Serve(c net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
dialer := s.proxy.NextDialer(tgt.String())
|
||||
|
||||
// udp over tcp?
|
||||
uot := socks.UoT(tgt[0])
|
||||
if uot && dialer.Addr() == "DIRECT" {
|
||||
rc, err := net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
log.F("[ss] UDP remote listen error: %v", err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
buf := pool.GetBuffer(proxy.UDPBufSize)
|
||||
defer pool.PutBuffer(buf)
|
||||
|
||||
n, err := c.Read(buf)
|
||||
if err != nil {
|
||||
log.F("[ss] error in read: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
tgtAddr, _ := net.ResolveUDPAddr("udp", tgt.String())
|
||||
rc.WriteTo(buf[:n], tgtAddr)
|
||||
|
||||
n, _, err = rc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[ss] read error: %v", err)
|
||||
}
|
||||
|
||||
c.Write(buf[:n])
|
||||
|
||||
log.F("[ss] %s <-tcp-> %s - %s <-udp-> %s ", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
network := "tcp"
|
||||
if uot {
|
||||
network = "udp"
|
||||
}
|
||||
dialer := s.proxy.NextDialer(tgt.String())
|
||||
|
||||
rc, err := dialer.Dial(network, tgt.String())
|
||||
if err != nil {
|
||||
@ -161,7 +123,7 @@ func (s *SS) ListenAndServeUDP() {
|
||||
nm.Delete(raddr.String())
|
||||
}()
|
||||
|
||||
log.F("[ssu] %s <-> %s", raddr, c.tgtAddr)
|
||||
log.F("[ssu] %s <-> %s via %s", raddr, c.tgtAddr, nextHop)
|
||||
|
||||
} else {
|
||||
pc = v.(*PktConn)
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/nadoo/glider/pool"
|
||||
"github.com/nadoo/glider/proxy"
|
||||
"github.com/nadoo/glider/proxy/socks"
|
||||
)
|
||||
|
||||
@ -36,14 +35,19 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
if len(b) < 2 {
|
||||
return 0, nil, errors.New("buf size is not enough")
|
||||
}
|
||||
|
||||
// Length
|
||||
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint16(b[:2]))
|
||||
if length > proxy.UDPBufSize {
|
||||
return 0, nil, errors.New("packet invalid")
|
||||
|
||||
if len(b) < length {
|
||||
return 0, nil, errors.New("buf size is not enough")
|
||||
}
|
||||
|
||||
// CRLF
|
||||
@ -51,10 +55,6 @@ 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 {
|
||||
@ -70,10 +70,15 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
buf := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(buf)
|
||||
|
||||
buf.Write(pc.tgtAddr)
|
||||
tgtLen, _ := buf.Write(pc.tgtAddr)
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(b)))
|
||||
buf.WriteString("\r\n")
|
||||
buf.Write(b)
|
||||
|
||||
return pc.Write(buf.Bytes())
|
||||
n, err := pc.Write(buf.Bytes())
|
||||
if n > tgtLen+4 {
|
||||
return n - tgtLen - 4, nil
|
||||
}
|
||||
|
||||
return 0, err
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ func (s *Trojan) readHeader(r io.Reader) (byte, socks.Addr, error) {
|
||||
func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
|
||||
rc, err := net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
log.F("[trojan] UDP remote listen error: %v", err)
|
||||
log.F("[trojan] UDP listen error: %v", err)
|
||||
return
|
||||
}
|
||||
defer rc.Close()
|
||||
@ -212,13 +212,11 @@ func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
|
||||
for {
|
||||
n, _, err := pc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[trojan] read error: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = rc.WriteTo(buf[:n], tgtAddr)
|
||||
if err != nil {
|
||||
log.F("[trojan] write rc error: %s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -232,14 +230,12 @@ func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
|
||||
for {
|
||||
n, _, err := rc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[trojan] read rc error: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
// WriteTo addr can be nil because the PktConn has it's own target, see packet.go
|
||||
_, err = pc.WriteTo(buf[:n], nil)
|
||||
if err != nil {
|
||||
log.F("[trojan] write pc error: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -1,114 +0,0 @@
|
||||
package uottun
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nadoo/glider/log"
|
||||
"github.com/nadoo/glider/proxy"
|
||||
)
|
||||
|
||||
// UoTTun is a base udp over tcp tunnel struct.
|
||||
type UoTTun struct {
|
||||
proxy proxy.Proxy
|
||||
addr string
|
||||
|
||||
raddr string
|
||||
}
|
||||
|
||||
func init() {
|
||||
proxy.RegisterServer("uottun", NewUoTTunServer)
|
||||
}
|
||||
|
||||
// NewUoTTun returns a UoTTun proxy.
|
||||
func NewUoTTun(s string, p proxy.Proxy) (*UoTTun, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
log.F("parse err: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr := u.Host
|
||||
d := strings.Split(addr, "=")
|
||||
if len(d) < 2 {
|
||||
return nil, errors.New("error in strings.Split")
|
||||
}
|
||||
|
||||
ut := &UoTTun{
|
||||
proxy: p,
|
||||
addr: d[0],
|
||||
raddr: d[1],
|
||||
}
|
||||
|
||||
return ut, nil
|
||||
}
|
||||
|
||||
// NewUoTTunServer returns a uot tunnel server.
|
||||
func NewUoTTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||
return NewUoTTun(s, p)
|
||||
}
|
||||
|
||||
// ListenAndServe listen and serve on tcp.
|
||||
func (s *UoTTun) ListenAndServe() {
|
||||
c, err := net.ListenPacket("udp", s.addr)
|
||||
if err != nil {
|
||||
log.F("[uottun] failed to listen on %s: %v", s.addr, err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
log.F("[uottun] listening UDP on %s", s.addr)
|
||||
|
||||
buf := make([]byte, proxy.UDPBufSize)
|
||||
|
||||
for {
|
||||
n, clientAddr, err := c.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[uottun] read error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
rc, p, err := s.proxy.Dial("uot", s.raddr)
|
||||
if err != nil {
|
||||
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
// no remote forwarder, just a local udp forwarder
|
||||
if urc, ok := rc.(*net.UDPConn); ok {
|
||||
proxy.RelayUDP(c, clientAddr, urc, 2*time.Minute)
|
||||
urc.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// remote forwarder, udp over tcp
|
||||
// TODO: check here carefully, ReadAll allocates buffer and may leads to memory leak.
|
||||
resp, err := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
log.F("[uottun] error in ioutil.ReadAll: %s\n", err)
|
||||
return
|
||||
}
|
||||
rc.Close()
|
||||
c.WriteTo(resp, clientAddr)
|
||||
}()
|
||||
|
||||
_, err = rc.Write(buf[:n])
|
||||
if err != nil {
|
||||
log.F("[uottun] remote write error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.F("[uottun] %s <-> %s via %s", clientAddr, s.raddr, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Serve is not allowed to be called directly.
|
||||
func (s *UoTTun) Serve(c net.Conn) {
|
||||
// TODO
|
||||
log.F("[uottun] func Serve: can not be called directly")
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
|
||||
"github.com/nadoo/glider/log"
|
||||
"github.com/nadoo/glider/pool"
|
||||
"github.com/nadoo/glider/proxy"
|
||||
)
|
||||
@ -35,12 +36,18 @@ func (s *VLess) Dial(network, addr string) (net.Conn, error) {
|
||||
|
||||
// DialUDP connects to the given address via the proxy.
|
||||
func (s *VLess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
||||
c, err := s.Dial("udp", addr)
|
||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
log.F("[vless]: dial to %s error: %s", s.addr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
c, err := NewClientConn(rc, s.uuid, network, addr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pkc := NewPktConn(c)
|
||||
return pkc, nil, nil
|
||||
|
||||
return NewPktConn(c), nil, nil
|
||||
}
|
||||
|
||||
// ClientConn is a vless client connection.
|
||||
|
@ -18,6 +18,10 @@ 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) {
|
||||
if len(b) < 2 {
|
||||
return 0, nil, errors.New("buf size is not enough")
|
||||
}
|
||||
|
||||
// Length
|
||||
if _, err := io.ReadFull(pc.Conn, b[:2]); err != nil {
|
||||
return 0, nil, err
|
||||
@ -41,5 +45,9 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(b)))
|
||||
buf.Write(b)
|
||||
|
||||
return pc.Write(buf.Bytes())
|
||||
n, err := pc.Write(buf.Bytes())
|
||||
if n > 2 {
|
||||
return n - 2, err
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package vless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -52,6 +51,8 @@ func (s *VLess) Serve(c net.Conn) {
|
||||
headBuf := pool.GetWriteBuffer()
|
||||
defer pool.PutWriteBuffer(headBuf)
|
||||
|
||||
c = NewServerConn(c)
|
||||
|
||||
cmd, target, err := s.readHeader(io.TeeReader(c, headBuf))
|
||||
if err != nil {
|
||||
log.F("[vless] verify header from %s error: %v", c.RemoteAddr(), err)
|
||||
@ -82,7 +83,7 @@ func (s *VLess) Serve(c net.Conn) {
|
||||
|
||||
log.F("[vless] %s <-> %s via %s", c.RemoteAddr(), target, dialer.Addr())
|
||||
|
||||
if err = proxy.Relay(NewServerConn(c), rc); err != nil {
|
||||
if err = proxy.Relay(c, rc); err != nil {
|
||||
log.F("[vless] %s <-> %s via %s, relay error: %v", c.RemoteAddr(), target, dialer.Addr(), err)
|
||||
// record remote conn failure only
|
||||
if !strings.Contains(err.Error(), s.addr) {
|
||||
@ -161,7 +162,7 @@ func (s *VLess) readHeader(r io.Reader) (CmdType, string, error) {
|
||||
func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
||||
rc, err := net.ListenPacket("udp", "")
|
||||
if err != nil {
|
||||
log.F("[vless] UDP remote listen error: %v", err)
|
||||
log.F("[vless] UDP listen error: %v", err)
|
||||
return
|
||||
}
|
||||
defer rc.Close()
|
||||
@ -172,26 +173,19 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
||||
return
|
||||
}
|
||||
|
||||
pc := NewPktConn(c)
|
||||
|
||||
go func() {
|
||||
buf := pool.GetBuffer(proxy.UDPBufSize)
|
||||
defer pool.PutBuffer(buf)
|
||||
for {
|
||||
_, err := io.ReadFull(c, buf[:2])
|
||||
n, _, err := pc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[vless] read c error: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
length := binary.BigEndian.Uint16(buf[:2])
|
||||
n, err := io.ReadFull(c, buf[:length])
|
||||
if err != nil {
|
||||
log.F("[vless] read payload error: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = rc.WriteTo(buf[:n], tgtAddr)
|
||||
if err != nil {
|
||||
log.F("[vless] write rc error: %s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -203,20 +197,16 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
||||
defer pool.PutBuffer(buf)
|
||||
|
||||
for {
|
||||
n, _, err := rc.ReadFrom(buf[2:])
|
||||
n, _, err := rc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.F("[vless] read rc error: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(n))
|
||||
_, err = c.Write(buf[:2+n])
|
||||
_, err = pc.WriteTo(buf[:n], nil)
|
||||
if err != nil {
|
||||
log.F("[vless] write c error: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ServerConn is a vless client connection.
|
||||
|
Loading…
Reference in New Issue
Block a user