You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.1 KiB

4 years ago
package tunnel
import (
"errors"
4 years ago
"io"
"net"
"sync"
"time"
"github.com/xjasonlyu/tun2socks/v2/common/pool"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"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"
4 years ago
)
// _tcpWaitTimeout is the default timeout to wait after closing each TCP connection.
var _tcpWaitTimeout = 5 * time.Second
func SetTCPWaitTimeout(t time.Duration) {
_tcpWaitTimeout = t
}
4 years ago
func handleTCPConn(localConn adapter.TCPConn) {
4 years ago
defer localConn.Close()
id := localConn.ID()
metadata := &M.Metadata{
Network: M.TCP,
SrcIP: net.IP(id.RemoteAddress),
SrcPort: id.RemotePort,
DstIP: net.IP(id.LocalAddress),
DstPort: id.LocalPort,
}
4 years ago
targetConn, err := proxy.Dial(metadata)
if err != nil {
log.Warnf("[TCP] dial %s: %v", metadata.DestinationAddress(), err)
4 years ago
return
}
metadata.MidIP, metadata.MidPort = parseAddr(targetConn.LocalAddr())
4 years ago
targetConn = statistic.DefaultTCPTracker(targetConn, metadata)
4 years ago
defer targetConn.Close()
4 years ago
log.Infof("[TCP] %s <-> %s", metadata.SourceAddress(), metadata.DestinationAddress())
if err = relay(localConn, targetConn); err != nil {
log.Debugf("[TCP] %s <-> %s: %v", metadata.SourceAddress(), metadata.DestinationAddress(), err)
}
4 years ago
}
// relay copies between left and right bidirectionally.
func relay(left, right net.Conn) error {
4 years ago
wg := sync.WaitGroup{}
4 years ago
wg.Add(2)
var leftErr, rightErr error
4 years ago
go func() {
defer wg.Done()
if err := copyBuffer(right, left); err != nil {
leftErr = errors.Join(leftErr, err)
}
right.SetReadDeadline(time.Now().Add(_tcpWaitTimeout))
4 years ago
}()
go func() {
defer wg.Done()
if err := copyBuffer(left, right); err != nil {
rightErr = errors.Join(rightErr, err)
}
left.SetReadDeadline(time.Now().Add(_tcpWaitTimeout))
4 years ago
}()
wg.Wait()
return errors.Join(leftErr, rightErr)
4 years ago
}
func copyBuffer(dst io.Writer, src io.Reader) error {
4 years ago
buf := pool.Get(pool.RelayBufferSize)
4 years ago
defer pool.Put(buf)
_, err := io.CopyBuffer(dst, src, buf)
return err
4 years ago
}