allow overriding default VPN address

This commit is contained in:
Eugene K 2024-04-12 11:20:38 -04:00
parent 0775847fa5
commit fdea51210e
No known key found for this signature in database
GPG Key ID: C8CCB4692865B818
6 changed files with 141 additions and 30 deletions

View File

@ -3,12 +3,14 @@ package main
import (
"encoding/json"
"fmt"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/openziti/zrok/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net"
"slices"
"time"
)
@ -115,7 +117,15 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
}
case "vpn":
target = "vpn"
if len(args) == 2 {
_, _, err := net.ParseCIDR(args[1])
if err != nil {
tui.Error("the 'vpn' backend expect valid CIDR <target>", err)
}
target = args[1]
} else {
target = vpn.DefaultTarget()
}
default:
tui.Error(fmt.Sprintf("invalid backend mode '%v'; "+

View File

@ -16,6 +16,7 @@ import (
"github.com/openziti/zrok/tui"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net"
"os"
"os/signal"
"syscall"
@ -107,7 +108,15 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
target = "socks"
case "vpn":
target = "vpn"
if len(args) == 1 {
_, _, err := net.ParseCIDR(args[0])
if err != nil {
tui.Error("the 'vpn' backend expect valid CIDR <target>", err)
}
target = args[0]
} else {
target = vpn.DefaultTarget()
}
default:
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel, udpTunnel, caddy, drive}", cmd.backendMode), nil)

View File

@ -2,6 +2,7 @@ package vpn
import (
"encoding/json"
"github.com/google/go-cmp/cmp"
"github.com/net-byte/vtun/common/config"
"github.com/net-byte/vtun/tun"
_ "github.com/net-byte/vtun/tun"
@ -15,6 +16,7 @@ import (
"github.com/songgao/water/waterutil"
"io"
"net"
"strconv"
"sync/atomic"
"time"
)
@ -34,7 +36,10 @@ type Backend struct {
cfg *BackendConfig
listener edge.Listener
cidr net.IPAddr
addr net.IP
addr6 net.IP
subnet *net.IPNet
subnet6 *net.IPNet
tun *water.Interface
mtu int
@ -60,6 +65,19 @@ func NewBackend(cfg *BackendConfig) (*Backend, error) {
if err != nil {
return nil, errors.Wrap(err, "error listening")
}
addr6 := zrokIPv6Addr
addr4 := zrokIPv4Addr
sub4 := zrokIPv4
sub6 := zrokIPv6
if cfg.EndpointAddress != "" {
addr4, sub4, err = net.ParseCIDR(cfg.EndpointAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to parse VPN subnet config")
}
}
b := &Backend{
cfg: cfg,
listener: listener,
@ -67,6 +85,10 @@ func NewBackend(cfg *BackendConfig) (*Backend, error) {
clients: cmap.NewWithCustomShardingFunction[dest, *client](func(key dest) uint32 {
return key.toInt32()
}),
addr: addr4,
addr6: addr6,
subnet: sub4,
subnet6: sub6,
}
b.counter.Store(1)
return b, nil
@ -112,15 +134,18 @@ func (b *Backend) Run() error {
logrus.Info("started")
defer logrus.Info("exited")
bits, _ := b.subnet.Mask.Size()
bits6, _ := b.subnet6.Mask.Size()
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",
ServerIP: b.addr.String(),
ServerIPv6: b.addr6.String(),
CIDR: b.addr.String() + "/" + strconv.Itoa(bits),
CIDRv6: b.addr6.String() + "/" + strconv.Itoa(bits6),
MTU: ZROK_VPN_MTU,
Verbose: true,
}
logrus.Infof("%+v", tunCfg)
b.tun = tun.CreateTun(tunCfg)
defer func() {
_ = b.tun.Close()
@ -142,20 +167,18 @@ func (b *Backend) handle(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))
ipv4, ipv6 := b.nextIP()
ip := ipToDest(ipv4)
bits, _ := b.subnet.Mask.Size()
bits6, _ := b.subnet6.Mask.Size()
cfg := &ClientConfig{
Greeting: "Welcome to zrok VPN",
IP: ipv4.String(),
ServerIP: "192.168.127.1",
CIDR: ipv4.String() + "/24",
ServerIP: b.addr.String(),
ServerIPv6: b.addr6.String(),
CIDR: ipv4.String() + "/" + strconv.Itoa(bits),
CIDR6: ipv6.String() + "/" + strconv.Itoa(bits6),
MTU: b.mtu,
}
@ -203,3 +226,40 @@ func (b *Backend) handle(conn net.Conn) {
}
}
}
func (b *Backend) nextIP() (net.IP, net.IP) {
ip4 := make([]byte, len(b.subnet.IP))
for {
copy(ip4, b.subnet.IP)
n := b.counter.Add(1)
if n == 0 {
continue
}
for i := 0; i < len(ip4); i++ {
b := (n >> (i * 8)) % 0xff
ip4[len(ip4)-1-i] ^= byte(b)
}
// subnet overflow
if !b.subnet.Contains(ip4) {
b.counter.Store(1)
continue
}
if cmp.Equal(b.addr, ip4) {
continue
}
if b.clients.Has(ipToDest(ip4)) {
continue
}
break
}
ip6 := append([]byte{}, b.subnet6.IP...)
copy(ip6[net.IPv6len-net.IPv4len:], ip4)
return ip4, ip6
}

View File

@ -82,8 +82,8 @@ func (f *Frontend) Run() error {
cfg := config.Config{
ServerIP: cltCfg.ServerIP,
CIDR: cltCfg.CIDR,
ServerIPv6: "fced::ffff:c0a8:7f01",
CIDRv6: "fced::ffff:c0a8:7f16/64",
ServerIPv6: cltCfg.ServerIPv6,
CIDRv6: cltCfg.CIDR6,
MTU: cltCfg.MTU,
Verbose: false,
}

View File

@ -9,11 +9,42 @@ import (
const ZROK_VPN_MTU = 16 * 1024
var (
zrokIPv4Addr = net.IPv4(10, 'z', 0, 0)
zrokIPv4 = &net.IPNet{
IP: net.IPv4(10, 'z', 0, 0),
Mask: net.CIDRMask(16, 8*net.IPv4len),
}
zrokIPv6Addr = net.IP{0xfd, 0, 'z', 'r', 'o', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
zrokIPv6 = &net.IPNet{
IP: net.IP{0xfd, 0, 'z', 'r', 'o', 'k', // prefix + global ID
0, 0, // subnet id
0, 0, 0, 0,
0, 0, 0, 0,
},
Mask: net.CIDRMask(64, 8*net.IPv6len),
}
)
func DefaultTarget() string {
l := len(zrokIPv4Addr)
subnet := net.IPNet{
IP: make([]byte, l),
Mask: zrokIPv4.Mask,
}
copy(subnet.IP, zrokIPv4Addr)
subnet.IP[l-1] = 1
return subnet.String()
}
type ClientConfig struct {
Greeting string
IP string
CIDR string
CIDR6 string
ServerIP string
ServerIPv6 string
Routes []string
MTU int
}

1
go.mod
View File

@ -17,6 +17,7 @@ require (
github.com/go-openapi/validate v0.23.0
github.com/gobwas/glob v0.2.3
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.1
github.com/iancoleman/strcase v0.2.0