diff --git a/ZitiTunneler/IdentityItem.xaml.cs b/ZitiTunneler/IdentityItem.xaml.cs
index 453f409f..73016a0c 100644
--- a/ZitiTunneler/IdentityItem.xaml.cs
+++ b/ZitiTunneler/IdentityItem.xaml.cs
@@ -70,8 +70,13 @@ namespace ZitiTunneler {
}
catch(ServiceClient.ServiceException se)
{
+ MessageBox.Show("Unexpected error 5 the toggle needs to be rolled back!!! jeremy!", se.Message);
MessageBox.Show(se.AdditionalInfo, se.Message);
}
+ catch (Exception ex)
+ {
+ MessageBox.Show("Unexpected error 5 the toggle needs to be rolled back!!! jeremy!", ex.Message);
+ }
}
private void ToggleButton_Checked(object sender, RoutedEventArgs e) {
diff --git a/ZitiTunneler/ServiceClient/ClientImpl.cs b/ZitiTunneler/ServiceClient/ClientImpl.cs
index ec51ba37..ddb6d4c7 100644
--- a/ZitiTunneler/ServiceClient/ClientImpl.cs
+++ b/ZitiTunneler/ServiceClient/ClientImpl.cs
@@ -60,25 +60,6 @@ namespace ZitiTunneler.ServiceClient
pipeClient.Dispose();
}
pipeClient = new NamedPipeClientStream(localPipeServer, ipcPipe, inOut);
- /*
- PipeSecurity pipeSecurity = CreateSystemIOPipeSecurity();
- var pipeServer = new NamedPipeServerStream(ipcPipe,
- PipeDirection.InOut,
- 1,
- PipeTransmissionMode.Message,
- PipeOptions.Asynchronous,
- 0x4000,
- 0x400,
- pipeSecurity,
- HandleInheritability.Inheritable);
-
- pipeClient = new NamedPipeClientStream(localPipeServer,
- ipcPipe,
- PipeAccessRights.Read | PipeAccessRights.Write,
- PipeOptions.None,
- System.Security.Principal.TokenImpersonationLevel.None,
- System.IO.HandleInheritability.None);
- */
try
{
@@ -92,18 +73,16 @@ namespace ZitiTunneler.ServiceClient
Debug.WriteLine("There was a problem connecting to the service. " + ex.Message);
try
{
- ipcReader?.Close();
- ipcWriter?.Close();
pipeClient?.Close();
}
- catch
+ catch (Exception exc)
{
//intentionally ignored
+ Debug.WriteLine(exc.Message);
}
ipcReader = null;
ipcWriter = null;
pipeClient = null;
- throw;
}
}
}
diff --git a/wintun-testing/build.bat b/wintun-testing/build.bat
index 19c083e9..6ad97167 100644
--- a/wintun-testing/build.bat
+++ b/wintun-testing/build.bat
@@ -6,6 +6,12 @@ if not exist %TUNNELER_SDK_DIR%\install mkdir %TUNNELER_SDK_DIR%\install
cmake -G Ninja -S %TUNNELER_SDK_DIR% -B %TUNNELER_SDK_DIR%\build -DCMAKE_INSTALL_PREFIX=%TUNNELER_SDK_DIR%\install
cmake --build %TUNNELER_SDK_DIR%\build --target install
+cp %TUNNELER_SDK_DIR%\install\lib\ziti.dll .
+cp %TUNNELER_SDK_DIR%\install\lib\libuv.dll .
+
+echo COPIED dlls to .
+
set CGO_CFLAGS=-DNOGDI -I %TUNNELER_SDK_DIR%\install\include
set CGO_LDFLAGS=-L %TUNNELER_SDK_DIR%\install\lib
go build -a ./ziti-wintun
+go build -a ./winio
diff --git a/wintun-testing/build.sh b/wintun-testing/build.sh
index 7271604c..e327b06f 100644
--- a/wintun-testing/build.sh
+++ b/wintun-testing/build.sh
@@ -26,5 +26,6 @@ cp ./install/lib/libuv.dll .
export CGO_CFLAGS="-DNOGDI -I $(cygpath -a -m ./install/include)"
export CGO_LDFLAGS="-L $(cygpath -a -m ./install/lib)"
-go build -a ./ziti-wintun
+rm ./ziti-wintun.exe
+go build -v ./ziti-wintun
diff --git a/wintun-testing/cziti/ctun.go b/wintun-testing/cziti/ctun.go
index f90d5d45..a4039994 100644
--- a/wintun-testing/cziti/ctun.go
+++ b/wintun-testing/cziti/ctun.go
@@ -32,14 +32,11 @@ import "C"
import (
"errors"
"fmt"
- "github.com/miekg/dns"
"golang.zx2c4.com/wireguard/tun"
"net"
"unsafe"
)
-const dnsIP = "169.254.1.253"
-
type Tunnel interface {
AddIntercept(service string, hostname string, port int, ctx unsafe.Pointer)
}
@@ -61,7 +58,7 @@ type tunnel struct {
var devMap = make(map[string]*tunnel)
-func HookupTun(dev tun.Device) (Tunnel, error) {
+func HookupTun(dev tun.Device, dns []net.IP) (Tunnel, error) {
fmt.Println("in HookupTun ")
defer fmt.Println("exiting HookupTun")
name, err := dev.Name()
@@ -89,9 +86,7 @@ func HookupTun(dev tun.Device) (Tunnel, error) {
t.tunCtx = C.NF_tunneler_init(opts, _impl.libuvCtx.l)
- dnsServer := C.CString(dnsIP)
- rc := C.NF_udp_handler(t.tunCtx, dnsServer, C.int(53), C.ziti_udp_cb(C.dnsHandler), unsafe.Pointer(nil))
- fmt.Println("registered UDP handler = ", int64(rc))
+ go runDNSserver(dns)
return t, nil
}
@@ -241,47 +236,19 @@ func (t *tunnel) AddIntercept(service string, host string, port int, ctx unsafe.
// extern void dnsHandler(tunneler_io_context tio, void *ctx, addr_t src, uint16_t sport, void *data, ssize_t len);
//export dnsHandler
func dnsHandler(tio C.tunneler_io_context, ctx unsafe.Pointer, src C.addr_t, sport C.uint16_t, b unsafe.Pointer, bl C.ssize_t) {
- q := &dns.Msg{}
- if err := q.Unpack(C.GoBytes(b, C.int(bl))); err != nil {
- fmt.Println("error", err)
- }
+ /*
+ reply, err := processDNSquery(C.GoBytes(b, C.int(bl)))
- msg := dns.Msg{}
- msg.SetReply(q)
- msg.RecursionAvailable = false
-
- query := q.Question[0]
- var ip net.IP
- if query.Qtype == dns.TypeA {
- ip = DNS.Resolve(query.Name)
- }
-
- if ip != nil {
- msg.Authoritative = true
- msg.Rcode = dns.RcodeSuccess
- answer := &dns.A{
- Hdr: dns.RR_Header{Name: query.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
- A: ip,
+ if err == nil {
+ replyC := C.CBytes(reply)
+ rc := C.NF_udp_send(tio, src, sport, replyC, C.ssize_t(len(reply)))
+ C.free(replyC)
+ if rc != 0 {
+ fmt.Println("NF_udp_reply rc=", rc)
+ }
+ } else {
+ fmt.Println("dns message error", err)
}
- msg.Answer = append(msg.Answer, answer)
- } else {
- // msg.Rcode = dns.RcodeNotImplemented
- msg.Authoritative = false
- msg.Rcode = dns.RcodeRefused
- }
-
- reply, err := msg.Pack()
- if err == nil {
- replyC := C.CBytes(reply)
- rc := C.NF_udp_send(tio, src, sport, replyC, C.ssize_t(len(reply)))
- C.free(replyC)
- if rc != 0 {
- fmt.Println("NF_udp_reply rc=", rc)
- }
- } else {
- fmt.Println("dns message error", err)
- }
+ */
}
-
-/*******************************************************************/
diff --git a/wintun-testing/cziti/cziti-cli/main.go b/wintun-testing/cziti/cziti-cli/main.go
index 6acecdb4..d829da63 100644
--- a/wintun-testing/cziti/cziti-cli/main.go
+++ b/wintun-testing/cziti/cziti-cli/main.go
@@ -38,7 +38,7 @@ func main() {
}
}
-var commands = make(map[string]func([]string)error)
+var commands = make(map[string]func([]string) error)
func init() {
commands["quit"] = quit
@@ -77,7 +77,7 @@ func quit(_ []string) error {
return nil
}
-func help(_[]string) error {
+func help(_ []string) error {
fmt.Println("available commands:")
for k, _ := range commands {
fmt.Println("\t", k)
@@ -108,4 +108,4 @@ func list(args []string) error {
fmt.Printf("\t%d:\t%s@%s\n", i, c.Name(), c.Controller())
}
return nil
-}
\ No newline at end of file
+}
diff --git a/wintun-testing/cziti/dns-proxy.go b/wintun-testing/cziti/dns-proxy.go
new file mode 100644
index 00000000..bf38810d
--- /dev/null
+++ b/wintun-testing/cziti/dns-proxy.go
@@ -0,0 +1,202 @@
+package cziti
+
+import (
+ "fmt"
+ "github.com/miekg/dns"
+ "net"
+ "wintun-testing/cziti/windns"
+)
+
+func processDNSquery(packet []byte, p *net.UDPAddr, s *net.UDPConn) {
+ q := &dns.Msg{}
+ if err := q.Unpack(packet); err != nil {
+ fmt.Println("ERROR", err)
+ return
+ }
+
+ msg := dns.Msg{}
+ msg.SetReply(q)
+ msg.RecursionAvailable = false
+ msg.Authoritative = false
+ msg.Rcode = dns.RcodeRefused
+
+ query := q.Question[0]
+ var ip net.IP
+ // fmt.Printf("query: Type(%d) name(%s)\n", query.Qtype, query.Name)
+
+ ip = DNS.Resolve(query.Name)
+
+ // never proxy hostnames that we know about regardless of type
+ if ip != nil {
+ fmt.Println("resolved ", query.Name, ip)
+
+ var answer *dns.A
+ if query.Qtype == dns.TypeA && len(ip.To4()) == net.IPv4len {
+ answer = &dns.A{
+ Hdr: dns.RR_Header{Name: query.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
+ A: ip,
+ }
+ } else if query.Qtype == dns.TypeAAAA {
+ answer = &dns.A{
+ Hdr: dns.RR_Header{Name: query.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 60},
+ A: ip.To16(),
+ }
+ }
+
+ if answer != nil {
+ msg.Authoritative = true
+ msg.Rcode = dns.RcodeSuccess
+
+ msg.Answer = append(msg.Answer, answer)
+ }
+
+ repB, err := msg.Pack()
+ if err == nil {
+ _, _, err = s.WriteMsgUDP(repB, nil, p)
+ }
+ if err != nil {
+ fmt.Println("dns error", err)
+ }
+ } else {
+ // fmt.Println("proxying ", dns.Type(query.Qtype), query.Name, q.Id, " for ", p)
+ proxyDNS(q, p, s)
+ }
+}
+
+type dnsreq struct {
+ q []byte
+ s *net.UDPConn
+ p *net.UDPAddr
+}
+
+func runDNSserver(dnsBind []net.IP) {
+ dnsServers := windns.GetUpstreamDNS()
+ go runDNSproxy(dnsServers)
+
+ reqch := make(chan dnsreq)
+
+ for _, bindAddr := range dnsBind {
+ go runListener(bindAddr, 53, reqch)
+ }
+
+ windns.ReplaceDNS(dnsBind)
+
+ for req := range reqch {
+ processDNSquery(req.q, req.p, req.s)
+ }
+}
+
+func runListener(ip net.IP, port int, reqch chan dnsreq) {
+ laddr := &net.UDPAddr{
+ IP: ip,
+ Port: 53,
+ Zone: "",
+ }
+
+ network := "udp6"
+ if len(ip.To4()) == net.IPv4len {
+ network = "udp4"
+ }
+ fmt.Println(network, ip)
+ server, err := net.ListenUDP(network, laddr)
+ if err != nil {
+ panic(err)
+ }
+
+ // oob := make([]byte, 1024)
+ for {
+ b := make([]byte, 1024)
+ nb, _, _, peer, err := server.ReadMsgUDP(b, nil)
+ if err != nil {
+ panic(err)
+ }
+ reqch <- dnsreq{
+ q: b[:nb],
+ s: server,
+ p: peer,
+ }
+ }
+}
+
+/*******************************************************************/
+type proxiedReq struct {
+ req *dns.Msg
+ peer *net.UDPAddr
+ s *net.UDPConn
+}
+
+var proxiedRequests chan *proxiedReq
+
+func proxyDNS(req *dns.Msg, peer *net.UDPAddr, serv *net.UDPConn) {
+ proxiedRequests <- &proxiedReq{
+ req: req,
+ peer: peer,
+ s: serv,
+ }
+}
+
+func runDNSproxy(dnsServers []string) {
+ var dnsUpstreams []*net.UDPConn
+ for _, s := range dnsServers {
+ sAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:53", s))
+ if err != nil {
+ fmt.Println("skipping upstream", s, err.Error())
+ } else {
+ conn, err := net.DialUDP("udp", nil, sAddr)
+ if err != nil {
+ fmt.Println("skipping upstream", s, err.Error())
+ }
+ dnsUpstreams = append(dnsUpstreams, conn)
+ }
+ }
+
+ proxiedRequests = make(chan *proxiedReq, 16)
+ respChan := make(chan []byte, 16)
+
+ for _, proxy := range dnsUpstreams {
+ go func() {
+ for {
+ resp := make([]byte, 1024)
+ n, err := proxy.Read(resp)
+ if err != nil {
+ fmt.Println("error receiving from ", proxy.RemoteAddr(), err)
+ } else {
+ respChan <- resp[:n]
+ }
+ }
+ }()
+ }
+
+ reqs := make(map[uint32]*proxiedReq)
+
+ for {
+ select {
+ case pr := <-proxiedRequests:
+ id := (uint32(pr.req.Id) << 16) | uint32(pr.req.Question[0].Qtype)
+ reqs[id] = pr
+ b, _ := pr.req.Pack()
+ // fmt.Println("sending proxy req", id, dns.Type(pr.req.Question[0].Qtype), pr.req.Question[0].Name)
+ for _, proxy := range dnsUpstreams {
+ // fmt.Println("sending proxy req", dns.Type(pr.req.Question[0].Qtype), pr.req.Question[0].Name, proxy.RemoteAddr())
+ if _, err := proxy.Write(b); err != nil {
+ fmt.Println("failed to proxy DNS to ", proxy)
+ }
+ }
+
+ case rep := <-respChan:
+ reply := dns.Msg{}
+ if err := reply.Unpack(rep); err == nil {
+ id := (uint32(reply.Id) << 16) | uint32(reply.Question[0].Qtype)
+ req, found := reqs[id]
+ if found {
+ delete(reqs, id)
+ // fmt.Printf("proxy resolved %+v for %v\n\n", reply, req.peer)
+ req.s.WriteMsgUDP(rep, nil, req.peer)
+ } else {
+ fmt.Println("matching request was not found for ",
+ dns.Type(reply.Question[0].Qtype), reply.Question[0].Name)
+ }
+ }
+ }
+ }
+}
diff --git a/wintun-testing/cziti/dns.go b/wintun-testing/cziti/dns.go
index e7b1484e..73184bae 100644
--- a/wintun-testing/cziti/dns.go
+++ b/wintun-testing/cziti/dns.go
@@ -16,6 +16,7 @@ type DnsManager interface {
DeregisterService(ctx *CZitiCtx, name string)
GetService(ip net.IP, port uint16) (*CZitiCtx, string, error)
}
+
const defaultCidr = "169.254.0.0"
const defaultMaskBits = 16
@@ -23,7 +24,7 @@ var initOnce = sync.Once{}
var DNS = &dnsImpl{}
type dnsImpl struct {
- cidr uint32
+ cidr uint32
counter uint32
serviceMap map[string]ctxService
@@ -35,7 +36,7 @@ type dnsImpl struct {
}
type ctxService struct {
- ctx *CZitiCtx
+ ctx *CZitiCtx
name string
}
@@ -69,11 +70,11 @@ func (dns *dnsImpl) RegisterService(dnsName string, port uint16, ctx *CZitiCtx,
return nextIp, nil
}
-func (dns *dnsImpl)Resolve(dnsName string) net.IP {
+func (dns *dnsImpl) Resolve(dnsName string) net.IP {
return dns.hostnameMap[dnsName]
}
-func (dns *dnsImpl)DeregisterService(ctx *CZitiCtx, name string) {
+func (dns *dnsImpl) DeregisterService(ctx *CZitiCtx, name string) {
for k, sc := range dns.serviceMap {
if sc.ctx == ctx && sc.name == name {
delete(dns.serviceMap, k)
@@ -82,7 +83,7 @@ func (dns *dnsImpl)DeregisterService(ctx *CZitiCtx, name string) {
}
}
-func (this *dnsImpl)GetService(ip net.IP, port uint16) (*CZitiCtx, string, error) {
+func (this *dnsImpl) GetService(ip net.IP, port uint16) (*CZitiCtx, string, error) {
ipv4 := binary.BigEndian.Uint32(ip)
dns, found := this.ipMap[ipv4]
if !found {
@@ -108,4 +109,3 @@ func DnsInit(ip string, maskBits int) {
DNS.counter = 2
})
}
-
diff --git a/wintun-testing/cziti/windns/windns.go b/wintun-testing/cziti/windns/windns.go
new file mode 100644
index 00000000..e33116c4
--- /dev/null
+++ b/wintun-testing/cziti/windns/windns.go
@@ -0,0 +1,73 @@
+package windns
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+func ResetDNS() {
+ fmt.Println("Resetting DNS to original-ish state")
+
+ script := `Get-NetIPInterface | ForEach-Object { Set-DnsClientServerAddress -InterfaceIndex $_.ifIndex -ResetServerAddresses }`
+
+ cmd := exec.Command("powershell", "-Command", script)
+ cmd.Stderr = os.Stdout
+ cmd.Stdout = os.Stdout
+
+ err := cmd.Run()
+ if err != nil {
+ fmt.Println("ERROR resetting DNS", err)
+ }
+}
+
+func GetUpstreamDNS() []string {
+ ResetDNS()
+
+ script := `Get-DnsClientServerAddress | ForEach-Object { $_.ServerAddresses } | Sort-Object | Get-Unique`
+
+ cmd := exec.Command("powershell", "-Command", script)
+ cmd.Stderr = os.Stdout
+ output := new(bytes.Buffer)
+ cmd.Stdout = output
+
+ err := cmd.Run()
+
+ if err != nil {
+ panic(err)
+ }
+
+ var names []string
+ for {
+ l, err := output.ReadString('\n')
+ if err != nil {
+ break
+ }
+ addr := net.ParseIP(strings.TrimSpace(l))
+ if !addr.IsLoopback() {
+ names = append(names, addr.String())
+ }
+ }
+ return names
+}
+
+func ReplaceDNS(ips []net.IP) {
+ var names []string
+ for _, i := range ips {
+ names = append(names, i.String())
+ }
+ addresses := strings.Join(names, ",")
+ script := fmt.Sprintf(
+ `Get-NetIPInterface | ForEach-Object { Set-DnsClientServerAddress -InterfaceIndex $_.ifIndex -ServerAddresses %s }`,
+ addresses)
+ cmd := exec.Command("powershell", "-Command", script)
+ cmd.Stderr = os.Stderr
+ cmd.Stdout = os.Stdout
+
+ if err := cmd.Run(); err != nil {
+ fmt.Println("ERROR", err)
+ }
+}
diff --git a/wintun-testing/go.sum b/wintun-testing/go.sum
index 2f19d355..a700ac11 100644
--- a/wintun-testing/go.sum
+++ b/wintun-testing/go.sum
@@ -1,3 +1,4 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
@@ -13,6 +14,7 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -59,6 +61,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/netfoundry/secretstream v0.1.1/go.mod h1:uasYkYSp0MmNSlKOWJ2sVzxPms8e58TS4ENq4yro86k=
github.com/netfoundry/ziti-foundation v0.9.8 h1:Nyx4U+pZ6iPtXBYSIad8xg5nBVjQNLatCHg5krQmeWM=
github.com/netfoundry/ziti-foundation v0.9.8/go.mod h1:desAxe5jN/V/+cYe99TGEqxtMVdlJ1HfSRzCmuPJD7M=
+github.com/netfoundry/ziti-foundation v0.9.11 h1:FKLAdAkXjYeSbCSbcpyvY2vHPE9a1zDswaWAGiW5Brc=
github.com/netfoundry/ziti-sdk-golang v0.11.16 h1:YZxHtDq4o+r141ISHvElT0CH4DKdb+EeQaoxSDVJAq0=
github.com/netfoundry/ziti-sdk-golang v0.11.16/go.mod h1:Onxp1kNm0xarDjl6S43Y9PQPVHfXgUFcM157KQKqHm4=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -69,6 +72,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -86,6 +90,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@@ -109,6 +114,7 @@ golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -141,6 +147,7 @@ golang.zx2c4.com/wireguard v0.0.20200320/go.mod h1:lDian4Sw4poJ04SgHh35nzMVwGSYl
golang.zx2c4.com/wireguard/windows v0.1.0 h1:742izt2DAJBpIQT+DvrzN58P9p7fO4BUFOgMzY9qVhw=
golang.zx2c4.com/wireguard/windows v0.1.0/go.mod h1:EK7CxrFnicmYJ0ZCF6crBh2/EMMeSxMlqgLlwN0Kv9s=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
@@ -148,4 +155,5 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/wintun-testing/winio/dto/dtos.go b/wintun-testing/winio/dto/dtos.go
index c03fcf60..d05c728c 100644
--- a/wintun-testing/winio/dto/dtos.go
+++ b/wintun-testing/winio/dto/dtos.go
@@ -3,6 +3,8 @@ package dto
import (
idcfg "github.com/netfoundry/ziti-sdk-golang/ziti/config"
"github.com/netfoundry/ziti-sdk-golang/ziti/enroll"
+ "log"
+ "wintun-testing/winio/config"
)
type AddIdentity struct {
@@ -24,6 +26,8 @@ type Identity struct {
Status string
Services []*Service
Metrics Metrics
+
+ Connected bool `json:"-"`
}
type Metrics struct {
TotalBytes int64
@@ -43,4 +47,11 @@ type ZitiTunnelStatus struct {
Message string
Error string
Payload Identity
-}
\ No newline at end of file
+}
+
+func (id *Identity) Path() string {
+ if id.FingerPrint == "" {
+ log.Fatalf("fingerprint is invalid for id %s", id.Name)
+ }
+ return config.Path() + id.FingerPrint + ".json"
+}
diff --git a/wintun-testing/winio/goland.run/go build wintun-testing main.go.run.xml b/wintun-testing/winio/goland.run/go build wintun-testing main.go.run.xml
index 2a60b33a..e2ebd906 100644
--- a/wintun-testing/winio/goland.run/go build wintun-testing main.go.run.xml
+++ b/wintun-testing/winio/goland.run/go build wintun-testing main.go.run.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/wintun-testing/winio/ipc/impl.go b/wintun-testing/winio/ipc/impl.go
index 030890ad..4accf27a 100644
--- a/wintun-testing/winio/ipc/impl.go
+++ b/wintun-testing/winio/ipc/impl.go
@@ -13,7 +13,12 @@ import (
"io/ioutil"
"net"
"os"
+ "os/signal"
"strings"
+ "syscall"
+ "time"
+ "wintun-testing/cziti"
+ "wintun-testing/cziti/windns"
"wintun-testing/winio/config"
"wintun-testing/winio/dto"
"wintun-testing/winio/idutil"
@@ -36,36 +41,71 @@ const (
IDENTITY_NOT_FOUND = 1000
)
-var delim = []byte("====")
+//var delim = []byte("====")
+const (
+ // see: https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-strings
+ // breaks down to
+ // "allow" - A (A;;
+ // "full access" - FA (A;;FA
+ // "well-known sid" - IU (A;;FA;;;IU)
+ InteractivelyLoggedInUser = "(A;;GRGW;;;IU)" //generic read/write. We will want to tune this to a specific group but that is not working with Windows 10 home at the moment
+ System = "(A;;FA;;;SY)"
+ BuiltinAdmins = "(A;;FA;;;BA)"
+ LocalService = "(A;;FA;;;LS)"
+)
func SubMain() {
-
+ errs := make(chan error)
+ term := make(chan os.Signal, 1)
config.InitLogger("debug")
+ //ensure the necessary group exists and the process has access to the group
+ // sid := runtime.EnsurePermissions(runtime.NF_GROUP_NAME) //will return the string or Fatal/Panic
+ // onlyNF := "S:(ML;;NW;;;LW)D:(A;;FA;;;" + sid + ")"
+ grps := []string{InteractivelyLoggedInUser, System, BuiltinAdmins, LocalService}
+ auth := "D:" + strings.Join(grps, "")
+
pc := winio.PipeConfig{
- SecurityDescriptor: "",
+ SecurityDescriptor: auth,
MessageMode: false,
- InputBufferSize: 0,
- OutputBufferSize: 0,
+ InputBufferSize: 1024,
+ OutputBufferSize: 1024,
}
- logs, err := winio.ListenPipe(logsPipeName, pc)
+ logs, err := winio.ListenPipe(logsPipeName, &pc)
if err != nil {
log.Panic(err)
}
go acceptLogs(logs)
- log.Info("log listener ready")
+ log.Info("log listener ready. pipe: %s", logsPipeName)
- ipc, err := winio.ListenPipe(ipcPipeName, nil)
+ pc2 := winio.PipeConfig{
+ SecurityDescriptor: auth,
+ MessageMode: false,
+ InputBufferSize: 1024,
+ OutputBufferSize: 1024,
+ }
+ ipc, err := winio.ListenPipe(ipcPipeName, &pc2)
if err != nil {
log.Panic(err)
}
go acceptIPC(ipc)
- log.Info("IPC listener ready")
+ log.Info("IPC listener ready pipe: %s", ipcPipeName)
initialize()
establishTun()
- <-finished
- <-finished
+
+ signal.Notify(term, os.Interrupt)
+ signal.Notify(term, os.Kill)
+ signal.Notify(term, syscall.SIGTERM)
+
+ select {
+ case <-term:
+ case <-errs:
+ }
+
+ windns.ResetDNS()
+
+ state.Close()
_ = ipc.Close()
_ = logs.Close()
}
@@ -73,17 +113,17 @@ func SubMain() {
func acceptIPC(p net.Listener) {
for {
c, err := p.Accept()
- log.Debugf("accepting a new client")
if err != nil {
panic(err)
}
+ log.Debugf("accepting a new client")
go serveIpc(c)
}
}
func initialize() {
- log.Debugf("reading config file located at %s:", config.File())
+ log.Debugf("reading config file located at : %s", config.File())
file, err := os.OpenFile(config.File(), os.O_RDONLY, 0640)
if err != nil {
// file does not exist or process has no rights to read the file - return leaving configuration empty
@@ -96,10 +136,12 @@ func initialize() {
_ = dec.Decode(&state)
+ // decide if the tunnel should be active or not and if so - activate it
+ setTunnelState(state.Active)
+
+ // connect any identities that are enabled
for _, id := range state.Identities {
- if id.Active {
- loadServices(id)
- }
+ connectIdentity(id)
}
err = file.Close()
@@ -140,13 +182,15 @@ func serveIpc(conn net.Conn) {
for {
log.Debug("beginning read")
msg, err := reader.ReadString('\n')
- if err != nil{
+ if err != nil {
respondWithError(enc, "could not read string properly", UNKNOWN_ERROR, err)
return
}
- os.Stdout.Write(delim)
- os.Stdout.Write([]byte(msg))
- os.Stdout.Write(delim)
+ /*
+ os.Stdout.Write(delim)
+ os.Stdout.Write([]byte(msg))
+ os.Stdout.Write(delim)
+ */
log.Debugf("msg received: %s", msg)
dec := json.NewDecoder(strings.NewReader(msg))
var cmd dto.CommandMsg
@@ -158,8 +202,21 @@ func serveIpc(conn net.Conn) {
switch cmd.Function {
case "AddIdentity":
+ addIdMsg, err := reader.ReadString('\n')
+ if err != nil {
+ respondWithError(enc, "could not read string properly", UNKNOWN_ERROR, err)
+ return
+ }
+ /*
+ os.Stdout.Write(delim)
+ os.Stdout.Write([]byte(addIdMsg))
+ os.Stdout.Write(delim)
+ */
+ log.Debugf("msg received: %s", addIdMsg)
+ addIdDec := json.NewDecoder(strings.NewReader(addIdMsg))
+
var newId dto.AddIdentity
- if err := dec.Decode(&newId); err == io.EOF {
+ if err := addIdDec.Decode(&newId); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
@@ -194,10 +251,10 @@ func acceptLogs(p net.Listener) {
log.Debug("beginning logs receive loop")
for {
l, err := p.Accept()
- log.Debug("accepted a connection, returning logs")
if err != nil {
panic(err)
}
+ log.Debug("accepted a connection, returning logs")
go serveLogs(l)
}
@@ -248,26 +305,55 @@ func reportStatus(out *json.Encoder) {
func tunnelState(onOff bool, out *json.Encoder) {
log.Debugf("toggle ziti on/off: %t", onOff)
- state.TunnelActive = onOff
+ if onOff == state.Active {
+ log.Debug("nothing to do. the state of the tunnel already matches the requested state: %t", onOff)
+ return
+ }
+ setTunnelState(onOff)
+ state.Active = onOff
runtime.SaveState(&state)
- //TODO: actually turn the tunnel on and off as well as handle errors
+
respond(out, dto.Response{Message: "tunnel state updated successfully", Code: SUCCESS, Error: "", Payload: nil})
log.Debugf("toggle ziti on/off: %t responded to", onOff)
}
+func setTunnelState(onOff bool) {
+ if state.Active == onOff {
+ log.Debugf("noop. tunnel state is already active: %t", onOff)
+ return
+ }
+
+ if onOff {
+ state.CreateTun()
+ runtime.TunStarted = time.Now()
+
+ for _, id := range state.Identities {
+ connectIdentity(id)
+ }
+ } else {
+ state.Close()
+ }
+}
+
func toggleIdentity(out *json.Encoder, fingerprint string, onOff bool) {
log.Debugf("toggle ziti on/off for %s: %t", fingerprint, onOff)
_, id := state.Find(fingerprint)
- id.Active = onOff
-
- if onOff {
- //enable the identity
- loadServices(id)
- } else {
- //clear out the services before returning
- id.Services = nil
+ if id.Active == onOff {
+ log.Debugf("nothing to do - the provided identity %s is already set to active=%t", id.Name, id.Active)
+ //nothing to do...
+ respond(out, dto.Response{
+ Code: SUCCESS,
+ Message: fmt.Sprintf("no update performed. identity is already set to active=%t", onOff),
+ Error: "",
+ Payload: nil,
+ })
+ return
}
+
+ id.Active = onOff
+ connectIdentity(id)
+
respond(out, dto.Response{Message: "identity toggled", Code: SUCCESS, Error: "", Payload: idutil.Clean(*id)})
log.Debugf("toggle ziti on/off for %s: %t responded to", fingerprint, onOff)
runtime.SaveState(&state)
@@ -278,7 +364,7 @@ func removeTempFile(file os.File) {
if err != nil {
log.Warnf("could not remove temp file: %s", file.Name())
}
- err = file.Close()
+ err = file.Close()
if err != nil {
log.Warnf("could not close the temp file: %s", file.Name())
}
@@ -351,7 +437,7 @@ func newIdentity(newId dto.AddIdentity, out *json.Encoder) {
if err != nil {
panic(err)
}
- newPath := config.Path() + newId.Id.FingerPrint + ".json"
+ newPath := newId.Id.Path()
//move the temp file to its final home after enrollment
err = os.Rename(enrolled.Name(), newPath)
@@ -391,8 +477,29 @@ func respondWithError(out *json.Encoder, msg string, code int, err error) {
}
func connectIdentity(id *dto.Identity) {
+ if !id.Active && !state.Active {
+ //clear out the services before returning
+ id.Services = nil
+ log.Infof("not connecting identity: %s as it is not active", id.Name)
+ return
+ }
+
+ if id.Connected {
+ log.Debugf("id: %s is already connected - not attempting to connect again fingerprint:%s", id.Name, id.FingerPrint)
+ return
+ }
+
//tell the c sdk to use the file from the id and connect
log.Infof("Connecting identity: %s", id.Name)
+
+ if ctx, err := cziti.LoadZiti(id.Path()); err != nil {
+ log.Panic(err)
+ } else {
+ log.Infof("successfully loaded %s@%s\n", ctx.Name(), ctx.Controller())
+ }
+
+ id.Connected = true
+
loadServices(id)
log.Infof("Connecting identity: %s responded to", id.Name)
}
@@ -406,12 +513,22 @@ func loadServices(id *dto.Identity) {
)
}
-func disconnectIdentity(id dto.Identity) error {
+func disconnectIdentity(id *dto.Identity) error {
//tell the c sdk to disconnect the identity/services etc
log.Infof("Disconnecting identity: %s", id.Name)
+ if id.Connected {
+ // actually disconnect from the c sdk here
+ log.Warn("not implemented yet - disconnected an already connected id doesn't actually work yet...")
+
+ return nil
+ id.Connected = false
+ } else {
+ log.Debugf("id: %s is already disconnected - not attempting to disconnected again fingerprint:%s", id.Name, id.FingerPrint)
+ }
+
//remove the file from the filesystem - first verify it's the proper file
- err := os.Remove(config.Path() + id.FingerPrint + ".json")
+ err := os.Remove(id.Path())
if err != nil {
log.Warn("could not remove file: %s", config.Path()+id.FingerPrint+".json")
}
@@ -426,7 +543,7 @@ func removeIdentity(out *json.Encoder, fingerprint string) {
return
}
- err := disconnectIdentity(*id)
+ err := disconnectIdentity(id)
if err != nil {
respondWithError(out, "Error when disconnecting identity", ERROR_DISCONNECTING_ID, err)
return
@@ -440,8 +557,9 @@ func removeIdentity(out *json.Encoder, fingerprint string) {
}
func respond(out *json.Encoder, thing interface{}) {
- os.Stdout.Write(delim)
+ /*os.Stdout.Write(delim)
_ = json.NewEncoder(os.Stdout).Encode(thing)
os.Stdout.Write(delim)
+ */
_ = out.Encode(thing)
}
diff --git a/wintun-testing/winio/main.go b/wintun-testing/winio/main.go
index dcf5e365..9038015d 100644
--- a/wintun-testing/winio/main.go
+++ b/wintun-testing/winio/main.go
@@ -5,5 +5,7 @@ import (
)
func main() {
+
ipc.SubMain()
+
}
diff --git a/wintun-testing/winio/runtime/package-variables.go b/wintun-testing/winio/runtime/package-variables.go
new file mode 100644
index 00000000..bd58533b
--- /dev/null
+++ b/wintun-testing/winio/runtime/package-variables.go
@@ -0,0 +1,25 @@
+package runtime
+
+import (
+ "github.com/michaelquigley/pfxlog"
+ "time"
+)
+
+const (
+ NF_GROUP_NAME = "NetFoundry Tunneler Users"
+ TunName = "ZitiTUN"
+)
+
+var log = pfxlog.Logger()
+var TunStarted time.Time
+
+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
+// : 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
diff --git a/wintun-testing/winio/runtime/permissions.go b/wintun-testing/winio/runtime/permissions.go
new file mode 100644
index 00000000..ddb4c612
--- /dev/null
+++ b/wintun-testing/winio/runtime/permissions.go
@@ -0,0 +1,39 @@
+package runtime
+
+import (
+ "github.com/netfoundry/ziti-foundation/util/stringz"
+ "os/user"
+)
+
+func EnsurePermissions(group string) string {
+ log.Infof("verifying process has access to the correct group: %s", group)
+
+ //check the current process is in this group
+ g, err := user.LookupGroup(group)
+ if err != nil || g == nil {
+ log.Fatalf("the necessary group [%s] was not found on this machine. ensure the group exists and start the process again.", group)
+ return "" //quiets the nil warning below even though this code won't get hit
+ }
+
+ sid := g.Gid
+ log.Debugf("sid for %s is %s", group, sid)
+
+ u, err := user.Current()
+ if err != nil || u == nil {
+ log.Fatal("could not acquire current user! user: %v %v", u, err)
+ return "" //quiets the nil warning below even though this code won't get hit
+ }
+
+ gr, err := u.GroupIds()
+ if err != nil {
+ log.Fatal("could not acquire groups for current user!", err)
+ }
+
+ if stringz.Contains(gr, sid) {
+ log.Debugf("user: %s is in the required group: %s", u.Username, NF_GROUP_NAME)
+ } else {
+ log.Fatalf("Token Membership Error: %s", err)
+ }
+
+ return sid
+}
\ No newline at end of file
diff --git a/wintun-testing/winio/runtime/state.go b/wintun-testing/winio/runtime/state.go
index 62ff3840..7f4d7141 100644
--- a/wintun-testing/winio/runtime/state.go
+++ b/wintun-testing/winio/runtime/state.go
@@ -3,26 +3,33 @@ package runtime
import (
"bufio"
"encoding/json"
- "github.com/michaelquigley/pfxlog"
+ "fmt"
+ "golang.zx2c4.com/wireguard/tun"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+ "net"
"os"
+ "time"
+ "wintun-testing/cziti"
"wintun-testing/winio/config"
"wintun-testing/winio/dto"
"wintun-testing/winio/idutil"
)
-var log = pfxlog.Logger()
-
type TunnelerState struct {
- TunnelActive bool
- Identities []*dto.Identity
- IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
+ Active bool
+ Duration int64
+ Identities []*dto.Identity
+ IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
+
+ tun tun.Device
+ tunName string
}
type TunIpInfo struct {
- Ip string
+ Ip string
Subnet string
- MTU uint16
- DNS string
+ MTU uint16
+ DNS string
}
func (t *TunnelerState) RemoveByFingerprint(fingerprint string) {
@@ -65,20 +72,101 @@ func SaveState(s *TunnelerState) {
_ = w.Flush()
err = cfg.Close()
- if err != nil{
+ if err != nil {
panic(err)
}
}
-func (s TunnelerState) Clean() TunnelerState {
- rtn := TunnelerState{
- TunnelActive: s.TunnelActive,
- Identities: make([]*dto.Identity, len(s.Identities)),
- IpInfo: s.IpInfo,
+func (t TunnelerState) Clean() TunnelerState {
+ var d int64
+ if t.Active {
+ now := time.Now()
+ dd := now.Sub(TunStarted)
+ d = dd.Milliseconds()
+ } else {
+ d = 0
}
- for i, id := range s.Identities {
+
+ rtn := TunnelerState{
+ Active: t.Active,
+ Duration: d,
+ Identities: make([]*dto.Identity, len(t.Identities)),
+ IpInfo: t.IpInfo,
+ }
+ for i, id := range t.Identities {
rtn.Identities[i] = idutil.Clean(*id)
}
return rtn
-}
\ No newline at end of file
+}
+
+func (t *TunnelerState) CreateTun() {
+ log.Infof("creating TUN device: %s", TunName)
+ tunDevice, err := tun.CreateTUN(TunName, 64*1024)
+ if err == nil {
+ t.tun = tunDevice
+ tunName, err2 := tunDevice.Name()
+ if err2 == nil {
+ t.tunName = tunName
+ }
+ } else {
+ log.Fatalf("error creating TUN device: (%v)", err)
+ }
+
+ if name, err := tunDevice.Name(); err == nil {
+ fmt.Printf("created TUN device [%s]\n", name)
+ }
+
+ nativeTunDevice := tunDevice.(*tun.NativeTun)
+ luid := winipcfg.LUID(nativeTunDevice.LUID())
+ ip, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ipv4ip, ipv4mask))
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("setting TUN interface address to [%s]\n", ip)
+ err = luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ dnsServers := []net.IP{
+ net.ParseIP(ipv4dns).To4(),
+ net.ParseIP(ipv6dns),
+ }
+ err = luid.AddDNS(dnsServers)
+ if err != nil {
+ log.Fatal(err)
+ }
+ dns, err := luid.DNS()
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("dns servers = ", dns)
+
+ fmt.Printf("routing destination [%s] through [%s]\n", *ipnet, ipnet.IP)
+ err = luid.SetRoutes([]*winipcfg.RouteData{{*ipnet, ipnet.IP, 0}})
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("routing applied")
+
+ fmt.Println("running")
+ cziti.DnsInit(ipv4ip, 24)
+
+ cziti.Start()
+ _, err = cziti.HookupTun(tunDevice, dns)
+ if err != nil {
+ panic(err)
+ }
+
+}
+
+func (t *TunnelerState) Close() {
+ cziti.Stop()
+ if t.tun != nil {
+ err := t.tun.Close()
+ if err != nil {
+ log.Fatalf("problem closing tunnel!")
+ }
+ }
+}
diff --git a/wintun-testing/ziti-wintun/main.go b/wintun-testing/ziti-wintun/main.go
index 7ec2aae9..81031796 100644
--- a/wintun-testing/ziti-wintun/main.go
+++ b/wintun-testing/ziti-wintun/main.go
@@ -7,19 +7,32 @@ import (
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"net"
"os"
- "os/exec"
"os/signal"
user2 "os/user"
"path/filepath"
"syscall"
"wintun-testing/cziti"
+ "wintun-testing/cziti/windns"
)
const bufferSize = 64 * 1024
+// TUN IPs
+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
+// : 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
+
func main() {
user, err := user2.Current()
- fmt.Printf("welcome to cziti-cli testing: [%v]\n", user)
+
+ fmt.Printf("user [%v]\n", user)
if len(os.Args) < 2 {
fmt.Printf("usage: %s \n", filepath.Base(os.Args[0]))
@@ -28,7 +41,7 @@ func main() {
interfaceName := os.Args[1]
fmt.Println("creating TUN device")
- tunDevice, err := tun.CreateTUN(interfaceName, 64 * 1024)
+ tunDevice, err := tun.CreateTUN(interfaceName, 64*1024)
if err == nil {
realInterfaceName, err2 := tunDevice.Name()
if err2 == nil {
@@ -46,7 +59,7 @@ func main() {
nativeTunDevice := tunDevice.(*tun.NativeTun)
luid := winipcfg.LUID(nativeTunDevice.LUID())
- ip, ipnet, err := net.ParseCIDR("169.254.1.1/24")
+ ip, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ipv4ip, ipv4mask))
if err != nil {
fatal(err)
}
@@ -55,7 +68,20 @@ func main() {
if err != nil {
fatal(err)
}
- fmt.Printf("TUN interface address set to [%s]\n", ip)
+
+ dnsServers := []net.IP{
+ net.ParseIP(ipv4dns).To4(),
+ net.ParseIP(ipv6dns),
+ }
+ err = luid.AddDNS(dnsServers)
+ if err != nil {
+ fatal(err)
+ }
+ dns, err := luid.DNS()
+ if err != nil {
+ fatal(err)
+ }
+ fmt.Println("dns servers = ", dns)
fmt.Printf("routing destination [%s] through [%s]\n", *ipnet, ipnet.IP)
err = luid.SetRoutes([]*winipcfg.RouteData{{*ipnet, ipnet.IP, 0}})
@@ -68,47 +94,19 @@ func main() {
term := make(chan os.Signal, 1)
fmt.Println("running")
- cziti.DnsInit("169.254.1.1", 24)
+ cziti.DnsInit(ipv4ip, 24)
cziti.Start()
- _, err = cziti.HookupTun(tunDevice)
+ _, err = cziti.HookupTun(tunDevice, dns)
if err != nil {
panic(err)
}
- cmd := exec.Command("netsh", "interface", "ipv4", "set",
- "dnsservers", "name="+interfaceName,
- "source=static", "address=169.254.1.253",
- "register=primary", "validate=no")
- cmd.Stderr = os.Stderr
- cmd.Stdout = os.Stdout
- err = cmd.Run()
- if err != nil {
- fmt.Print(err)
- }
-
if ctx, err := cziti.LoadZiti(os.Args[2]); err != nil {
panic(err)
} else {
fmt.Printf("successfully loaded %s@%s\n", ctx.Name(), ctx.Controller())
}
- //tunnel.AddIntercept("awesome sauce service", "169.254.1.42", 8080)
- /*
- for {
- buffer := make([]byte, bufferSize)
- n, err := tunDevice.Read(buffer, 0)
- if err != nil {
- fatal(err)
- }
- printPacket(buffer[:n])
-
- //fmt.Printf("read [%d] bytes [", n)
- //for i := 0; i < n; i++ {
- // fmt.Printf("%x ", buffer[i])
- //}
- //fmt.Println("]")
- }
- */
signal.Notify(term, os.Interrupt)
signal.Notify(term, os.Kill)
@@ -119,7 +117,8 @@ func main() {
case <-errs:
}
- _ = tunDevice.Close()
+ windns.ResetDNS()
+
fmt.Println("shutting down")
}