Files
kubevpn/pkg/core/gvisorlocaltcpforwarder.go
naison b3b13fce86 refactor: rename cmd dev to run (#684)
* refactor: code

* refactor: optimize code
2025-08-04 23:00:38 +08:00

88 lines
2.5 KiB
Go

package core
import (
"context"
"fmt"
"io"
"net"
"time"
"github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
)
func LocalTCPForwarder(ctx context.Context, s *stack.Stack) func(stack.TransportEndpointID, *stack.PacketBuffer) bool {
return tcp.NewForwarder(s, 0, 100000, func(request *tcp.ForwarderRequest) {
ctx = context.Background()
id := request.ID()
plog.G(ctx).Infof("[TUN-TCP] LocalPort: %d, LocalAddress: %s, RemotePort: %d, RemoteAddress %s",
id.LocalPort, id.LocalAddress.String(), id.RemotePort, id.RemoteAddress.String(),
)
w := &waiter.Queue{}
endpoint, tErr := request.CreateEndpoint(w)
if tErr != nil {
plog.G(ctx).Errorf("[TUN-TCP] Failed to create endpoint: %v", tErr)
request.Complete(true)
return
}
defer endpoint.Close()
conn := gonet.NewTCPConn(w, endpoint)
defer conn.Close()
var err error
defer func() {
if err != nil && !errors.Is(err, io.EOF) {
request.Complete(true)
} else {
request.Complete(false)
}
}()
// 2, dial proxy
var host string
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) {
host = "127.0.0.1"
network = "tcp4"
} else {
host = net.IPv6loopback.String()
network = "tcp6"
}
port := fmt.Sprintf("%d", id.LocalPort)
var d = net.Dialer{Timeout: time.Second * 5}
var remote net.Conn
remote, err = d.DialContext(ctx, network, net.JoinHostPort(host, port))
if err != nil {
plog.G(ctx).Errorf("[TUN-TCP] Failed to connect addr %s: %v", net.JoinHostPort(host, port), err)
return
}
defer remote.Close()
errChan := make(chan error, 2)
go func() {
buf := config.LPool.Get().([]byte)[:]
defer config.LPool.Put(buf[:])
written, err2 := io.CopyBuffer(remote, conn, buf)
plog.G(ctx).Infof("[TUN-TCP] Write length %d data to remote", written)
errChan <- err2
}()
go func() {
buf := config.LPool.Get().([]byte)[:]
defer config.LPool.Put(buf[:])
written, err2 := io.CopyBuffer(conn, remote, buf)
plog.G(ctx).Infof("[TUN-TCP] Read length %d data from remote", written)
errChan <- err2
}()
err = <-errChan
if err != nil && !errors.Is(err, io.EOF) {
plog.G(ctx).Errorf("[TUN-TCP] Disconnect: %s >-<: %s: %v", conn.LocalAddr(), remote.RemoteAddr(), err)
}
}).HandlePacket
}