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") }