Merge branch 'svc-comms' of https://github.com/netfoundry/ziti-windows-uwp into svc-comms

This commit is contained in:
Jeremy Tellier - ROG
2020-04-27 02:07:30 +01:00
18 changed files with 696 additions and 173 deletions
+5
View File
@@ -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) {
+2 -23
View File
@@ -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;
}
}
}
+6
View File
@@ -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
+2 -1
View File
@@ -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
+14 -47
View File
@@ -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)
}
*/
}
/*******************************************************************/
+3 -3
View File
@@ -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
}
}
+202
View File
@@ -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)
}
}
}
}
}
+6 -6
View File
@@ -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
})
}
+73
View File
@@ -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)
}
}
+8
View File
@@ -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=
+12 -1
View File
@@ -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
}
}
func (id *Identity) Path() string {
if id.FingerPrint == "" {
log.Fatalf("fingerprint is invalid for id %s", id.Name)
}
return config.Path() + id.FingerPrint + ".json"
}
@@ -4,7 +4,7 @@
<working_directory value="$PROJECT_DIR$" />
<go_parameters value="-i" />
<envs>
<env name="PATH" value="v:\dev\tools\mingw-w64\bin" />
<env name="PATH" value="v:\dev\tools\mingw-w64\bin;c:\windows\system32" />
<env name="PFXLOG_NO_JSON" value="true" />
</envs>
<kind value="FILE" />
+156 -38
View File
@@ -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)
}
+2
View File
@@ -5,5 +5,7 @@ import (
)
func main() {
ipc.SubMain()
}
@@ -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
// <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
@@ -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
}
+105 -17
View File
@@ -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
}
}
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!")
}
}
}
+35 -36
View File
@@ -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
// <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
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 <interfaceName>\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")
}