udp: remove uottun and optimize udp implementation

This commit is contained in:
nadoo 2020-10-15 00:19:05 +08:00
parent 78e03d7fbf
commit d510ea45b0
19 changed files with 83 additions and 249 deletions

View File

@ -63,7 +63,6 @@ we can set up local listeners as proxy servers, and forward requests to internet
|simple-obfs | | |√| |transport client only |simple-obfs | | |√| |transport client only
|tcptun |√| | | |transport server only |tcptun |√| | | |transport server only
|udptun | |√| | |transport server only |udptun | |√| | |transport server only
|uottun | |√| | |transport server only
|redir |√| | | |linux only |redir |√| | | |linux only
|redir6 |√| | | |linux only(ipv6) |redir6 |√| | | |linux only(ipv6)
|reject | | |√|√|reject all requests |reject | | |√|√|reject all requests
@ -144,7 +143,7 @@ glider 0.12.0 usage:
verbose mode verbose mode
Available schemes: 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 forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tls ws unix kcp simple-obfs
Socks5 scheme: 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 ./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. -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 ./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. -listen on :1080 as socks5 server, :8080 as http proxy server, forward all requests via remote ss server.

View File

@ -131,7 +131,7 @@ func usage() {
fmt.Fprintf(w, "\n") fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "Available schemes:\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, " forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tls ws unix kcp simple-obfs\n")
fmt.Fprintf(w, "\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, " "+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, " -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, "\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, " "+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, " -listen on :1080 as socks5 server, :8080 as http proxy server, forward all requests via remote ss server.\n")
fmt.Fprintf(w, "\n") fmt.Fprintf(w, "\n")

View File

@ -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 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=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) # http over tls (HTTPS proxy)
# listen=tls://:443?cert=crtFilePath&key=keyFilePath,http:// # listen=tls://:443?cert=crtFilePath&key=keyFilePath,http://

View File

@ -19,7 +19,6 @@ import (
_ "github.com/nadoo/glider/proxy/tls" _ "github.com/nadoo/glider/proxy/tls"
_ "github.com/nadoo/glider/proxy/trojan" _ "github.com/nadoo/glider/proxy/trojan"
_ "github.com/nadoo/glider/proxy/udptun" _ "github.com/nadoo/glider/proxy/udptun"
_ "github.com/nadoo/glider/proxy/uottun"
_ "github.com/nadoo/glider/proxy/vless" _ "github.com/nadoo/glider/proxy/vless"
_ "github.com/nadoo/glider/proxy/vmess" _ "github.com/nadoo/glider/proxy/vmess"
_ "github.com/nadoo/glider/proxy/ws" _ "github.com/nadoo/glider/proxy/ws"

6
go.mod
View File

@ -10,10 +10,10 @@ require (
github.com/nadoo/ipset v0.3.0 github.com/nadoo/ipset v0.3.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/xtaci/kcp-go/v5 v5.6.1 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/net v0.0.0-20201010224723-4f7140c49acb // indirect
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 // indirect golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc // indirect
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 // indirect golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752 // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
) )

12
go.sum
View File

@ -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-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 h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= 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-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 h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20201014080544-cc95f250f6bc h1:HVFDs9bKvTxP6bh1Rj9MCSo+UmafQtI8ZWDPVwVk9g4=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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= 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 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-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-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 h1:BANdcOVw3KTuUiyfDp7wrzCpkCe8UP3lowugJngxBTg= golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752 h1:2ntEwh02rqo2jSsrYmp4yKHHjh0CbXP3ZtSUetSB+q8=
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= 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-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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=

View File

@ -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) { func (d *Direct) dial(network, addr string, localIP net.IP) (net.Conn, error) {
if network == "uot" {
network = "udp"
}
var la net.Addr var la net.Addr
switch network { switch network {
case "tcp": case "tcp":

View File

@ -45,14 +45,14 @@ var Errors = []error{
errors.New("socks5UDPAssociate"), errors.New("socks5UDPAssociate"),
} }
// Addr . // Addr represents a SOCKS address as defined in RFC 1928 section 5.
type Addr []byte type Addr []byte
// String serializes SOCKS address a to string form. // String serializes SOCKS address a to string form.
func (a Addr) String() string { func (a Addr) String() string {
var host, port string var host, port string
switch ATYP(a[0]) { // address type switch a[0] { // address type
case ATypDomain: case ATypDomain:
host = string(a[2 : 2+int(a[1])]) 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])) 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) 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. // ReadAddrBuf reads just enough bytes from r to get a valid Addr.
func ReadAddrBuf(r io.Reader, b []byte) (Addr, error) { func ReadAddrBuf(r io.Reader, b []byte) (Addr, error) {
if len(b) < MaxAddrLen { if len(b) < MaxAddrLen {
@ -87,7 +77,7 @@ func ReadAddrBuf(r io.Reader, b []byte) (Addr, error) {
return nil, err return nil, err
} }
switch ATYP(b[0]) { switch b[0] {
case ATypDomain: case ATypDomain:
_, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length _, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length
if err != nil { if err != nil {
@ -118,7 +108,7 @@ func SplitAddr(b []byte) Addr {
return nil return nil
} }
switch ATYP(b[0]) { switch b[0] {
case ATypDomain: case ATypDomain:
if len(b) < 2 { if len(b) < 2 {
return nil return nil

View File

@ -4,7 +4,6 @@ import (
"errors" "errors"
"net" "net"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/pool" "github.com/nadoo/glider/pool"
"github.com/nadoo/glider/proxy/socks" "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() { if err, ok := err.(net.Error); ok && err.Timeout() {
continue continue
} }
log.F("[socks5] dialudp udp associate end") // log.F("[socks5] dialudp udp associate end")
return return
} }
}() }()
@ -98,14 +97,19 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return pc.PacketConn.WriteTo(b, addr) return pc.PacketConn.WriteTo(b, addr)
} }
buf := pool.GetBuffer(3 + len(pc.tgtAddr) + len(b)) buf := pool.GetWriteBuffer()
defer pool.PutBuffer(buf) defer pool.PutWriteBuffer(buf)
copy(buf, []byte{0, 0, 0}) buf.Write([]byte{0, 0, 0})
copy(buf[3:], pc.tgtAddr) tgtLen, _ := buf.Write(pc.tgtAddr)
copy(buf[3+len(pc.tgtAddr):], b) 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 . // Close .

View File

@ -139,7 +139,7 @@ func (s *Socks5) ListenAndServeUDP() {
nm.Delete(raddr.String()) nm.Delete(raddr.String())
}() }()
log.F("[socks5u] %s <-> %s", raddr, c.tgtAddr) log.F("[socks5u] %s <-> %s via %s", raddr, c.tgtAddr, nextHop)
} else { } else {
pc = v.(*PktConn) pc = v.(*PktConn)

View File

@ -29,10 +29,6 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) {
return nil, errors.New("[ss] unable to parse address: " + addr) 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) c, err := s.dialer.Dial("tcp", s.addr)
if err != nil { if err != nil {
log.F("[ss] dial to %s error: %s", s.addr, err) log.F("[ss] dial to %s error: %s", s.addr, err)

View File

@ -67,11 +67,16 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return pc.PacketConn.WriteTo(b, addr) return pc.PacketConn.WriteTo(b, addr)
} }
buf := pool.GetBuffer(len(pc.tgtAddr) + len(b)) buf := pool.GetWriteBuffer()
pool.PutBuffer(buf) defer pool.PutWriteBuffer(buf)
copy(buf, pc.tgtAddr) tgtLen, _ := buf.Write(pc.tgtAddr)
copy(buf[len(pc.tgtAddr):], b) 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
} }

View File

@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/nadoo/glider/log" "github.com/nadoo/glider/log"
"github.com/nadoo/glider/pool"
"github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy"
"github.com/nadoo/glider/proxy/socks" "github.com/nadoo/glider/proxy/socks"
) )
@ -60,45 +59,8 @@ func (s *SS) Serve(c net.Conn) {
return 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" network := "tcp"
if uot { dialer := s.proxy.NextDialer(tgt.String())
network = "udp"
}
rc, err := dialer.Dial(network, tgt.String()) rc, err := dialer.Dial(network, tgt.String())
if err != nil { if err != nil {
@ -161,7 +123,7 @@ func (s *SS) ListenAndServeUDP() {
nm.Delete(raddr.String()) nm.Delete(raddr.String())
}() }()
log.F("[ssu] %s <-> %s", raddr, c.tgtAddr) log.F("[ssu] %s <-> %s via %s", raddr, c.tgtAddr, nextHop)
} else { } else {
pc = v.(*PktConn) pc = v.(*PktConn)

View File

@ -7,7 +7,6 @@ import (
"net" "net"
"github.com/nadoo/glider/pool" "github.com/nadoo/glider/pool"
"github.com/nadoo/glider/proxy"
"github.com/nadoo/glider/proxy/socks" "github.com/nadoo/glider/proxy/socks"
) )
@ -36,14 +35,19 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
return 0, nil, err return 0, nil, err
} }
if len(b) < 2 {
return 0, nil, errors.New("buf size is not enough")
}
// Length // Length
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil { if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
return 0, nil, err return 0, nil, err
} }
length := int(binary.BigEndian.Uint16(b[:2])) 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 // CRLF
@ -51,10 +55,6 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
return 0, nil, err return 0, nil, err
} }
if len(b) < length {
return 0, nil, errors.New("buf size is not enough")
}
// Payload // Payload
n, err := io.ReadFull(pc.Conn, b[:length]) n, err := io.ReadFull(pc.Conn, b[:length])
if err != nil { if err != nil {
@ -70,10 +70,15 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
buf := pool.GetWriteBuffer() buf := pool.GetWriteBuffer()
defer pool.PutWriteBuffer(buf) defer pool.PutWriteBuffer(buf)
buf.Write(pc.tgtAddr) tgtLen, _ := buf.Write(pc.tgtAddr)
binary.Write(buf, binary.BigEndian, uint16(len(b))) binary.Write(buf, binary.BigEndian, uint16(len(b)))
buf.WriteString("\r\n") buf.WriteString("\r\n")
buf.Write(b) 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
} }

