kubenetworks/kubevpn

View on GitHub
pkg/core/route.go

Summary

Maintainability
A
2 hrs
Test Coverage
package core

import (
    "fmt"
    "net"
    "os"
    "strings"
    "sync"

    "github.com/containernetworking/cni/pkg/types"
    "github.com/pkg/errors"
    log "github.com/sirupsen/logrus"

    "github.com/wencaiwulue/kubevpn/v2/pkg/config"
    "github.com/wencaiwulue/kubevpn/v2/pkg/tun"
)

var (
    // RouteMapTCP map[srcIP]net.Conn Globe route table for inner ip
    RouteMapTCP = &sync.Map{}
    // TCPPacketChan tcp connects
    TCPPacketChan = make(chan *datagramPacket, MaxSize)
)

type TCPUDPacket struct {
    data *datagramPacket
}

// Route example:
// -L "tcp://:10800" -L "tun://:8422?net=223.254.0.100/16"
// -L "tun:/10.233.24.133:8422?net=223.254.0.102/16&route=223.254.0.0/16"
// -L "tun:/127.0.0.1:8422?net=223.254.0.102/16&route=223.254.0.0/16,10.233.0.0/16" -F "tcp://127.0.0.1:10800"
type Route struct {
    ServeNodes []string // -L tun
    ChainNode  string   // -F tcp
    Retries    int
}

func (r *Route) parseChain() (*Chain, error) {
    node, err := parseChainNode(r.ChainNode)
    if err != nil {
        return nil, err
    }
    return NewChain(r.Retries, node), nil
}

func parseChainNode(ns string) (*Node, error) {
    node, err := ParseNode(ns)
    if err != nil {
        return nil, err
    }
    node.Client = &Client{
        Connector:   UDPOverTCPTunnelConnector(),
        Transporter: TCPTransporter(),
    }
    return node, nil
}

func (r *Route) GenerateServers() ([]Server, error) {
    chain, err := r.parseChain()
    if err != nil && !errors.Is(err, ErrorInvalidNode) {
        log.Errorf("Failed to parse chain: %v", err)
        return nil, err
    }

    servers := make([]Server, 0, len(r.ServeNodes))
    for _, serveNode := range r.ServeNodes {
        var node *Node
        node, err = ParseNode(serveNode)
        if err != nil {
            log.Errorf("Failed to parse node %s: %v", serveNode, err)
            return nil, err
        }

        var ln net.Listener
        var handler Handler

        switch node.Protocol {
        case "tun":
            handler = TunHandler(chain, node)
            ln, err = tun.Listener(tun.Config{
                Name:    node.Get("name"),
                Addr:    node.Get("net"),
                Addr6:   os.Getenv(config.EnvInboundPodTunIPv6),
                MTU:     node.GetInt("mtu"),
                Routes:  parseIPRoutes(node.Get("route")),
                Gateway: node.Get("gw"),
            })
            if err != nil {
                log.Errorf("Failed to create tun listener: %v", err)
                return nil, err
            }
        case "tcp":
            handler = TCPHandler()
            ln, err = TCPListener(node.Addr)
            if err != nil {
                log.Errorf("Failed to create tcp listener: %v", err)
                return nil, err
            }
        case "gtcp":
            handler = GvisorTCPHandler()
            ln, err = GvisorTCPListener(node.Addr)
            if err != nil {
                log.Errorf("Failed to create gvisor tcp listener: %v", err)
                return nil, err
            }
        case "gudp":
            handler = GvisorUDPHandler()
            ln, err = GvisorUDPListener(node.Addr)
            if err != nil {
                log.Errorf("Failed to create gvisor udp listener: %v", err)
                return nil, err
            }
        default:
            log.Errorf("Not support protocol %s", node.Protocol)
            return nil, fmt.Errorf("not support protocol %s", node.Protocol)
        }
        servers = append(servers, Server{Listener: ln, Handler: handler})
    }
    return servers, nil
}

func parseIPRoutes(routeStringList string) (routes []types.Route) {
    if len(routeStringList) == 0 {
        return
    }

    routeList := strings.Split(routeStringList, ",")
    for _, route := range routeList {
        if _, ipNet, _ := net.ParseCIDR(strings.TrimSpace(route)); ipNet != nil {
            routes = append(routes, types.Route{Dst: *ipNet})
        }
    }
    return
}