mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +08:00 
			
		
		
		
	unix: support udp forwarding (#194)
This commit is contained in:
		
							parent
							
								
									63112a1509
								
							
						
					
					
						commit
						142865535e
					
				@ -60,7 +60,7 @@ we can set up local listeners as proxy servers, and forward requests to internet
 | 
				
			|||||||
|UDP          | |√| |√|udp tunnel client & server
 | 
					|UDP          | |√| |√|udp tunnel client & server
 | 
				
			||||||
|TLS          |√| |√| |transport client & server
 | 
					|TLS          |√| |√| |transport client & server
 | 
				
			||||||
|KCP          | |√|√| |transport client & server
 | 
					|KCP          | |√|√| |transport client & server
 | 
				
			||||||
|Unix         |√| |√| |transport client & server
 | 
					|Unix         |√|√|√|√|transport client & server
 | 
				
			||||||
|Websocket    |√| |√| |transport client & server
 | 
					|Websocket    |√| |√| |transport client & server
 | 
				
			||||||
|Simple-Obfs  | | |√| |transport client only
 | 
					|Simple-Obfs  | | |√| |transport client only
 | 
				
			||||||
|Redir        |√| | | |linux only
 | 
					|Redir        |√| | | |linux only
 | 
				
			||||||
@ -238,6 +238,9 @@ KCP scheme:
 | 
				
			|||||||
Available crypt types for KCP:
 | 
					Available crypt types for KCP:
 | 
				
			||||||
  none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20
 | 
					  none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available modes for KCP:
 | 
				
			||||||
 | 
					  fast, fast2, fast3, normal, default: fast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Simple-Obfs scheme:
 | 
					Simple-Obfs scheme:
 | 
				
			||||||
  simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]
 | 
					  simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -239,6 +239,10 @@ func usage() {
 | 
				
			|||||||
	fmt.Fprintf(w, "  none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20\n")
 | 
						fmt.Fprintf(w, "  none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20\n")
 | 
				
			||||||
	fmt.Fprintf(w, "\n")
 | 
						fmt.Fprintf(w, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Fprintf(w, "Available modes for KCP:\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(w, "  fast, fast2, fast3, normal, default: fast\n")
 | 
				
			||||||
 | 
						fmt.Fprintf(w, "\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Fprintf(w, "Simple-Obfs scheme:\n")
 | 
						fmt.Fprintf(w, "Simple-Obfs scheme:\n")
 | 
				
			||||||
	fmt.Fprintf(w, "  simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]\n")
 | 
						fmt.Fprintf(w, "  simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]\n")
 | 
				
			||||||
	fmt.Fprintf(w, "\n")
 | 
						fmt.Fprintf(w, "\n")
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@ -15,8 +15,8 @@ require (
 | 
				
			|||||||
	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-20201124201722-c8d3bf9c5392
 | 
						golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392
 | 
				
			||||||
	golang.org/x/sys v0.0.0-20201130072748-111129e158e2 // indirect
 | 
						golang.org/x/sys v0.0.0-20201130171929-760e229fe7c5 // indirect
 | 
				
			||||||
	golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b // indirect
 | 
						golang.org/x/tools v0.0.0-20201201064407-fd09bd90d85c // indirect
 | 
				
			||||||
	gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
 | 
						gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							@ -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-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 h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201130072748-111129e158e2 h1:zXpk15uCEAaaJcTxBqQacweHUQ0HDhDOzupNGFs4imE=
 | 
					golang.org/x/sys v0.0.0-20201130171929-760e229fe7c5 h1:dMDtAap8F/+vsyXblqK90iTzYJjNix5MsXDicSYol6w=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20201130072748-111129e158e2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20201130171929-760e229fe7c5/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 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
					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=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
@ -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-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 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-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b h1:Lq5JUTFhiybGVf28jB6QRpqd13/JPOaCnET17PVzYJE=
 | 
					golang.org/x/tools v0.0.0-20201201064407-fd09bd90d85c h1:D/mVYXCk6gUcyr7WuGlAk/ShHqgARUXc2VQxo27Hmws=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20201201064407-fd09bd90d85c/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-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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
 | 
				
			|||||||
@ -24,8 +24,8 @@ type KCP struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	key   string
 | 
						key   string
 | 
				
			||||||
	crypt string
 | 
						crypt string
 | 
				
			||||||
	mode  string
 | 
					 | 
				
			||||||
	block kcp.BlockCrypt
 | 
						block kcp.BlockCrypt
 | 
				
			||||||
 | 
						mode  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dataShards   int
 | 
						dataShards   int
 | 
				
			||||||
	parityShards int
 | 
						parityShards int
 | 
				
			||||||
@ -258,7 +258,8 @@ func (s *KCP) setParams(c *kcp.UDPSession) {
 | 
				
			|||||||
		c.SetNoDelay(1, 20, 2, 1)
 | 
							c.SetNoDelay(1, 20, 2, 1)
 | 
				
			||||||
	case "fast3":
 | 
						case "fast3":
 | 
				
			||||||
		c.SetNoDelay(1, 10, 2, 1)
 | 
							c.SetNoDelay(1, 10, 2, 1)
 | 
				
			||||||
	default: // default use fast
 | 
						default:
 | 
				
			||||||
 | 
							log.F("[kcp] unkonw mode: %s, use fast mode instead", s.mode)
 | 
				
			||||||
		c.SetNoDelay(0, 30, 2, 1)
 | 
							c.SetNoDelay(0, 30, 2, 1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,9 @@ func (s *UDP) ListenAndServe() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		v, ok := nm.Load(lraddr.String())
 | 
							v, ok := nm.Load(lraddr.String())
 | 
				
			||||||
		if !ok && v == nil {
 | 
							if !ok && v == nil {
 | 
				
			||||||
			pc, dialer, raddr, err = s.proxy.DialUDP("udp", "")
 | 
								// we know we are creating an udp tunnel, so the dial addr is meaningless,
 | 
				
			||||||
 | 
								// we use lraddr here to help the unix client to identify the source socket.
 | 
				
			||||||
 | 
								pc, dialer, raddr, err = s.proxy.DialUDP("udp", lraddr.String())
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.F("[udp] remote dial error: %v", err)
 | 
									log.F("[udp] remote dial error: %v", err)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										76
									
								
								proxy/unix/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								proxy/unix/client.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					package unix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/nadoo/glider/proxy"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proxy.RegisterDialer("unix", NewUnixDialer)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewUnixDialer returns a unix domain socket dialer.
 | 
				
			||||||
 | 
					func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
 | 
				
			||||||
 | 
						return NewUnix(s, d, nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Addr returns forwarder's address.
 | 
				
			||||||
 | 
					func (s *Unix) 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.
 | 
				
			||||||
 | 
					// NOTE: must be the first dialer in a chain
 | 
				
			||||||
 | 
					func (s *Unix) Dial(network, addr string) (net.Conn, error) {
 | 
				
			||||||
 | 
						return net.Dial("unix", s.addr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DialUDP connects to the given address via the proxy.
 | 
				
			||||||
 | 
					// NOTE: must be the first dialer in a chain
 | 
				
			||||||
 | 
					func (s *Unix) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
 | 
				
			||||||
 | 
						laddru := s.addru + "_" + addr
 | 
				
			||||||
 | 
						os.Remove(laddru)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						luaddru, err := net.ResolveUnixAddr("unixgram", laddru)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pc, err := net.ListenUnixgram("unixgram", luaddru)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &PktConn{pc, laddru, luaddru, s.uaddru}, s.uaddru, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PktConn .
 | 
				
			||||||
 | 
					type PktConn struct {
 | 
				
			||||||
 | 
						*net.UnixConn
 | 
				
			||||||
 | 
						addr      string
 | 
				
			||||||
 | 
						uaddr     *net.UnixAddr
 | 
				
			||||||
 | 
						writeAddr *net.UnixAddr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ReadFrom overrides the original function from net.PacketConn.
 | 
				
			||||||
 | 
					func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
 | 
				
			||||||
 | 
						n, _, err := pc.UnixConn.ReadFrom(b)
 | 
				
			||||||
 | 
						return n, pc.uaddr, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WriteTo overrides the original function from net.PacketConn.
 | 
				
			||||||
 | 
					func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
 | 
				
			||||||
 | 
						return pc.UnixConn.WriteTo(b, pc.writeAddr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close overrides the original function from net.PacketConn.
 | 
				
			||||||
 | 
					func (pc *PktConn) Close() error {
 | 
				
			||||||
 | 
						pc.UnixConn.Close()
 | 
				
			||||||
 | 
						os.Remove(pc.addr)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										149
									
								
								proxy/unix/server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								proxy/unix/server.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					package unix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/nadoo/glider/log"
 | 
				
			||||||
 | 
						"github.com/nadoo/glider/proxy"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proxy.RegisterServer("unix", NewUnixServer)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewUnixServer returns a unix domain socket server.
 | 
				
			||||||
 | 
					func NewUnixServer(s string, p proxy.Proxy) (proxy.Server, error) {
 | 
				
			||||||
 | 
						transport := strings.Split(s, ",")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unix, err := NewUnix(transport[0], nil, p)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(transport) > 1 {
 | 
				
			||||||
 | 
							unix.server, err = proxy.ServerFromURL(transport[1], p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return unix, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServe serves requests.
 | 
				
			||||||
 | 
					func (s *Unix) ListenAndServe() {
 | 
				
			||||||
 | 
						go s.ListenAndServeUDP()
 | 
				
			||||||
 | 
						s.ListenAndServeTCP()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServe serves tcp requests.
 | 
				
			||||||
 | 
					func (s *Unix) ListenAndServeTCP() {
 | 
				
			||||||
 | 
						os.Remove(s.addr)
 | 
				
			||||||
 | 
						l, err := net.Listen("unix", s.addr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.F("[unix] failed to listen on %s: %v", s.addr, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.F("[unix] listening on %s", s.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							c, err := l.Accept()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.F("[unix] failed to accept: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							go s.Serve(c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Serve serves requests.
 | 
				
			||||||
 | 
					func (s *Unix) Serve(c net.Conn) {
 | 
				
			||||||
 | 
						if s.server != nil {
 | 
				
			||||||
 | 
							s.server.Serve(c)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer c.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc, dialer, err := s.proxy.Dial("unix", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.F("[unix] %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("[unix] %s <-> %s", c.RemoteAddr(), dialer.Addr())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = proxy.Relay(c, rc); err != nil {
 | 
				
			||||||
 | 
							log.F("[unix] %s <-> %s, relay error: %v", c.RemoteAddr(), dialer.Addr(), err)
 | 
				
			||||||
 | 
							// record remote conn failure only
 | 
				
			||||||
 | 
							if !strings.Contains(err.Error(), s.addr) {
 | 
				
			||||||
 | 
								s.proxy.Record(dialer, false)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServe serves udp requests.
 | 
				
			||||||
 | 
					func (s *Unix) ListenAndServeUDP() {
 | 
				
			||||||
 | 
						os.Remove(s.addru)
 | 
				
			||||||
 | 
						c, err := net.ListenPacket("unixgram", s.addru)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.F("[unix] failed to ListenPacket on %s: %v", s.addru, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer c.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.F("[unix] ListenPacket on %s", s.addru)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var nm sync.Map
 | 
				
			||||||
 | 
						buf := make([]byte, proxy.UDPBufSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							n, lraddr, err := c.ReadFrom(buf)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.F("[unix] read error: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var raddr net.Addr
 | 
				
			||||||
 | 
							var pc net.PacketConn
 | 
				
			||||||
 | 
							var dialer proxy.UDPDialer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							v, ok := nm.Load(lraddr.String())
 | 
				
			||||||
 | 
							if !ok && v == nil {
 | 
				
			||||||
 | 
								pc, dialer, raddr, err = s.proxy.DialUDP("udp", "")
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.F("[unix] 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("[unix] remote write error: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							log.F("[unix] %s <-> %s", s.addru, dialer.Addr())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,11 +1,8 @@
 | 
				
			|||||||
package unix
 | 
					package unix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/nadoo/glider/log"
 | 
						"github.com/nadoo/glider/log"
 | 
				
			||||||
	"github.com/nadoo/glider/proxy"
 | 
						"github.com/nadoo/glider/proxy"
 | 
				
			||||||
@ -15,21 +12,20 @@ import (
 | 
				
			|||||||
type Unix struct {
 | 
					type Unix struct {
 | 
				
			||||||
	dialer proxy.Dialer
 | 
						dialer proxy.Dialer
 | 
				
			||||||
	proxy  proxy.Proxy
 | 
						proxy  proxy.Proxy
 | 
				
			||||||
	addr   string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server proxy.Server
 | 
						server proxy.Server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr  string // addr for tcp
 | 
				
			||||||
 | 
						uaddr *net.UnixAddr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addru  string // addr for udp (datagram)
 | 
				
			||||||
 | 
						uaddru *net.UnixAddr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					// NewUnix returns unix domain socket proxy.
 | 
				
			||||||
	proxy.RegisterServer("unix", NewUnixServer)
 | 
					 | 
				
			||||||
	proxy.RegisterDialer("unix", NewUnixDialer)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewUnix returns  unix fomain socket proxy.
 | 
					 | 
				
			||||||
func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
 | 
					func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
 | 
				
			||||||
	u, err := url.Parse(s)
 | 
						u, err := url.Parse(s)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.F("parse url err: %s", err)
 | 
							log.F("[unix] parse url err: %s", err)
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,101 +33,18 @@ func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
 | 
				
			|||||||
		dialer: d,
 | 
							dialer: d,
 | 
				
			||||||
		proxy:  p,
 | 
							proxy:  p,
 | 
				
			||||||
		addr:   u.Path,
 | 
							addr:   u.Path,
 | 
				
			||||||
 | 
							addru:  u.Path + "u",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return unix, nil
 | 
						unix.uaddr, err = net.ResolveUnixAddr("unixgram", unix.addr)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewUnixDialer returns a unix domain socket dialer.
 | 
					 | 
				
			||||||
func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
 | 
					 | 
				
			||||||
	return NewUnix(s, d, nil)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewUnixServer returns a unix domain socket server.
 | 
					 | 
				
			||||||
func NewUnixServer(s string, p proxy.Proxy) (proxy.Server, error) {
 | 
					 | 
				
			||||||
	transport := strings.Split(s, ",")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unix, err := NewUnix(transport[0], nil, p)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(transport) > 1 {
 | 
						unix.uaddru, err = net.ResolveUnixAddr("unixgram", unix.addru)
 | 
				
			||||||
		unix.server, err = proxy.ServerFromURL(transport[1], p)
 | 
						if err != nil {
 | 
				
			||||||
		if err != nil {
 | 
							return nil, err
 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return unix, nil
 | 
						return unix, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenAndServe serves requests.
 | 
					 | 
				
			||||||
func (s *Unix) ListenAndServe() {
 | 
					 | 
				
			||||||
	os.Remove(s.addr)
 | 
					 | 
				
			||||||
	l, err := net.Listen("unix", s.addr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.F("[unix] failed to listen on %s: %v", s.addr, err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer l.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log.F("[unix] listening on %s", s.addr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		c, err := l.Accept()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			log.F("[unix] failed to accept: %v", err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		go s.Serve(c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Serve serves requests.
 | 
					 | 
				
			||||||
func (s *Unix) Serve(c net.Conn) {
 | 
					 | 
				
			||||||
	if s.server != nil {
 | 
					 | 
				
			||||||
		s.server.Serve(c)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defer c.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rc, dialer, err := s.proxy.Dial("unix", "")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.F("[unix] %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("[unix] %s <-> %s", c.RemoteAddr(), dialer.Addr())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = proxy.Relay(c, rc); err != nil {
 | 
					 | 
				
			||||||
		log.F("[unix] %s <-> %s, relay error: %v", c.RemoteAddr(), dialer.Addr(), err)
 | 
					 | 
				
			||||||
		// record remote conn failure only
 | 
					 | 
				
			||||||
		if !strings.Contains(err.Error(), s.addr) {
 | 
					 | 
				
			||||||
			s.proxy.Record(dialer, false)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Addr returns forwarder's address.
 | 
					 | 
				
			||||||
func (s *Unix) 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 *Unix) Dial(network, addr string) (net.Conn, error) {
 | 
					 | 
				
			||||||
	// NOTE: must be the first dialer in a chain
 | 
					 | 
				
			||||||
	return net.Dial("unix", s.addr)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialUDP connects to the given address via the proxy.
 | 
					 | 
				
			||||||
func (s *Unix) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
 | 
					 | 
				
			||||||
	return nil, nil, errors.New("unix domain socket client does not support udp now")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -214,7 +214,7 @@ func (p *FwdrGroup) Check() {
 | 
				
			|||||||
	case "file":
 | 
						case "file":
 | 
				
			||||||
		checker = newFileChecker(u.Host + u.Path)
 | 
							checker = newFileChecker(u.Host + u.Path)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		log.F("[group] invalid check config `%s`, disable health checking", p.config.Check)
 | 
							log.F("[group] check config `%s`, disable health checking", p.config.Check)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user