View File

@ -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) { func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
rc, err := net.ListenPacket("udp", "") rc, err := net.ListenPacket("udp", "")
if err != nil { if err != nil {
log.F("[trojan] UDP remote listen error: %v", err) log.F("[trojan] UDP listen error: %v", err)
return return
} }
defer rc.Close() defer rc.Close()
@ -212,13 +212,11 @@ func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
for { for {
n, _, err := pc.ReadFrom(buf) n, _, err := pc.ReadFrom(buf)
if err != nil { if err != nil {
log.F("[trojan] read error: %s\n", err)
return return
} }
_, err = rc.WriteTo(buf[:n], tgtAddr) _, err = rc.WriteTo(buf[:n], tgtAddr)
if err != nil { if err != nil {
log.F("[trojan] write rc error: %s\n", err)
return return
} }
} }
@ -232,14 +230,12 @@ func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
for { for {
n, _, err := rc.ReadFrom(buf) n, _, err := rc.ReadFrom(buf)
if err != nil { if err != nil {
log.F("[trojan] read rc error: %v", err)
break break
} }
// WriteTo addr can be nil because the PktConn has it's own target, see packet.go // WriteTo addr can be nil because the PktConn has it's own target, see packet.go
_, err = pc.WriteTo(buf[:n], nil) _, err = pc.WriteTo(buf[:n], nil)
if err != nil { if err != nil {
log.F("[trojan] write pc error: %v", err)
break break
} }
} }

View File

@ -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")
}

