Files
kubevpn/pkg/core/tcphandler.go
2023-02-28 19:52:28 +08:00

150 lines
3.6 KiB
Go

package core
import (
"context"
"errors"
"net"
"time"
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/pkg/config"
)
type fakeUDPTunnelConnector struct {
}
func UDPOverTCPTunnelConnector() Connector {
return &fakeUDPTunnelConnector{}
}
func (c *fakeUDPTunnelConnector) ConnectContext(ctx context.Context, conn net.Conn) (net.Conn, error) {
//defer conn.SetDeadline(time.Time{})
switch con := conn.(type) {
case *net.TCPConn:
err := con.SetNoDelay(true)
if err != nil {
return nil, err
}
con.SetKeepAlive(true)
con.SetKeepAlivePeriod(30 * time.Second)
}
return newFakeUDPTunnelConnOverTCP(ctx, conn)
}
type fakeUdpHandler struct {
nat *NAT
}
func TCPHandler() Handler {
return &fakeUdpHandler{
nat: RouteNAT,
}
}
var Server8422, _ = net.ResolveUDPAddr("udp", "127.0.0.1:8422")
func (h *fakeUdpHandler) Handle(ctx context.Context, tcpConn net.Conn) {
defer tcpConn.Close()
log.Debugf("[tcpserver] %s -> %s\n", tcpConn.RemoteAddr(), tcpConn.LocalAddr())
udpConn, err := net.DialUDP("udp", nil, Server8422)
if err != nil {
log.Errorf("[tcpserver] udp-tun %s -> %s : %s", tcpConn.RemoteAddr(), udpConn.LocalAddr(), err)
return
}
defer udpConn.Close()
defer func(addr net.Addr) {
n := h.nat.RemoveAddr(addr)
log.Debugf("delete addr %s from globle route, deleted count %d", addr, n)
}(udpConn.LocalAddr())
log.Debugf("[tcpserver] udp-tun %s <-> %s", tcpConn.RemoteAddr(), udpConn.LocalAddr())
errChan := make(chan error, 2)
go func() {
b := config.LPool.Get().([]byte)
defer config.LPool.Put(b[:])
for {
dgram, err := readDatagramPacket(tcpConn, b[:])
if err != nil {
log.Debugf("[udp-tun] %s -> 0 : %v", tcpConn.RemoteAddr(), err)
errChan <- err
return
}
if _, err = udpConn.Write(dgram.Data); err != nil {
log.Debugf("[tcpserver] udp-tun %s -> %s : %s", tcpConn.RemoteAddr(), Server8422, err)
errChan <- err
return
}
log.Debugf("[tcpserver] udp-tun %s >>> %s length: %d", tcpConn.RemoteAddr(), Server8422, len(dgram.Data))
}
}()
go func() {
b := config.LPool.Get().([]byte)
defer config.LPool.Put(b[:])
for {
n, err := udpConn.Read(b[:])
if err != nil {
log.Debugf("[udp-tun] %s : %s", tcpConn.RemoteAddr(), err)
errChan <- err
return
}
// pipe from peer to tunnel
dgram := newDatagramPacket(b[:n])
if err = dgram.Write(tcpConn); err != nil {
log.Debugf("[tcpserver] udp-tun %s <- %s : %s", tcpConn.RemoteAddr(), dgram.Addr(), err)
errChan <- err
return
}
log.Debugf("[tcpserver] udp-tun %s <<< %s length: %d", tcpConn.RemoteAddr(), dgram.Addr(), len(dgram.Data))
}
}()
err = <-errChan
if err != nil {
log.Error(err)
}
log.Debugf("[tcpserver] udp-tun %s >-< %s", tcpConn.RemoteAddr(), udpConn.LocalAddr())
return
}
// fake udp connect over tcp
type fakeUDPTunnelConn struct {
// tcp connection
net.Conn
ctx context.Context
}
func newFakeUDPTunnelConnOverTCP(ctx context.Context, conn net.Conn) (net.Conn, error) {
return &fakeUDPTunnelConn{ctx: ctx, Conn: conn}, nil
}
func (c *fakeUDPTunnelConn) ReadFrom(b []byte) (int, net.Addr, error) {
select {
case <-c.ctx.Done():
return 0, nil, errors.New("closed connection")
default:
dgram, err := readDatagramPacket(c.Conn, b)
if err != nil {
return 0, nil, err
}
return int(dgram.DataLength), dgram.Addr(), nil
}
}
func (c *fakeUDPTunnelConn) WriteTo(b []byte, _ net.Addr) (int, error) {
dgram := newDatagramPacket(b)
if err := dgram.Write(c.Conn); err != nil {
return 0, err
}
return len(b), nil
}
func (c *fakeUDPTunnelConn) Close() error {
return c.Conn.Close()
}