mirror of
https://github.com/openziti/zrok.git
synced 2024-12-22 23:02:52 +01:00
implement VPN backend
This commit is contained in:
parent
67851c64af
commit
b7f046abf5
@ -2,15 +2,19 @@ package vpn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/net-byte/vtun/common/config"
|
||||
"github.com/net-byte/vtun/tun"
|
||||
_ "github.com/net-byte/vtun/tun"
|
||||
"github.com/net-byte/water"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
cmap "github.com/orcaman/concurrent-map/v2"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/songgao/water/waterutil"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -21,11 +25,20 @@ type BackendConfig struct {
|
||||
RequestsChan chan *endpoints.Request
|
||||
}
|
||||
|
||||
type client struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
cfg *BackendConfig
|
||||
listener edge.Listener
|
||||
|
||||
cidr net.IPAddr
|
||||
tun *water.Interface
|
||||
mtu int
|
||||
|
||||
counter atomic.Uint32
|
||||
clients cmap.ConcurrentMap[dest, *client]
|
||||
}
|
||||
|
||||
func NewBackend(cfg *BackendConfig) (*Backend, error) {
|
||||
@ -49,14 +62,66 @@ func NewBackend(cfg *BackendConfig) (*Backend, error) {
|
||||
b := &Backend{
|
||||
cfg: cfg,
|
||||
listener: listener,
|
||||
mtu: ZROK_VPN_MTU,
|
||||
clients: cmap.NewWithCustomShardingFunction[dest, *client](func(key dest) uint32 {
|
||||
return key.toInt32()
|
||||
}),
|
||||
}
|
||||
b.counter.Store(1)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *Backend) readTun() {
|
||||
buf := make([]byte, ZROK_VPN_MTU)
|
||||
for {
|
||||
n, err := b.tun.Read(buf)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to read tun device")
|
||||
// handle? error
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
pkt := packet(buf[:n])
|
||||
if !waterutil.IsIPv4(pkt) {
|
||||
continue
|
||||
}
|
||||
|
||||
logrus.WithField("packet", pkt).Trace("read from tun device")
|
||||
dest := pkt.destination()
|
||||
|
||||
if clt, ok := b.clients.Get(dest); ok {
|
||||
_, err := clt.conn.Write(pkt)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("failed to write packet to clt[%v]", dest)
|
||||
_ = clt.conn.Close()
|
||||
b.clients.Remove(dest)
|
||||
}
|
||||
} else {
|
||||
logrus.Errorf("no client with address[%v]", dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) Run() error {
|
||||
logrus.Info("started")
|
||||
defer logrus.Info("exited")
|
||||
|
||||
tunCfg := config.Config{
|
||||
ServerIP: "192.168.127.1",
|
||||
ServerIPv6: "fced::ffff:c0a8:7f01",
|
||||
CIDR: "192.168.127.1/24",
|
||||
CIDRv6: "fced::ffff:c0a8:7f01/64",
|
||||
MTU: ZROK_VPN_MTU,
|
||||
Verbose: true,
|
||||
}
|
||||
|
||||
b.tun = tun.CreateTun(tunCfg)
|
||||
defer func() {
|
||||
_ = b.tun.Close()
|
||||
}()
|
||||
|
||||
go b.readTun()
|
||||
|
||||
for {
|
||||
if conn, err := b.listener.Accept(); err == nil {
|
||||
go b.handle(conn)
|
||||
@ -66,47 +131,54 @@ func (b *Backend) Run() error {
|
||||
}
|
||||
}
|
||||
|
||||
type ipProto waterutil.IPProtocol
|
||||
|
||||
func (p ipProto) String() string {
|
||||
switch p {
|
||||
case waterutil.TCP:
|
||||
return "tcp"
|
||||
case waterutil.UDP:
|
||||
return "udp"
|
||||
case waterutil.ICMP:
|
||||
return "icmp"
|
||||
default:
|
||||
return fmt.Sprintf("proto[%d]", p)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) handle(conn net.Conn) {
|
||||
defer func(conn net.Conn) {
|
||||
_ = conn.Close()
|
||||
}(conn)
|
||||
|
||||
num := uint32(0)
|
||||
for num == 0 || num == 1 {
|
||||
num = b.counter.Add(1)
|
||||
num = num % 256
|
||||
}
|
||||
|
||||
ipv4 := net.IPv4(192, 168, 127, byte(num))
|
||||
ip := ipToDest(ipv4)
|
||||
|
||||
cfg := &ClientConfig{
|
||||
Greeting: "Welcome to zrok VPN",
|
||||
IP: ipv4.String(),
|
||||
ServerIP: "192.168.127.1",
|
||||
CIDR: ipv4.String() + "/24",
|
||||
MTU: b.mtu,
|
||||
}
|
||||
|
||||
j, err := json.Marshal(&cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to write client VPN config")
|
||||
return
|
||||
}
|
||||
_, err = conn.Write(j)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to write client VPN config")
|
||||
return
|
||||
}
|
||||
conn.Write(j)
|
||||
|
||||
buf := make([]byte, 16*1024)
|
||||
clt := &client{conn: conn}
|
||||
b.clients.Set(ip, clt)
|
||||
|
||||
buf := make([]byte, b.mtu)
|
||||
for {
|
||||
read, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
logrus.Error("read error", err)
|
||||
return
|
||||
}
|
||||
pkt := buf[:read]
|
||||
logrus.Infof("read packet %d bytes %v %v:%v -> %v:%v", read,
|
||||
ipProto(waterutil.IPv4Protocol(pkt)),
|
||||
waterutil.IPv4Source(pkt), waterutil.IPv4SourcePort(pkt),
|
||||
waterutil.IPv4Destination(pkt), waterutil.IPv4DestinationPort(pkt))
|
||||
|
||||
pkt := packet(buf[:read])
|
||||
logrus.WithField("packet", pkt).Info("read from ziti")
|
||||
_, err = b.tun.Write(pkt)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to write packet to tun")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,63 @@
|
||||
package vpn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/songgao/water/waterutil"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const ZROK_VPN_MTU = 16 * 1024
|
||||
|
||||
type ClientConfig struct {
|
||||
Greeting string
|
||||
IP string
|
||||
CIDR string
|
||||
ServerIP string
|
||||
Routes []string
|
||||
MTU int
|
||||
}
|
||||
|
||||
type dest struct {
|
||||
addr [4]byte
|
||||
}
|
||||
|
||||
func (d dest) String() string {
|
||||
return net.IP(d.addr[:]).String()
|
||||
}
|
||||
|
||||
func (d dest) toInt32() uint32 {
|
||||
return uint32(d.addr[0])<<24 + uint32(d.addr[1])<<16 + uint32(d.addr[2])<<8 + uint32(d.addr[3])
|
||||
}
|
||||
|
||||
func ipToDest(addr net.IP) dest {
|
||||
return dest{
|
||||
addr: [4]byte{addr[0], addr[1], addr[2], addr[3]},
|
||||
}
|
||||
}
|
||||
|
||||
type packet []byte
|
||||
|
||||
func (p packet) destination() dest {
|
||||
return ipToDest(waterutil.IPv4Destination(p))
|
||||
}
|
||||
|
||||
func (p packet) String() string {
|
||||
return fmt.Sprintf("%s %s:%d -> %s:%d %d bytes", p.proto(),
|
||||
waterutil.IPv4Source(p), waterutil.IPv4SourcePort(p),
|
||||
waterutil.IPv4Destination(p), waterutil.IPv4DestinationPort(p), len(waterutil.IPv4Payload(p)))
|
||||
}
|
||||
|
||||
func (p packet) proto() string {
|
||||
proto := waterutil.IPv4Protocol(p)
|
||||
switch proto {
|
||||
case waterutil.TCP:
|
||||
return "tcp"
|
||||
case waterutil.UDP:
|
||||
return "udp"
|
||||
case waterutil.ICMP:
|
||||
return "icmp"
|
||||
default:
|
||||
return strconv.Itoa(int(proto))
|
||||
}
|
||||
}
|
||||
|
4
go.mod
4
go.mod
@ -31,6 +31,7 @@ require (
|
||||
github.com/michaelquigley/pfxlog v0.6.10
|
||||
github.com/muesli/reflow v0.3.0
|
||||
github.com/net-byte/vtun v1.7.0
|
||||
github.com/net-byte/water v0.0.7
|
||||
github.com/nxadm/tail v1.4.8
|
||||
github.com/openziti/channel/v2 v2.0.121
|
||||
github.com/openziti/edge-api v0.26.12
|
||||
@ -38,6 +39,7 @@ require (
|
||||
github.com/openziti/identity v1.0.72
|
||||
github.com/openziti/sdk-golang v0.23.10
|
||||
github.com/openziti/transport/v2 v2.0.124
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rabbitmq/amqp091-go v1.8.1
|
||||
github.com/rubenv/sql-migrate v1.6.0
|
||||
@ -166,7 +168,6 @@ require (
|
||||
github.com/muesli/termenv v0.13.0 // indirect
|
||||
github.com/muhlemmer/gu v0.3.1 // indirect
|
||||
github.com/net-byte/go-gateway v0.0.2 // indirect
|
||||
github.com/net-byte/water v0.0.7 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
@ -174,7 +175,6 @@ require (
|
||||
github.com/openziti/metrics v1.2.47 // indirect
|
||||
github.com/openziti/secretstream v0.1.17 // indirect
|
||||
github.com/openziti/storage v0.2.6 // indirect
|
||||
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
|
||||
github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
|
Loading…
Reference in New Issue
Block a user