implement VPN frontend

This commit is contained in:
eugene 2024-04-11 14:49:30 -04:00
parent bbeb435dfa
commit 8c3441d527
No known key found for this signature in database
2 changed files with 156 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/openziti/zrok/endpoints/proxy"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/rest_client_zrok"
"github.com/openziti/zrok/rest_client_zrok/share"
@ -165,6 +166,30 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
}()
case "vpn":
endpointUrl = &url.URL{
Scheme: "VPN",
}
fe, err := vpn.NewFrontend(&vpn.FrontendConfig{
IdentityName: env.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
})
if err != nil {
if !panicInstead {
tui.Error("unable to create private access", err)
}
panic(err)
}
go func() {
if err := fe.Run(); err != nil {
if !panicInstead {
tui.Error("error starting access", err)
}
panic(err)
}
}()
default:
cfg := proxy.DefaultFrontendConfig(env.EnvironmentIdentityName())
cfg.ShrToken = shrToken

131
endpoints/vpn/frontend.go Normal file
View File

@ -0,0 +1,131 @@
package vpn
import (
"encoding/json"
"github.com/net-byte/vtun/common/config"
"github.com/net-byte/vtun/tun"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"net"
"time"
)
type FrontendConfig struct {
IdentityName string
ShrToken string
RequestsChan chan *endpoints.Request
}
type Frontend struct {
cfg *FrontendConfig
ztx ziti.Context
conn net.Conn
}
func NewFrontend(cfg *FrontendConfig) (*Frontend, error) {
env, err := environment.LoadRoot()
if err != nil {
return nil, errors.Wrap(err, "error loading environment root")
}
zCfgPath, err := env.ZitiIdentityNamed(cfg.IdentityName)
if err != nil {
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.IdentityName)
}
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
if err != nil {
return nil, errors.Wrap(err, "error loading config")
}
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
zCtx, err := ziti.NewContext(zCfg)
if err != nil {
return nil, errors.Wrap(err, "error loading ziti context")
}
zConn, err := zCtx.Dial(cfg.ShrToken)
if err != nil {
zCtx.Close()
return nil, errors.Wrap(err, "error connecting to ziti")
}
return &Frontend{
cfg: cfg,
ztx: zCtx,
conn: zConn,
}, nil
}
func (f *Frontend) Run() error {
var cltCfg ClientConfig
d := json.NewDecoder(f.conn)
if err := d.Decode(&cltCfg); err != nil {
return errors.Wrap(err, "error decoding vpn config")
}
f.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: cltCfg.ServerIP,
Method: "CONNECTED",
Path: cltCfg.Greeting,
}
logrus.Info("connected:", cltCfg.Greeting)
defer func() {
f.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: cltCfg.ServerIP,
Method: "Disconnected",
}
}()
cfg := config.Config{
ServerIP: cltCfg.ServerIP,
CIDR: cltCfg.CIDR,
ServerIPv6: "fced::ffff:c0a8:7f01",
CIDRv6: "fced::ffff:c0a8:7f16/64",
MTU: cltCfg.MTU,
Verbose: false,
}
iface := tun.CreateTun(cfg)
logrus.Infof("created tun device: %s", iface.Name())
go func() {
defer func() {
_ = f.conn.Close()
_ = iface.Close()
}()
b := make([]byte, cltCfg.MTU)
for {
n, err := f.conn.Read(b)
if err != nil {
logrus.WithError(err).Error("error reading from ziti")
return
}
p := packet(b[:n])
logrus.WithField("packet", p).Trace("received packet from peer")
_, err = iface.Write(p)
if err != nil {
logrus.WithError(err).Error("error writing to device")
return
}
}
}()
buf := make([]byte, cltCfg.MTU)
for {
n, err := iface.Read(buf)
if err != nil {
return errors.Wrap(err, "error reading packet")
}
pkt := packet(buf[:n])
logrus.WithField("packet", pkt).Trace("read packet from tun device")
_, err = f.conn.Write(pkt)
if err != nil {
return errors.Wrap(err, "error sending packet to ziti")
}
}
}