Browse Source

update echo & redirect

pull/15/head
Jason 5 years ago
parent
commit
fd3c094d3b
  1. 8
      proxy/echo/tcp.go
  2. 6
      proxy/echo/udp.go
  3. 43
      proxy/redirect/tcp.go
  4. 16
      proxy/redirect/udp.go

8
proxy/echo/tcp.go

@ -16,11 +16,11 @@ func NewTCPHandler() core.TCPConnHandler {
return &tcpHandler{} return &tcpHandler{}
} }
func (h *tcpHandler) echoBack(conn net.Conn) { func (h *tcpHandler) echoBack(localConn net.Conn) {
io.Copy(conn, conn) io.Copy(localConn, localConn)
} }
func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { func (h *tcpHandler) Handle(localConn net.Conn, target *net.TCPAddr) error {
go h.echoBack(conn) go h.echoBack(localConn)
return nil return nil
} }

6
proxy/echo/udp.go

@ -14,15 +14,15 @@ func NewUDPHandler() core.UDPConnHandler {
return &udpHandler{} return &udpHandler{}
} }
func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error { func (h *udpHandler) Connect(localConn core.UDPConn, target *net.UDPAddr) error {
return nil return nil
} }
func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) error { func (h *udpHandler) ReceiveTo(localConn core.UDPConn, data []byte, addr *net.UDPAddr) error {
// Dispatch to another goroutine, otherwise will result in deadlock. // Dispatch to another goroutine, otherwise will result in deadlock.
payload := append([]byte(nil), data...) payload := append([]byte(nil), data...)
go func(b []byte) { go func(b []byte) {
_, err := conn.WriteFrom(b, addr) _, err := localConn.WriteFrom(b, addr)
if err != nil { if err != nil {
log.Warnf("failed to echo back data: %v", err) log.Warnf("failed to echo back data: %v", err)
} }

43
proxy/redirect/tcp.go

@ -1,14 +1,11 @@
package redirect package redirect
import ( import (
"io"
"net" "net"
"sync"
"time"
"github.com/xjasonlyu/tun2socks/common/log" "github.com/xjasonlyu/tun2socks/common/log"
"github.com/xjasonlyu/tun2socks/common/pool"
"github.com/xjasonlyu/tun2socks/core" "github.com/xjasonlyu/tun2socks/core"
. "github.com/xjasonlyu/tun2socks/proxy"
) )
// To do a benchmark using iperf3 locally, you may follow these steps: // To do a benchmark using iperf3 locally, you may follow these steps:
@ -38,43 +35,17 @@ func NewTCPHandler(target string) core.TCPConnHandler {
return &tcpHandler{target: target} return &tcpHandler{target: target}
} }
func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { func (h *tcpHandler) Handle(localConn net.Conn, target *net.TCPAddr) error {
c, err := net.Dial("tcp", h.target) remoteConn, err := net.Dial("tcp", h.target)
if err != nil { if err != nil {
return err return err
} }
// WaitGroup // set keepalive
var wg sync.WaitGroup TCPKeepAlive(localConn)
wg.Add(2) TCPKeepAlive(remoteConn)
var once sync.Once go TCPRelay(localConn, remoteConn)
relayCopy := func(dst, src net.Conn) {
closeOnce := func() {
once.Do(func() {
src.Close()
dst.Close()
})
}
// Close
defer closeOnce()
buf := pool.BufPool.Get().([]byte)
defer pool.BufPool.Put(buf[:cap(buf)])
if _, err := io.CopyBuffer(dst, src, buf); err != nil {
closeOnce()
} else {
src.SetDeadline(time.Now())
dst.SetDeadline(time.Now())
}
wg.Done()
wg.Wait() // Wait for another goroutine
}
go relayCopy(conn, c)
go relayCopy(c, conn)
log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String()) log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String())
return nil return nil

16
proxy/redirect/udp.go

@ -52,7 +52,7 @@ func (h *udpHandler) fetchUDPInput(conn core.UDPConn, pc *net.UDPConn) {
} }
} }
func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error { func (h *udpHandler) Connect(localConn core.UDPConn, target *net.UDPAddr) error {
bindAddr := &net.UDPAddr{IP: nil, Port: 0} bindAddr := &net.UDPAddr{IP: nil, Port: 0}
pc, err := net.ListenUDP("udp", bindAddr) pc, err := net.ListenUDP("udp", bindAddr)
if err != nil { if err != nil {
@ -61,24 +61,24 @@ func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error {
} }
targetAddr, _ := net.ResolveUDPAddr("udp", h.target) targetAddr, _ := net.ResolveUDPAddr("udp", h.target)
h.remoteAddrMap.Store(conn, targetAddr) h.remoteAddrMap.Store(localConn, targetAddr)
h.remoteUDPConnMap.Store(conn, pc) h.remoteUDPConnMap.Store(localConn, pc)
go h.fetchUDPInput(conn, pc) go h.fetchUDPInput(localConn, pc)
log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String()) log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String())
return nil return nil
} }
func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) error { func (h *udpHandler) ReceiveTo(localConn core.UDPConn, data []byte, addr *net.UDPAddr) error {
var pc *net.UDPConn var pc *net.UDPConn
var targetAddr *net.UDPAddr var targetAddr *net.UDPAddr
if value, ok := h.remoteAddrMap.Load(conn); ok { if value, ok := h.remoteAddrMap.Load(localConn); ok {
targetAddr = value.(*net.UDPAddr) targetAddr = value.(*net.UDPAddr)
} }
if value, ok := h.remoteUDPConnMap.Load(conn); ok { if value, ok := h.remoteUDPConnMap.Load(localConn); ok {
pc = value.(*net.UDPConn) pc = value.(*net.UDPConn)
} }
@ -90,7 +90,7 @@ func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr
} }
return nil return nil
} else { } else {
return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", conn.LocalAddr(), addr)) return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", localConn.LocalAddr(), addr))
} }
} }

Loading…
Cancel
Save