proxy: added new scheme udp as replacement of udptun

This commit is contained in:
nadoo 2020-11-24 19:30:08 +08:00
parent 1fcfeabdb1
commit 6820644073
4 changed files with 137 additions and 5 deletions

View File

@ -16,11 +16,14 @@ import (
_ "github.com/nadoo/glider/proxy/ssh"
_ "github.com/nadoo/glider/proxy/ssr"
_ "github.com/nadoo/glider/proxy/tcp"
_ "github.com/nadoo/glider/proxy/tcptun"
_ "github.com/nadoo/glider/proxy/tls"
_ "github.com/nadoo/glider/proxy/trojan"
_ "github.com/nadoo/glider/proxy/udptun"
_ "github.com/nadoo/glider/proxy/udp"
_ "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

@ -16,7 +16,7 @@ require (
github.com/xtaci/kcp-go/v5 v5.6.1
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e // indirect
golang.org/x/tools v0.0.0-20201124005743-911501bfb504 // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
)

4
go.sum
View File

@ -141,8 +141,8 @@ golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174 h1:0rx0F4EjJNbxTuzWe0KjKcIzs+3VEb/Mrs/d1ciNz1c=
golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e h1:t96dS3DO8DGjawSLJL/HIdz8CycAd2v07XxqB3UPTi0=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201124005743-911501bfb504 h1:jOKV2ysikH1GANB7t2LotmhyvkkPvl7HQoEXkV6slJA=
golang.org/x/tools v0.0.0-20201124005743-911501bfb504/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

129
proxy/udp/udp.go Normal file
View File

@ -0,0 +1,129 @@
package udp
import (
"net"
"net/url"
"sync"
"time"
"github.com/nadoo/glider/log"
"github.com/nadoo/glider/proxy"
)
// UDP struct.
type UDP struct {
addr string
dialer proxy.Dialer
proxy proxy.Proxy
server proxy.Server
}
func init() {
proxy.RegisterDialer("udp", NewUDPDialer)
proxy.RegisterServer("udp", NewUDPServer)
}
// NewUDP returns a udp struct.
func NewUDP(s string, d proxy.Dialer, p proxy.Proxy) (*UDP, error) {
u, err := url.Parse(s)
if err != nil {
log.F("[udp] parse url err: %s", err)
return nil, err
}
t := &UDP{
dialer: d,
proxy: p,
addr: u.Host,
}
return t, nil
}
// NewUDPDialer returns a udp dialer.
func NewUDPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewUDP(s, d, nil)
}
// NewUDPServer returns a udp transport layer before the real server.
func NewUDPServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewUDP(s, nil, p)
}
// ListenAndServe listens on server's addr and serves connections.
func (s *UDP) ListenAndServe() {
c, err := net.ListenPacket("udp", s.addr)
if err != nil {
log.F("[udp] failed to listen on %s: %v", s.addr, err)
return
}
defer c.Close()
log.F("[udp] listening UDP on %s", s.addr)
var nm sync.Map
buf := make([]byte, proxy.UDPBufSize)
for {
n, lraddr, err := c.ReadFrom(buf)
if err != nil {
log.F("[udp] read error: %v", err)
continue
}
var raddr net.Addr
var pc net.PacketConn
v, ok := nm.Load(lraddr.String())
if !ok && v == nil {
pc, raddr, err = s.proxy.DialUDP("udp", "")
if err != nil {
log.F("[udp] remote dial error: %v", err)
continue
}
nm.Store(lraddr.String(), pc)
go func(c, pc net.PacketConn, lraddr net.Addr) {
proxy.RelayUDP(c, lraddr, pc, 2*time.Minute)
pc.Close()
nm.Delete(lraddr.String())
}(c, pc, lraddr)
} else {
pc = v.(net.PacketConn)
}
_, err = pc.WriteTo(buf[:n], raddr)
if err != nil {
log.F("[udp] remote write error: %v", err)
continue
}
log.F("[udp] %s <-> %s", lraddr, raddr)
}
}
// Serve serves a connection.
func (s *UDP) Serve(c net.Conn) {
log.F("[udp] func Serve: can not be called directly")
}
// Addr returns forwarder's address.
func (s *UDP) Addr() string {
if s.addr == "" {
return s.dialer.Addr()
}
return s.addr
}
// Dial connects to the address addr on the network net via the proxy.
func (s *UDP) Dial(network, addr string) (net.Conn, error) {
return s.dialer.Dial("udp", s.addr)
}
// DialUDP connects to the given address via the proxy.
func (s *UDP) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
return s.dialer.DialUDP(network, s.addr)
}