mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +08:00 
			
		
		
		
	tproxy: use goroutine to serve sessions
This commit is contained in:
		
							parent
							
								
									d615dc087e
								
							
						
					
					
						commit
						b38f8a8761
					
				@ -375,7 +375,7 @@ Examples:
 | 
				
			|||||||
  - service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
 | 
					  - service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
 | 
				
			||||||
  - e.g.:
 | 
					  - e.g.:
 | 
				
			||||||
  - service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
 | 
					  - service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
 | 
				
			||||||
  - service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:34:9e:25:01=192.168.2.101,fc:23:34:9e:25:02=192.168.2.102
 | 
					  - service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:34:9e:25:01=192.168.2.101
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Linux Service
 | 
					## Linux Service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ 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"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,6 +21,9 @@ func init() {
 | 
				
			|||||||
	proxy.RegisterServer("tproxy", NewTProxyServer)
 | 
						proxy.RegisterServer("tproxy", NewTProxyServer)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// nat mapping
 | 
				
			||||||
 | 
					var nm sync.Map
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewTProxy returns a tproxy.
 | 
					// NewTProxy returns a tproxy.
 | 
				
			||||||
func NewTProxy(s string, p proxy.Proxy) (*TProxy, error) {
 | 
					func NewTProxy(s string, p proxy.Proxy) (*TProxy, error) {
 | 
				
			||||||
	u, err := url.Parse(s)
 | 
						u, err := url.Parse(s)
 | 
				
			||||||
@ -47,12 +51,17 @@ func (s *TProxy) ListenAndServe() {
 | 
				
			|||||||
	s.ListenAndServeUDP()
 | 
						s.ListenAndServeUDP()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServeTCP .
 | 
					// ListenAndServeTCP listens and serves tcp.
 | 
				
			||||||
func (s *TProxy) ListenAndServeTCP() {
 | 
					func (s *TProxy) ListenAndServeTCP() {
 | 
				
			||||||
	log.F("[tproxy] tcp mode not supported now, please use 'redir' instead")
 | 
						log.F("[tproxy] tcp mode not supported now, please use 'redir' instead")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServeUDP .
 | 
					// Serve serves tcp conn.
 | 
				
			||||||
 | 
					func (s *TProxy) Serve(c net.Conn) {
 | 
				
			||||||
 | 
						log.F("[tproxy] func Serve: can not be called directly")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServeUDP listens and serves udp.
 | 
				
			||||||
func (s *TProxy) ListenAndServeUDP() {
 | 
					func (s *TProxy) ListenAndServeUDP() {
 | 
				
			||||||
	laddr, err := net.ResolveUDPAddr("udp", s.addr)
 | 
						laddr, err := net.ResolveUDPAddr("udp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -69,66 +78,65 @@ func (s *TProxy) ListenAndServeUDP() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	log.F("[tproxyu] listening UDP on %s", s.addr)
 | 
						log.F("[tproxyu] listening UDP on %s", s.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var nm sync.Map
 | 
					 | 
				
			||||||
	buf := make([]byte, proxy.UDPBufSize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		n, lraddr, dstAddr, err := ReadFromUDP(lc, buf)
 | 
							buf := pool.GetBuffer(proxy.UDPBufSize)
 | 
				
			||||||
 | 
							n, srcAddr, dstAddr, err := ReadFromUDP(lc, buf)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.F("[tproxyu] read error: %v", err)
 | 
								log.F("[tproxyu] read error: %v", err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var session *natEntry
 | 
							var session *Session
 | 
				
			||||||
		sessionKey := lraddr.String()
 | 
							sessionKey := srcAddr.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		v, ok := nm.Load(sessionKey)
 | 
							v, ok := nm.Load(sessionKey)
 | 
				
			||||||
		if !ok && v == nil {
 | 
							if !ok && v == nil {
 | 
				
			||||||
			pc, dialer, writeTo, err := s.proxy.DialUDP("udp", dstAddr.String())
 | 
								session = &Session{sessionKey, srcAddr, dstAddr, make(chan []byte, 32)}
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.F("[tproxyu] dial to %s error: %v", dstAddr, err)
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			lpc, err := ListenPacket(dstAddr)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.F("[tproxyu] ListenPacket as %s error: %v", dstAddr, err)
 | 
					 | 
				
			||||||
				pc.Close()
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			session = newNatEntry(pc, writeTo)
 | 
					 | 
				
			||||||
			nm.Store(sessionKey, session)
 | 
								nm.Store(sessionKey, session)
 | 
				
			||||||
 | 
								go s.ServeSession(session)
 | 
				
			||||||
			go func(lc net.PacketConn, pc net.PacketConn, lraddr *net.UDPAddr, key string) {
 | 
					 | 
				
			||||||
				proxy.RelayUDP(lc, lraddr, pc, 2*time.Minute)
 | 
					 | 
				
			||||||
				pc.Close()
 | 
					 | 
				
			||||||
				nm.Delete(key)
 | 
					 | 
				
			||||||
			}(lpc, pc, lraddr, sessionKey)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			log.F("[tproxyu] %s <-> %s via %s", lraddr, dstAddr, dialer.Addr())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			session = v.(*natEntry)
 | 
								session = v.(*Session)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							session.msgQueue <- buf[:n]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err = session.WriteTo(buf[:n], session.writeTo)
 | 
					// ServeSession serves a udp session.
 | 
				
			||||||
 | 
					func (s *TProxy) ServeSession(session *Session) {
 | 
				
			||||||
 | 
						dstPC, dialer, writeTo, err := s.proxy.DialUDP("udp", session.dst.String())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
			log.F("[tproxyu] writeTo %s error: %v", session.writeTo, err)
 | 
							log.F("[tproxyu] dial to %s error: %v", session.dst, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer dstPC.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						srcPC, err := ListenPacket(session.dst)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.F("[tproxyu] ListenPacket as %s error: %v", session.dst, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer srcPC.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.F("[tproxyu] %s <-> %s via %s", session.src, session.dst, dialer.Addr())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							proxy.RelayUDP(srcPC, session.src, dstPC, 2*time.Minute)
 | 
				
			||||||
 | 
							nm.Delete(session.key)
 | 
				
			||||||
 | 
							close(session.msgQueue)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for data := range session.msgQueue {
 | 
				
			||||||
 | 
							_, err = dstPC.WriteTo(data, writeTo)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.F("[tproxyu] writeTo %s error: %v", writeTo, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pool.PutBuffer(data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Serve .
 | 
					// Session is a udp session
 | 
				
			||||||
func (s *TProxy) Serve(c net.Conn) {
 | 
					type Session struct {
 | 
				
			||||||
	log.F("[tproxy] func Serve: can not be called directly")
 | 
						key      string
 | 
				
			||||||
}
 | 
						src, dst *net.UDPAddr
 | 
				
			||||||
 | 
						msgQueue chan []byte
 | 
				
			||||||
type natEntry struct {
 | 
					 | 
				
			||||||
	net.PacketConn
 | 
					 | 
				
			||||||
	writeTo net.Addr
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newNatEntry(pc net.PacketConn, writeTo net.Addr) *natEntry {
 | 
					 | 
				
			||||||
	return &natEntry{PacketConn: pc, writeTo: writeTo}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user