merge origin/master after it was cleaned up

This commit is contained in:
dovholuknf
2020-05-13 14:48:34 -04:00
52 changed files with 149 additions and 524 deletions
+3 -1
View File
@@ -258,4 +258,6 @@ paket-files/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.pyc
*/*.dll
+11 -20
View File
@@ -1,27 +1,18 @@
# ziti-client-windows
# Ziti Tunnel for Windows
This is a Windows 10 vpn plugin that "almost" works with windows 10. The VPN API is very fragile
and replacing the wrong element in the wrong place will likely result in errors.
(the uwp project which used to be here has moved to uwp-vpnplugin-archive and is likely abandoned)
Some notes:
The Ziti Tunnel for Windows is an application that is necessary to integrate applications which cannot embed a Ziti SDK
directly into the application. This is colloquially known as a "brown field" Ziti-enabled application because the app
itself has no understanding that it has been Ziti-enabled.
* to connect to a TCP server the traffic seems to be required to leave the actual machine. you
cannot use a locally listening socket for the tcpTransport
In order for an application that has no knowledge of being Ziti-enabled to work the connections established by the app
must be intercepted before leaving the computer and routed through the Ziti network. This is accomplished by three main
components:
* using an empty list as opposed to null in StartWithMainTransport might result in unexpected out of
memory erorrs.
* git@github.com:YtFlow/YtFlowTunnel.git at least compiles and deploys. never got it working but
might be useful
* [wintun](https://www.wintun.net) - provides a Layer 3 TUN for Windows
* A Windows service which runs as the local system account which creates the TUN as well as manages the Ziti connections
* A Windows UWP UI application that allows the interactively logged on user to interact with the Windows service
Testing:
once deployed (ideally using a remote machine so as to not risk your running windows) you should be able to
get the 'conenct' and 'disconnect' buttons to function. You'll need to update ZitiVPNPlugin.DESIRED_HOST
as that was using a linux vm.
You can run netcat on that linux vm using: nc -k -l 0.0.0.0 8900
Then you can see what routes are configured using: netstat -nr
If you run dnsmasq on that same linux VM you can set the vpnContext.DnsServer in MainPage.xaml.cs to the
same machine and influence what DNS results you get back and map those to whatever routes are added via the plugin
BIN
View File
Binary file not shown.
@@ -0,0 +1,26 @@
package runtime
import (
"time"
"wintun-testing/ziti-tunnel/globals"
)
const (
NF_GROUP_NAME = "NetFoundry Tunneler Users"
TunName = "ZitiTUN"
)
var TunStarted time.Time
var log = globals.Logger()
const Ipv4ip = "169.254.1.1"
const Ipv4mask = 24
const Ipv4dns = "127.0.0.1" // use lo -- don't pass DNS queries through tunneler SDK
// IPv6 CIDR fe80:6e66:7a69:7469::/64
// <link-local>: nf : zi : ti ::
const ipv6pfx = "fe80:6e66:7a69:7469"
const ipv6ip = "1"
const ipv6mask = 64
const Ipv6dns = "::1" // must be in "ipv6ip/ipv6mask" CIDR block
@@ -1,4 +1,4 @@
package service
package runtime
import (
"github.com/netfoundry/ziti-foundation/util/stringz"
@@ -1,4 +1,4 @@
package service
package runtime
import (
"bufio"
@@ -11,42 +11,54 @@ import (
"strconv"
"time"
"wintun-testing/cziti"
"wintun-testing/ziti-tunnel/config"
"wintun-testing/ziti-tunnel/dto"
"wintun-testing/ziti-tunnel/idutil"
)
type RuntimeState struct {
state *dto.TunnelStatus
type TunnelerState struct {
Active bool
Duration int64
Identities []*dto.Identity
IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
tun *tun.Device
tunName string
}
func (t *RuntimeState) RemoveByFingerprint(fingerprint string) {
type TunIpInfo struct {
Ip string
Subnet string
MTU uint16
DNS string
}
func (t *TunnelerState) RemoveByFingerprint(fingerprint string) {
log.Debugf("removing fingerprint: %s", fingerprint)
if index, _ := t.Find(fingerprint); index < len(t.state.Identities) {
t.state.Identities = append(t.state.Identities[:index], t.state.Identities[index+1:]...)
if index, _ := t.Find(fingerprint); index < len(t.Identities) {
t.Identities = append(t.Identities[:index], t.Identities[index+1:]...)
}
}
func (t *RuntimeState) Find(fingerprint string) (int, *dto.Identity) {
for i, n := range t.state.Identities {
func (t *TunnelerState) Find(fingerprint string) (int, *dto.Identity) {
for i, n := range t.Identities {
if n.FingerPrint == fingerprint {
return i, n
}
}
return len(t.state.Identities), nil
return len(t.Identities), nil
}
func (t *RuntimeState) RemoveByIdentity(id dto.Identity) {
func (t *TunnelerState) RemoveByIdentity(id dto.Identity) {
t.RemoveByFingerprint(id.FingerPrint)
}
func (t *RuntimeState) FindByIdentity(id dto.Identity) (int, *dto.Identity) {
func (t *TunnelerState) FindByIdentity(id dto.Identity) (int, *dto.Identity) {
return t.Find(id.FingerPrint)
}
func SaveState(t *RuntimeState) {
func SaveState(s *TunnelerState) {
// overwrite file if it exists
_ = os.MkdirAll(config.Path(), 0644)
@@ -57,11 +69,8 @@ func SaveState(t *RuntimeState) {
w := bufio.NewWriter(bufio.NewWriter(cfg))
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
t.state.IpInfo = nil
for _, id := range t.state.Identities {
id.Services = nil
}
_ = enc.Encode(t.state)
s.IpInfo = nil
_ = enc.Encode(s)
_ = w.Flush()
err = cfg.Close()
@@ -71,34 +80,31 @@ func SaveState(t *RuntimeState) {
log.Debug("state saved")
}
func (t *RuntimeState) ToStatus() dto.TunnelStatus {
var uptime int64
now := time.Now()
tunStart := now.Sub(TunStarted)
uptime = tunStart.Milliseconds()
var idCount int
if t.state != nil && t.state.Identities != nil {
idCount = len(t.state.Identities)
func (t *TunnelerState) Clean() TunnelerState {
var d int64
if t.Active {
now := time.Now()
dd := now.Sub(TunStarted)
d = dd.Milliseconds()
} else {
d = 0
}
clean := dto.TunnelStatus{
Active: t.state.Active,
Duration: uptime,
Identities: make([]*dto.Identity, idCount),
IpInfo: t.state.IpInfo,
rtn := TunnelerState{
Active: t.Active,
Duration: d,
Identities: make([]*dto.Identity, len(t.Identities)),
IpInfo: t.IpInfo,
}
for i, id := range t.Identities {
log.Debug("returning clean identity: %s", id.Name)
rtn.Identities[i] = idutil.Clean(*id)
}
for i, id := range t.state.Identities {
cid := idutil.Clean(*id)
clean.Identities[i] = &cid
}
return clean
return rtn
}
func (t *RuntimeState) CreateTun() error {
func (t *TunnelerState) CreateTun() error {
if noZiti() {
log.Warnf("NOZITI set to true. this should be only used for debugging")
return nil
@@ -162,38 +168,7 @@ func (t *RuntimeState) CreateTun() error {
return nil
}
func (t *RuntimeState) LoadIdentity(id *dto.Identity) {
if !noZiti() {
if id.Connected {
log.Warnf("id [%s] already connected", id.FingerPrint)
return
}
log.Infof("loading identity %s with fingerprint %s", id.Name, id.FingerPrint)
ctx := cziti.LoadZiti(id.Path())
id.NFContext = ctx
id.Connected = true
if ctx == nil {
log.Warnf("connecting to identity with fingerprint [%s] did not error but no context was returned", id.FingerPrint)
return
}
log.Infof("successfully loaded %s@%s", ctx.Name(), ctx.Controller())
log.Debugf("name changed from %s to %s", id.Name, ctx.Name())
id.Name = ctx.Name()
id.Services = make([]*dto.Service, 0)
} else {
log.Warnf("NOZITI set to true. this should be only used for debugging")
}
}
func noZiti() bool {
v, _ := strconv.ParseBool(os.Getenv("NOZITI"))
return v
}
func (t *RuntimeState) Close() {
func (t *TunnelerState) Close() {
if t.tun != nil {
log.Warn("TODO: actually close the tun - or disable all the identities etc.")
/*
@@ -207,26 +182,42 @@ func (t *RuntimeState) Close() {
}
}
func (t *RuntimeState) LoadConfig() {
log.Infof("reading config file located at: %s", config.File())
file, err := os.OpenFile(config.File(), os.O_RDONLY, 0644)
if err != nil {
t.state = &dto.TunnelStatus{}
return
}
func (t *TunnelerState) LoadIdentity(id *dto.Identity) {
if !noZiti() {
if id.Connected {
log.Warnf("id [%s] already connected", id.FingerPrint)
return
}
log.Infof("loading identity %s with fingerprint %s", id.Name, id.FingerPrint)
ctx := cziti.LoadZiti(id.Path())
id.Connected = true
if ctx == nil {
log.Warnf("connecting to identity with fingerprint [%s] did not error but no context was returned", id.FingerPrint)
return
}
log.Infof("successfully loaded %s@%s", ctx.Name(), ctx.Controller())
r := bufio.NewReader(file)
dec := json.NewDecoder(r)
log.Debug("name changed from %s to %s", id.Name, ctx.Name())
id.Name = ctx.Name()
err = dec.Decode(&rts.state)
if err != nil {
log.Warnf("unexpected error reading config file. %v", err)
t.state = &dto.TunnelStatus{}
return
if ctx.Services != nil {
log.Debug("ranging over services...")
id.Services = make([]*dto.Service, 0)
for _, svc := range *ctx.Services {
id.Services = append(id.Services, &dto.Service{
Name: svc.Name,
HostName: svc.InterceptHost,
Port: uint16(svc.InterceptPort)})
}
} else {
log.Warnf("no services to load for service name: %s", ctx.Name())
}
} else {
log.Warnf("NOZITI set to true. this should be only used for debugging")
}
}
err = file.Close()
if err != nil {
log.Errorf("could not close configuration file. this is not normal! %v", err)
}
}
func noZiti() bool {
v, _ := strconv.ParseBool(os.Getenv("NOZITI"))
return v
}
BIN
View File
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
# ziti-client-windows
This is a Windows 10 vpn plugin that "almost" works with windows 10. The VPN API is very fragile
and replacing the wrong element in the wrong place will likely result in errors.
Some notes:
* to connect to a TCP server the traffic seems to be required to leave the actual machine. you
cannot use a locally listening socket for the tcpTransport
* using an empty list as opposed to null in StartWithMainTransport might result in unexpected out of
memory erorrs.
* git@github.com:YtFlow/YtFlowTunnel.git at least compiles and deploys. never got it working but
might be useful
Testing:
once deployed (ideally using a remote machine so as to not risk your running windows) you should be able to
get the 'conenct' and 'disconnect' buttons to function. You'll need to update ZitiVPNPlugin.DESIRED_HOST
as that was using a linux vm.
You can run netcat on that linux vm using: nc -k -l 0.0.0.0 8900
Then you can see what routes are configured using: netstat -nr
If you run dnsmasq on that same linux VM you can set the vpnContext.DnsServer in MainPage.xaml.cs to the
same machine and influence what DNS results you get back and map those to whatever routes are added via the plugin
-27
View File
@@ -1,27 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
"path/filepath"
)
var exeName, _ = os.Executable()
var rootCmd = &cobra.Command{
Use: filepath.Base(exeName) ,
Short: "Runs the ziti-tunnel as a service",
Long: `This program provides access to a ziti-based network.
When executed without parameters it is expected that this application is running as a service`,
Run: func(cmd *cobra.Command, args []string) {
// Do Stuff Here
fmt.Println("i am in command")
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(addIdCmd)
}
var addIdCmd = &cobra.Command{
Use: "addId",
Short: "Adds the provided jwt file to the running service",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Adds the provided jwt file to the running service")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(debugCmd)
}
var debugCmd = &cobra.Command{
Use: "debug",
Short: "Runs the program interactively instead of expecting to be run as a service. Used in debugging",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Runs the program interactively instead of expecting to be run as a service. Used in debugging")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(disableIdCmd)
}
var disableIdCmd = &cobra.Command{
Use: "disable",
Short: "Disables any identity in the running service using the provided fingerprint",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Disables any identity in the running service using the provided fingerprint")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(enableIdCmd)
}
var enableIdCmd = &cobra.Command{
Use: "enable",
Short: "Enables any identity in the running service using the provided fingerprint",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Enables any identity in the running service using the provided fingerprint")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(removeIdCmd)
}
var removeIdCmd = &cobra.Command{
Use: "removeId",
Short: "Removes any identity from the running service using the provided fingerprint",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Removes any identity from the running service using the provided fingerprint")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(serviceCmd)
}
var serviceCmd = &cobra.Command{
Use: "service",
Short: "Expects to run the program as a service",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("print or return the version here")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
serviceCmd.AddCommand(installCmd)
}
var installCmd = &cobra.Command{
Use: "install",
Short: "Installs the executable as a service.",
Long: `When installing as a service using this function make sure not to move the executable. The path to the executing program will be used in the service`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("install this thing as a service")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
serviceCmd.AddCommand(removeCmd)
}
var removeCmd = &cobra.Command{
Use: "remove",
Short: "Removes the executable as a service.",
Long: `When removing the service make sure the path and service name have not changed`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("remove this thing as a service")
},
}
@@ -1,19 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
serviceCmd.AddCommand(startCmd)
}
var startCmd = &cobra.Command{
Use: "start",
Short: "Tries to start the service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Tries to start the service")
},
}
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
serviceCmd.AddCommand(statusCmd)
}
var statusCmd = &cobra.Command{
Use: "status",
Short: "Prints the status of the service",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Prints the status of the service")
},
}
@@ -1,19 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
serviceCmd.AddCommand(stopCmd)
}
var stopCmd = &cobra.Command{
Use: "stop",
Short: "Tries to stop the service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("try to stop the service")
},
}
-20
View File
@@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(versionCmd)
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version of the current executable",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("print or return the version here")
},
}
@@ -1,76 +0,0 @@
package service
import (
idcfg "github.com/netfoundry/ziti-sdk-golang/ziti/config"
"wintun-testing/ziti-tunnel/dto"
)
func dbg() {
r := rts.ToStatus()
events.broadcast <- dto.TunnelStatusEvent{
StatusEvent: dto.StatusEvent{Op: "status"},
Status: r,
}
svcs := make([]*dto.Service, 2)
svcs[0] = &dto.Service{
Name: "FakeService1",
HostName: "fake-service.com",
Port: 1234,
}
svcs[1] = &dto.Service{
Name: "Second Fake Service",
HostName: "some-other-host.ziti",
Port: 5555,
}
events.broadcast <- dto.IdentityEvent{
ActionEvent: IDENTITY_ADDED,
Id: dto.Identity{
Name: "NewIdentity",
FingerPrint: "new_id_fingerprint",
Active: true,
Config: idcfg.Config{
ZtAPI: "http://new_id.com:2123",
},
Status: STATUS_ENROLLED,
Services: svcs,
Metrics: nil,
},
}
events.broadcast <- dto.ServiceEvent{
ActionEvent: SERVICE_ADDED,
Service: dto.Service{
Name: "New Service",
HostName: "some new hostname",
Port: 5000,
},
Fingerprint: "new_id_fingerprint",
}
events.broadcast <- dto.ServiceEvent{
ActionEvent: SERVICE_REMOVED,
Service: dto.Service{
Name: "New Service",
},
Fingerprint: "new_id_fingerprint",
}
events.broadcast <- dto.IdentityEvent{
ActionEvent: IDENTITY_REMOVED,
Id: dto.Identity{
Name: "",
FingerPrint: "new_id_fingerprint",
Active: false,
Config: idcfg.Config{},
Status: "",
Services: nil,
Metrics: nil,
Connected: false,
NFContext: nil,
},
}
}
@@ -1,28 +0,0 @@
package service
import "wintun-testing/ziti-tunnel/dto"
const (
ADDED = "added"
REMOVED = "removed"
SERVICE_OP = "service"
IDENTITY_OP = "identity"
)
var SERVICE_ADDED = dto.ActionEvent{
StatusEvent: dto.StatusEvent{Op: SERVICE_OP},
Action: ADDED,
}
var SERVICE_REMOVED = dto.ActionEvent{
StatusEvent: dto.StatusEvent{Op: SERVICE_OP},
Action: REMOVED,
}
var IDENTITY_ADDED = dto.ActionEvent{
StatusEvent: dto.StatusEvent{Op: IDENTITY_OP},
Action: ADDED,
}
var IDENTITY_REMOVED = dto.ActionEvent{
StatusEvent: dto.StatusEvent{Op: IDENTITY_OP},
Action: REMOVED,
}
@@ -1,43 +0,0 @@
package service
type topic struct {
broadcast chan interface{}
channels map[int]chan interface{}
done chan bool
}
func newTopic() topic {
return topic{
broadcast: make(chan interface{}, 8),
channels: make(map[int]chan interface{}),
done: make(chan bool),
}
}
func(t *topic) register(id int, c chan interface{}) {
t.channels[id] = c
}
func(t *topic) unregister(id int) {
delete(t.channels, id)
}
func(t *topic) shutdown() {
t.done <- true
}
func(t *topic) run() {
go func() {
for {
select {
case msg := <-t.broadcast:
for _, c := range t.channels {
c <- msg
}
break
case <-t.done:
return
}
}
}()
}