mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +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