View File

@ -7,6 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/pool" "github.com/nadoo/glider/pool"
"github.com/nadoo/glider/proxy" "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. // DialUDP connects to the given address via the proxy.
func (s *VLess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { 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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
pkc := NewPktConn(c)
return pkc, nil, nil return NewPktConn(c), nil, nil
} }
// ClientConn is a vless client connection. // ClientConn is a vless client connection.

View File

@ -18,6 +18,10 @@ func NewPktConn(c net.Conn) *PktConn { return &PktConn{Conn: c} }
// ReadFrom implements the necessary function of net.PacketConn. // 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. // 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) { 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 // Length
if _, err := io.ReadFull(pc.Conn, b[:2]); err != nil { if _, err := io.ReadFull(pc.Conn, b[:2]); err != nil {
return 0, nil, err 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))) binary.Write(buf, binary.BigEndian, uint16(len(b)))
buf.Write(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
} }

View File

@ -2,7 +2,6 @@ package vless
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -52,6 +51,8 @@ func (s *VLess) Serve(c net.Conn) {
headBuf := pool.GetWriteBuffer() headBuf := pool.GetWriteBuffer()
defer pool.PutWriteBuffer(headBuf) defer pool.PutWriteBuffer(headBuf)
c = NewServerConn(c)
cmd, target, err := s.readHeader(io.TeeReader(c, headBuf)) cmd, target, err := s.readHeader(io.TeeReader(c, headBuf))
if err != nil { if err != nil {
log.F("[vless] verify header from %s error: %v", c.RemoteAddr(), err) 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()) 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) log.F("[vless] %s <-> %s via %s, relay error: %v", c.RemoteAddr(), target, dialer.Addr(), err)
// record remote conn failure only // record remote conn failure only
if !strings.Contains(err.Error(), s.addr) { 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) { func (s *VLess) ServeUoT(c net.Conn, tgt string) {
rc, err := net.ListenPacket("udp", "") rc, err := net.ListenPacket("udp", "")
if err != nil { if err != nil {
log.F("[vless] UDP remote listen error: %v", err) log.F("[vless] UDP listen error: %v", err)
return return
} }
defer rc.Close() defer rc.Close()
@ -172,26 +173,19 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
return return
} }
pc := NewPktConn(c)
go func() { go func() {
buf := pool.GetBuffer(proxy.UDPBufSize) buf := pool.GetBuffer(proxy.UDPBufSize)
defer pool.PutBuffer(buf) defer pool.PutBuffer(buf)
for { for {
_, err := io.ReadFull(c, buf[:2]) n, _, err := pc.ReadFrom(buf)
if err != nil { 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 return
} }
_, err = rc.WriteTo(buf[:n], tgtAddr) _, err = rc.WriteTo(buf[:n], tgtAddr)
if err != nil { if err != nil {
log.F("[vless] write rc error: %s\n", err)
return return
} }
} }
@ -203,20 +197,16 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
defer pool.PutBuffer(buf) defer pool.PutBuffer(buf)
for { for {
n, _, err := rc.ReadFrom(buf[2:]) n, _, err := rc.ReadFrom(buf)
if err != nil { if err != nil {
log.F("[vless] read rc error: %v", err)
break break
} }
binary.BigEndian.PutUint16(buf[:2], uint16(n)) _, err = pc.WriteTo(buf[:n], nil)
_, err = c.Write(buf[:2+n])
if err != nil { if err != nil {
log.F("[vless] write c error: %v", err)
break break
} }
} }
} }
// ServerConn is a vless client connection. // ServerConn is a vless client connection.