proxy: drop tcptun and udptun, use tcp and udp instead

This commit is contained in:
nadoo 2020-11-29 15:09:44 +08:00
parent adfb2fb9b4
commit c9f3c20bc1
15 changed files with 49 additions and 267 deletions

View File

@ -56,13 +56,13 @@ we can set up local listeners as proxy servers, and forward requests to internet
|SSR | | |√| |client only
|SSH | | |√| |client only
|SOCKS4 | | |√| |client only
|TCP |√| |√| |tcp tunnel client & server
|UDP | |√| |√|udp tunnel client & server
|TLS |√| |√| |transport client & server
|KCP | |√|√| |transport client & server
|Unix |√| |√| |transport client & server
|Websocket |√| |√| |transport client & server
|Simple-Obfs | | |√| |transport client only
|TCPTun |√| | | |transport server only
|UDPTun | |√| | |transport server only
|Redir |√| | | |linux only
|Redir6 |√| | | |linux only(ipv6)
|Reject | | |√|√|reject all requests
@ -94,7 +94,12 @@ glider -h
<summary>click to see details</summary>
```bash
glider 0.12.3 usage:
glider 0.13.0 usage:
-check string
check=tcp[://HOST:PORT]: tcp port connect check
check=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]
check=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, environment variables: FORWARDER_ADDR
check=disable: disable health check (default "http://www.msftconnecttest.com/connecttest.txt#expect=200")
-checkdisabledonly
check disabled fowarders only
-checkinterval int
@ -103,8 +108,6 @@ glider 0.12.3 usage:
fowarder check timeout(seconds) (default 10)
-checktolerance int
fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode
-checkwebsite string
fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80 (default "www.apple.com")
-config string
config file path
-dialtimeout int
@ -149,8 +152,8 @@ glider 0.12.3 usage:
verbose mode
Available schemes:
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcptun udptun tls ws unix kcp
forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tls ws unix kcp simple-obfs
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcp udp tls ws unix kcp
forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws unix kcp simple-obfs
Socks5 scheme:
socks://[user:pass@]host:port
@ -292,26 +295,20 @@ Examples:
./glider -listen redir://:1081 -forward ss://method:pass@1.1.1.1:8443
-listen on :1081 as a transparent redirect server, forward all requests via remote ss server.
./glider -listen redir://:1081 -forward "ssr://method:pass@1.1.1.1:8444?protocol=a&protocol_param=b&obfs=c&obfs_param=d"
-listen on :1081 as a transparent redirect server, forward all requests via remote ssr server.
./glider -listen redir://:1081 -forward "tls://abc.com:443,vmess://security:uuid@?alterID=10"
-listen on :1081 as a transparent redirect server, forward all requests via remote tls+vmess server.
./glider -listen redir://:1081 -forward "ws://1.1.1.1:80,vmess://security:uuid@?alterID=10"
-listen on :1081 as a transparent redirect server, forward all requests via remote ws+vmess server.
./glider -listen tcp://:80 -forward tcp://2.2.2.2:80
-tcp tunnel: listen on :80 and forward all requests to 2.2.2.2:80.
./glider -listen tcptun://:80=2.2.2.2:80 -forward ss://method:pass@1.1.1.1:8443
-listen on :80 and forward all requests to 2.2.2.2:80 via remote ss server.
./glider -listen udptun://:53=8.8.8.8:53 -forward ss://method:pass@1.1.1.1:8443
./glider -listen udp://:53 -forward ss://method:pass@1.1.1.1:8443,udp://8.8.8.8:53
-listen on :53 and forward all udp requests to 8.8.8.8:53 via remote ss server.
./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.
./glider -listen redir://:1081 -dns=:53 -dnsserver=8.8.8.8:53 -forward ss://method:pass@server1:port1,ss://method:pass@server2:port2
-listen on :1081 as transparent redirect server, :53 as dns server, use forward chain: server1 -> server2.
./glider -listen redir://:1081 -dns=:53 -dnsserver=8.8.8.8:53 -forward ss://method:pass@server:port
-listen on :1081 as transparent redirect server, :53 as dns server, forward via ss server.
./glider -listen socks5://:1080 -forward ss://method:pass@server1:port1 -forward ss://method:pass@server2:port2 -strategy rr
-listen on :1080 as socks5 server, forward requests via server1 and server2 in round robin mode.

View File

@ -131,8 +131,8 @@ 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 tls ws 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, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tcp udp tls ws unix kcp\n")
fmt.Fprintf(w, " forward: reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws unix kcp simple-obfs\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "Socks5 scheme:\n")
@ -302,26 +302,20 @@ func usage() {
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward ss://method:pass@1.1.1.1:8443\n")
fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote ss server.\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"ssr://method:pass@1.1.1.1:8444?protocol=a&protocol_param=b&obfs=c&obfs_param=d\"\n")
fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote ssr server.\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"tls://abc.com:443,vmess://security:uuid@?alterID=10\"\n")
fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote tls+vmess server.\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"ws://1.1.1.1:80,vmess://security:uuid@?alterID=10\"\n")
fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote ws+vmess server.\n")
fmt.Fprintf(w, " "+app+" -listen tcp://:80 -forward tcp://2.2.2.2:80\n")
fmt.Fprintf(w, " -tcp tunnel: listen on :80 and forward all requests to 2.2.2.2:80.\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, " "+app+" -listen tcptun://:80=2.2.2.2:80 -forward ss://method:pass@1.1.1.1:8443\n")
fmt.Fprintf(w, " -listen on :80 and forward all requests to 2.2.2.2:80 via remote ss server.\n")
fmt.Fprintf(w, "\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, " "+app+" -listen udp://:53 -forward ss://method:pass@1.1.1.1:8443,udp://8.8.8.8:53\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 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")
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -dns=:53 -dnsserver=8.8.8.8:53 -forward ss://method:pass@server1:port1,ss://method:pass@server2:port2\n")
fmt.Fprintf(w, " -listen on :1081 as transparent redirect server, :53 as dns server, use forward chain: server1 -> server2.\n")
fmt.Fprintf(w, " "+app+" -listen redir://:1081 -dns=:53 -dnsserver=8.8.8.8:53 -forward ss://method:pass@server:port\n")
fmt.Fprintf(w, " -listen on :1081 as transparent redirect server, :53 as dns server, forward via ss server.\n")
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, " "+app+" -listen socks5://:1080 -forward ss://method:pass@server1:port1 -forward ss://method:pass@server2:port2 -strategy rr\n")
fmt.Fprintf(w, " -listen on :1080 as socks5 server, forward requests via server1 and server2 in round robin mode.\n")

View File

@ -51,12 +51,6 @@ listen=socks5://:1080
# listen on 1081 as a linux transparent proxy server.
# listen=redir://:1081
# listen on 1082 as a tcp tunnel, all requests to :1082 will be forward to 1.1.1.1:80
# listen=tcptun://:1082=1.1.1.1:80
# 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
# http over tls (HTTPS proxy)
# listen=tls://:443?cert=crtFilePath&key=keyFilePath,http://

View File

@ -22,8 +22,4 @@ import (
_ "github.com/nadoo/glider/proxy/vless"
_ "github.com/nadoo/glider/proxy/vmess"
_ "github.com/nadoo/glider/proxy/ws"
// deprecated, to be removed.
_ "github.com/nadoo/glider/proxy/tcptun"
_ "github.com/nadoo/glider/proxy/udptun"
)

2
go.mod
View File

@ -15,7 +15,7 @@ require (
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-20201124201722-c8d3bf9c5392
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
golang.org/x/sys v0.0.0-20201126233918-771906719818 // indirect
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
)

4
go.sum
View File

@ -128,8 +128,8 @@ golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818 h1:f1CIuDlJhwANEC2MM87MBEVMr3jl5bifgsfj90XAF9c=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -8,7 +8,7 @@ type Proxy interface {
Dial(network, addr string) (c net.Conn, dialer Dialer, err error)
// DialUDP connects to the given address via the proxy.
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
DialUDP(network, addr string) (pc net.PacketConn, dialer UDPDialer, writeTo net.Addr, err error)
// Get the dialer by dstAddr.
NextDialer(dstAddr string) Dialer

View File

@ -124,7 +124,7 @@ func (s *Socks5) ListenAndServeUDP() {
continue
}
lpc, nextHop, err := s.proxy.DialUDP("udp", c.tgtAddr.String())
lpc, _, nextHop, err := s.proxy.DialUDP("udp", c.tgtAddr.String())
if err != nil {
log.F("[socks5u] remote dial error: %v", err)
continue

View File

@ -108,7 +108,7 @@ func (s *SS) ListenAndServeUDP() {
var pc *PktConn
v, ok := nm.Load(raddr.String())
if !ok && v == nil {
lpc, nextHop, err := s.proxy.DialUDP("udp", c.tgtAddr.String())
lpc, _, nextHop, err := s.proxy.DialUDP("udp", c.tgtAddr.String())
if err != nil {
log.F("[ssu] remote dial error: %v", err)
continue

View File

@ -1,99 +0,0 @@
package tcptun
import (
"errors"
"net"
"net/url"
"strings"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/proxy"
)
// TCPTun struct.
type TCPTun struct {
proxy proxy.Proxy
addr string
raddr string
}
func init() {
proxy.RegisterServer("tcptun", NewTCPTunServer)
}
// NewTCPTun returns a tcptun proxy.
func NewTCPTun(s string, p proxy.Proxy) (*TCPTun, error) {
u, err := url.Parse(s)
if err != nil {
log.F("[tcptun] 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")
}
t := &TCPTun{
proxy: p,
addr: d[0],
raddr: d[1],
}
return t, nil
}
// NewTCPTunServer returns a udp tunnel server.
func NewTCPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewTCPTun(s, p)
}
// ListenAndServe listens on server's addr and serves connections.
func (s *TCPTun) ListenAndServe() {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("[tcptun] failed to listen on %s: %v", s.addr, err)
return
}
log.F("[tcptun] listening TCP on %s", s.addr)
for {
c, err := l.Accept()
if err != nil {
log.F("[tcptun] failed to accept: %v", err)
continue
}
go s.Serve(c)
}
}
// Serve serves a connection.
func (s *TCPTun) Serve(c net.Conn) {
defer c.Close()
if c, ok := c.(*net.TCPConn); ok {
c.SetKeepAlive(true)
}
rc, dialer, err := s.proxy.Dial("tcp", s.raddr)
if err != nil {
log.F("[tcptun] %s <-> %s via %s, error in dial: %v", c.RemoteAddr(), s.addr, dialer.Addr(), err)
s.proxy.Record(dialer, false)
return
}
defer rc.Close()
log.F("[tcptun] %s <-> %s via %s", c.RemoteAddr(), s.raddr, dialer.Addr())
if err = proxy.Relay(c, rc); err != nil {
log.F("[tcptun] %s <-> %s via %s, relay error: %v", c.RemoteAddr(), s.raddr, dialer.Addr(), err)
// record remote conn failure only
if !strings.Contains(err.Error(), s.addr) {
s.proxy.Record(dialer, false)
}
}
}

View File

@ -73,10 +73,11 @@ func (s *UDP) ListenAndServe() {
var raddr net.Addr
var pc net.PacketConn
var dialer proxy.UDPDialer
v, ok := nm.Load(lraddr.String())
if !ok && v == nil {
pc, raddr, err = s.proxy.DialUDP("udp", "")
pc, dialer, raddr, err = s.proxy.DialUDP("udp", "")
if err != nil {
log.F("[udp] remote dial error: %v", err)
continue
@ -100,7 +101,7 @@ func (s *UDP) ListenAndServe() {
continue
}
log.F("[udp] %s <-> %s", lraddr, raddr)
log.F("[udp] %s <-> %s", lraddr, dialer.Addr())
}
}

View File

@ -1,113 +0,0 @@
package udptun
import (
"errors"
"net"
"net/url"
"strings"
"sync"
"time"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/proxy"
)
// UDPTun is a base udptun struct.
type UDPTun struct {
proxy proxy.Proxy
addr string
taddr string // tunnel addr string
tuaddr *net.UDPAddr // tunnel addr
}
func init() {
proxy.RegisterServer("udptun", NewUDPTunServer)
}
// NewUDPTun returns a UDPTun proxy.
func NewUDPTun(s string, p proxy.Proxy) (*UDPTun, error) {
u, err := url.Parse(s)
if err != nil {
log.F("[udptun] 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 := &UDPTun{
proxy: p,
addr: d[0],
taddr: d[1],
}
ut.tuaddr, err = net.ResolveUDPAddr("udp", ut.taddr)
return ut, err
}
// NewUDPTunServer returns a udp tunnel server.
func NewUDPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewUDPTun(s, p)
}
// ListenAndServe listen and serves on the given address.
func (s *UDPTun) ListenAndServe() {
c, err := net.ListenPacket("udp", s.addr)
if err != nil {
log.F("[udptun] failed to listen on %s: %v", s.addr, err)
return
}
defer c.Close()
log.F("[udptun] listening UDP on %s", s.addr)
var nm sync.Map
buf := make([]byte, proxy.UDPBufSize)
for {
n, raddr, err := c.ReadFrom(buf)
if err != nil {
log.F("[udptun] read error: %v", err)
continue
}
var pc net.PacketConn
v, ok := nm.Load(raddr.String())
if !ok && v == nil {
pc, _, err = s.proxy.DialUDP("udp", s.taddr)
if err != nil {
log.F("[udptun] remote dial error: %v", err)
continue
}
nm.Store(raddr.String(), pc)
go func(c, pc net.PacketConn, raddr net.Addr) {
proxy.RelayUDP(c, raddr, pc, 2*time.Minute)
pc.Close()
nm.Delete(raddr.String())
}(c, pc, raddr)
} else {
pc = v.(net.PacketConn)
}
_, err = pc.WriteTo(buf[:n], s.tuaddr)
if err != nil {
log.F("[udptun] remote write error: %v", err)
continue
}
log.F("[udptun] %s <-> %s", raddr, s.taddr)
}
}
// Serve serves a net.Conn, can not be called directly.
func (s *UDPTun) Serve(c net.Conn) {
log.F("[udptun] func Serve: can not be called directly")
}

View File

@ -48,16 +48,26 @@ func ForwarderFromURL(s, intface string, dialTimeout, relayTimeout time.Duration
return nil, err
}
var addrs []string
for _, url := range strings.Split(ss[0], ",") {
d, err = proxy.DialerFromURL(url, d)
if err != nil {
return nil, err
}
cnt := len(addrs)
if cnt == 0 ||
(cnt > 0 && d.Addr() != addrs[cnt-1]) {
addrs = append(addrs, d.Addr())
}
}
f.Dialer = d
f.addr = d.Addr()
if len(addrs) > 0 {
f.addr = strings.Join(addrs, ",")
}
// set forwarder to disabled by default
f.Disable()
@ -70,7 +80,6 @@ func DirectForwarder(intface string, dialTimeout, relayTimeout time.Duration) *F
if err != nil {
return nil
}
return &Forwarder{Dialer: d, addr: d.Addr()}
}
@ -93,6 +102,7 @@ func (f *Forwarder) parseOption(option string) error {
}
// Addr returns the forwarder's addr.
// NOTE: addr returns for chained dialers: dialer1Addr,dialer2Addr,...
func (f *Forwarder) Addr() string {
return f.addr
}
@ -103,7 +113,6 @@ func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
if err != nil {
f.IncFailures()
}
return c, err
}

View File

@ -102,8 +102,10 @@ func (p *FwdrGroup) Dial(network, addr string) (net.Conn, proxy.Dialer, error) {
}
// DialUDP connects to the given address.
func (p *FwdrGroup) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return p.NextDialer(addr).DialUDP(network, addr)
func (p *FwdrGroup) DialUDP(network, addr string) (pc net.PacketConn, dialer proxy.UDPDialer, writeTo net.Addr, err error) {
nd := p.NextDialer(addr)
pc, wt, err := nd.DialUDP(network, addr)
return pc, nd, wt, err
}
// NextDialer returns the next dialer.
@ -244,6 +246,7 @@ func (p *FwdrGroup) check(fwdr *Forwarder, checker Checker) {
if errors.Is(err, proxy.ErrNotSupported) {
fwdr.SetMaxFailures(0)
log.F("[check] %s(%d), %s, stop checking", fwdr.Addr(), fwdr.Priority(), err)
fwdr.Enable()
break
}
@ -258,9 +261,9 @@ func (p *FwdrGroup) check(fwdr *Forwarder, checker Checker) {
}
wait = 1
fwdr.Enable()
fwdr.SetLatency(int64(elapsed))
log.F("[check] %s(%d), SUCCESS. elapsed: %s", fwdr.Addr(), fwdr.Priority(), elapsed)
fwdr.Enable()
}
}

View File

@ -61,7 +61,7 @@ func (p *Proxy) Dial(network, addr string) (net.Conn, proxy.Dialer, error) {
}
// DialUDP connects to the given address via the proxy.
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, dialer proxy.UDPDialer, writeTo net.Addr, err error) {
return p.findDialer(addr).DialUDP(network, addr)
}