Files
tun2socks/proxy/tcp.go
2019-08-13 21:31:16 +08:00

86 lines
2.1 KiB
Go

package proxy
import (
"net"
"strconv"
"time"
"github.com/xjasonlyu/tun2socks/common/dns"
"github.com/xjasonlyu/tun2socks/common/log"
"github.com/xjasonlyu/tun2socks/common/lsof"
"github.com/xjasonlyu/tun2socks/common/stats"
"github.com/xjasonlyu/tun2socks/core"
"github.com/xjasonlyu/tun2socks/proxy/socks"
)
type tcpHandler struct {
proxyHost string
proxyPort int
fakeDns dns.FakeDns
sessionStater stats.SessionStater
}
func NewTCPHandler(proxyHost string, proxyPort int, fakeDns dns.FakeDns, sessionStater stats.SessionStater) core.TCPConnHandler {
return &tcpHandler{
proxyHost: proxyHost,
proxyPort: proxyPort,
fakeDns: fakeDns,
sessionStater: sessionStater,
}
}
func (h *tcpHandler) Handle(localConn net.Conn, target *net.TCPAddr) error {
// Replace with a domain name if target address IP is a fake IP.
var targetHost = target.IP.String()
if h.fakeDns != nil {
if host, exist := h.fakeDns.IPToHost(target.IP); exist {
targetHost = host
}
}
proxyAddr := net.JoinHostPort(h.proxyHost, strconv.Itoa(h.proxyPort))
targetAddr := net.JoinHostPort(targetHost, strconv.Itoa(target.Port))
// Dial
remoteConn, err := socks.Dial(proxyAddr, targetAddr)
if err != nil {
log.Warnf("Dial %v error: %v", proxyAddr, err)
return err
}
// Get name of the process.
var process = lsof.GetProcessName(localConn.LocalAddr())
if h.sessionStater != nil {
sess := &stats.Session{
ProcessName: process,
Network: localConn.LocalAddr().Network(),
DialerAddr: remoteConn.LocalAddr().String(),
ClientAddr: localConn.LocalAddr().String(),
TargetAddr: targetAddr,
UploadBytes: 0,
DownloadBytes: 0,
SessionStart: time.Now(),
}
h.sessionStater.AddSession(localConn, sess)
remoteConn = stats.NewSessionConn(remoteConn, sess)
}
// set keepalive
tcpKeepAlive(localConn)
tcpKeepAlive(remoteConn)
go func() {
// relay connections
tcpRelay(localConn, remoteConn)
// remove session
if h.sessionStater != nil {
h.sessionStater.RemoveSession(localConn)
}
}()
log.Access(process, "proxy", target.Network(), localConn.LocalAddr().String(), targetAddr)
return nil
}