Files
tun2socks/proxy/tcp.go
Jason 78b65e6a83 Revert "update proxy session"
This reverts commit 7a77dea691.
2019-08-22 13:39:57 +08:00

124 lines
2.6 KiB
Go

package proxy
import (
"io"
"net"
"strconv"
"sync"
"time"
"github.com/xjasonlyu/tun2socks/common/lsof"
"github.com/xjasonlyu/tun2socks/common/pool"
"github.com/xjasonlyu/tun2socks/core"
"github.com/xjasonlyu/tun2socks/log"
S "github.com/xjasonlyu/tun2socks/component/session"
)
type tcpHandler struct {
proxyHost string
proxyPort int
}
func NewTCPHandler(proxyHost string, proxyPort int) core.TCPConnHandler {
return &tcpHandler{
proxyHost: proxyHost,
proxyPort: proxyPort,
}
}
func (h *tcpHandler) relay(localConn, remoteConn net.Conn) {
var once sync.Once
closeOnce := func() {
once.Do(func() {
localConn.Close()
remoteConn.Close()
})
}
// Close
defer closeOnce()
// WaitGroup
var wg sync.WaitGroup
wg.Add(1)
// Up Link
go func() {
buf := pool.BufPool.Get().([]byte)
defer pool.BufPool.Put(buf[:cap(buf)])
if _, err := io.CopyBuffer(remoteConn, localConn, buf); err != nil {
closeOnce()
} else {
localConn.SetDeadline(time.Now())
remoteConn.SetDeadline(time.Now())
tcpCloseRead(remoteConn)
}
wg.Done()
}()
// Down Link
buf := pool.BufPool.Get().([]byte)
if _, err := io.CopyBuffer(localConn, remoteConn, buf); err != nil {
closeOnce()
} else {
localConn.SetDeadline(time.Now())
remoteConn.SetDeadline(time.Now())
tcpCloseRead(localConn)
}
pool.BufPool.Put(buf[:cap(buf)])
wg.Wait() // Wait for Up Link done
// Remove session
removeSession(localConn)
}
func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error {
// Alias
var localConn = conn
// Lookup fakeDNS host record
targetHost, err := lookupHost(target)
if err != nil {
log.Warnf("lookup target host: %v", err)
return err
}
proxyAddr := net.JoinHostPort(h.proxyHost, strconv.Itoa(h.proxyPort))
targetAddr := net.JoinHostPort(targetHost, strconv.Itoa(target.Port))
// Dial
remoteConn, err := dial(proxyAddr, targetAddr)
if err != nil {
log.Infof("Dial: %v", err)
return err
}
// Get name of the process
var process = lsof.GetProcessName(localConn.LocalAddr())
if monitor != nil {
session := &S.Session{
Process: process,
Network: localConn.LocalAddr().Network(),
DialerAddr: remoteConn.LocalAddr().String(),
ClientAddr: localConn.LocalAddr().String(),
TargetAddr: targetAddr,
UploadBytes: 0,
DownloadBytes: 0,
SessionStart: time.Now(),
}
addSession(localConn, session)
remoteConn = &S.Conn{Session: session, Conn: remoteConn}
}
// Set keepalive
tcpKeepAlive(localConn)
tcpKeepAlive(remoteConn)
// Relay connections
go h.relay(localConn, remoteConn)
log.Access(process, "proxy", "tcp", localConn.LocalAddr().String(), targetAddr)
return nil
}