Files
tun2socks/tunnel/tcp.go
2022-02-05 16:51:17 +08:00

81 lines
1.8 KiB
Go

package tunnel
import (
"io"
"net"
"sync"
"time"
"github.com/xjasonlyu/tun2socks/v2/common/pool"
"github.com/xjasonlyu/tun2socks/v2/core"
"github.com/xjasonlyu/tun2socks/v2/log"
M "github.com/xjasonlyu/tun2socks/v2/metadata"
"github.com/xjasonlyu/tun2socks/v2/proxy"
"github.com/xjasonlyu/tun2socks/v2/tunnel/statistic"
)
const (
tcpWaitTimeout = 5 * time.Second
)
func newTCPTracker(conn net.Conn, metadata *M.Metadata) net.Conn {
return statistic.NewTCPTracker(conn, metadata, statistic.DefaultManager)
}
func handleTCPConn(localConn core.TCPConn) {
defer localConn.Close()
var (
srcIP, srcPort = parseAddr(localConn.RemoteAddr())
dstIP, dstPort = parseAddr(localConn.LocalAddr())
)
metadata := &M.Metadata{
Network: M.TCP,
SrcIP: srcIP,
SrcPort: srcPort,
DstIP: dstIP,
DstPort: dstPort,
}
targetConn, err := proxy.Dial(metadata)
if err != nil {
log.Warnf("[TCP] dial %s error: %v", metadata.DestinationAddress(), err)
return
}
metadata.MidIP, metadata.MidPort = parseAddr(targetConn.LocalAddr())
targetConn = newTCPTracker(targetConn, metadata)
defer targetConn.Close()
log.Infof("[TCP] %s <-> %s", metadata.SourceAddress(), metadata.DestinationAddress())
relay(localConn, targetConn) /* relay connections */
}
// relay copies between left and right bidirectionally.
func relay(left, right net.Conn) {
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
_ = copyBuffer(right, left) /* ignore error */
right.SetReadDeadline(time.Now().Add(tcpWaitTimeout))
}()
go func() {
defer wg.Done()
_ = copyBuffer(left, right) /* ignore error */
left.SetReadDeadline(time.Now().Add(tcpWaitTimeout))
}()
wg.Wait()
}
func copyBuffer(dst io.Writer, src io.Reader) error {
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
_, err := io.CopyBuffer(dst, src, buf)
return err
}