diff --git a/wintun-testing/.gitignore b/wintun-testing/.gitignore new file mode 100644 index 00000000..2eb53393 --- /dev/null +++ b/wintun-testing/.gitignore @@ -0,0 +1,4 @@ +build/ +install/ +*.exe +*.dll \ No newline at end of file diff --git a/wintun-testing/README.md b/wintun-testing/README.md new file mode 100644 index 00000000..14bf8003 --- /dev/null +++ b/wintun-testing/README.md @@ -0,0 +1,28 @@ +Building Windows Tunneler +------------------------- + +You'll need +=========== +* CMake - in `$PATH` or in standard location +* migw - `cgo` requires gcc/mingw +* ninja +* bash + +Setup +===== +checkout github.com/netfoundry/ziti-tunneler-sdk-c somewhere +```shell script +git clone --recurse-submodules github.com/netfoundry/ziti-tunneler-sdk-c +``` + +Build +===== +```shell script +$ export TUNNELER_SDK_DIR=[your checkout location from above] +$ ./build.sh +``` + +Running +======= +`ziti-wintun.exe` requires `ziti.dll` and `uv.dll`. Build script copies them to the same directory as executable. +If you copy/move executable don't forget to copy/move those DLLs. \ No newline at end of file diff --git a/wintun-testing/build.sh b/wintun-testing/build.sh new file mode 100644 index 00000000..d157a574 --- /dev/null +++ b/wintun-testing/build.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +die() { + echo "Error: $1" + exit 1 +} + +[ -z "$TUNNELER_SDK_DIR" ] && die 'set TUNNELER_SDK_DIR' + +if [[ $(type -P cmake) ]]; then + CMAKE=cmake +elif [ -x "/c/Program Files/Cmake/bin/cmake.exe" ]; then + echo "cmake found in standard location" + CMAKE='/c/Program Files/Cmake/bin/cmake.exe' +fi + +mkdir build +mkdir install + +if [[ ! -f ./build/CMakeCache.txt ]]; then + "${CMAKE}" -G Ninja -S ${TUNNELER_SDK_DIR} -B ./build -DCMAKE_INSTALL_PREFIX=./install +fi +"${CMAKE}" --build ./build --target install + +export CGO_CFLAGS="-DNOGDI -I $(cygpath -a -m ./install/include)" +export CGO_LDFLAGS="-L $(cygpath -a -m ./install/lib)" +go build ./ziti-wintun + diff --git a/wintun-testing/cziti/ctun.go b/wintun-testing/cziti/ctun.go new file mode 100644 index 00000000..1bfd40d7 --- /dev/null +++ b/wintun-testing/cziti/ctun.go @@ -0,0 +1,301 @@ +package cziti + +// +/* +#cgo LDFLAGS: -l ziti_tunneler -l lwipcore -l lwipwin32arch -l ziti_tunneler + +#include "nf/netif_driver.h" +#include +#include + +extern int netifClose(netif_handle dev); +extern ssize_t netifRead(netif_handle dev, void *buf, size_t buf_len); +extern ssize_t netifWrite(netif_handle dev, void *buf, size_t len); +extern int netifSetup(netif_handle dev, uv_loop_t *loop, packet_cb packetCb, void* ctx); + +extern tunneler_sdk_options* new_tun_opts(); +typedef struct netif_handle_s { + const char* id; + packet_cb on_packet_cb; + void *packet_cb_ctx; +} netif_handle_t; + +extern void* zitiDial(char *service_name, void *ziti_dial_ctx, tunneler_io_context tnlr_io_ctx); +extern void zitiClose(void *ziti_dial_ctx); +extern int zitiWrite(void *ziti_io_ctx, void *data, int len); +extern void readAsync(struct uv_async_s *a); + +extern void call_on_packet(void *packet, ssize_t len, packet_cb cb, void *ctx); +extern uv_async_t* new_async(); + +extern void dnsHandler(tunneler_io_context tio, void *ctx, addr_t src, uint16_t sport, void *data, ssize_t len); + */ +import "C" +import ( + "errors" + "fmt" + "github.com/miekg/dns" + "golang.zx2c4.com/wireguard/tun" + "net" + "strings" + "unsafe" +) + +const dnsIP = "169.254.1.253" + +type Tunnel interface { + AddIntercept(service string, hostname string, port int) +} + +type tunnel struct{ + dev tun.Device + driver C.netif_driver + writeQ chan []byte + readQ chan []byte + + read *C.uv_async_t + loop *C.uv_loop_t + onPacket C.packet_cb + onPacketCtx unsafe.Pointer + + tunCtx C.tunneler_context +} + +var devMap = make(map[string]*tunnel) + +func HookupTun(dev tun.Device) (Tunnel, error) { + fmt.Println("in HookupTun") + defer fmt.Println("exiting HookupTun") + name, err := dev.Name() + if err != nil { + fmt.Println(err) + return nil, err + } + drv := makeDriver(name) + + fmt.Println("in HookupTun2") + + t := &tunnel{ + dev: dev, + driver: drv, + writeQ: make(chan []byte), + readQ: make(chan []byte, 64), + } + devMap[name] = t + + opts := C.new_tun_opts() + opts.netif_driver = drv + opts.ziti_dial = C.ziti_dial_cb(C.zitiDial) + opts.ziti_close = C.ziti_close_cb(C.zitiClose) + opts.ziti_write = C.ziti_write_cb(C.zitiWrite) + + 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)); + + return t, nil +} + +func makeDriver(name string) C.netif_driver { + driver := &C.netif_driver_t{} + driver.handle = &C.netif_handle_t{} + driver.handle.id = C.CString(name) + driver.close = C.netif_close_cb(C.netifClose) + driver.setup = C.setup_packet_cb(C.netifSetup) + driver.write = C.netif_write_cb(C.netifWrite) + return driver +} + +//export netifWrite +func netifWrite(h C.netif_handle, buf unsafe.Pointer, length C.size_t) C.ssize_t { + t, found := devMap[C.GoString(h.id)] + if !found { + fmt.Errorf("should not be here\n") + return -1 + } + fmt.Println("netifWrite len=", length); + + b := C.GoBytes(buf, C.int(length)) + + t.writeQ <- b + + return C.ssize_t(len(b)) +} + +//export netifClose +func netifClose(h C.netif_handle) C.int { + fmt.Println("in netifClose"); + return C.int(0) +} + +//export netifSetup +func netifSetup(h C.netif_handle, l *C.uv_loop_t, packetCb C.packet_cb, ctx unsafe.Pointer) C.int { + t, found := devMap[C.GoString(h.id)] + if !found { + fmt.Errorf("should not be here\n") + return -1 + } + + t.read = C.new_async() + C.uv_async_init(l, t.read, C.uv_async_cb(C.readAsync)) + t.read.data = unsafe.Pointer(h) + fmt.Printf("in netifSetup netif[%s] handle[%p]\n", C.GoString(h.id), h) + + t.onPacket = packetCb + t.onPacketCtx = ctx + t.loop = l + + go t.runWriteLoop() + go t.runReadLoop() + + return C.int(0) +} + +func (t *tunnel)runReadLoop() { + mtu, err := t.dev.MTU() + if err != nil { + panic(err) + } + fmt.Printf("starting tun read loop mtu=%d\n", mtu) + defer fmt.Println("tun read loop is done") + for { + buf := make([]byte, mtu) + nr, err := t.dev.Read(buf,0) + if err != nil { + panic(err) + } + t.readQ <- buf[:nr] + C.uv_async_send((*C.uv_async_t)(unsafe.Pointer(t.read))) + } +} + +//export readAsync +func readAsync(a *C.uv_async_t) { + i := 0 + + dev := (*C.netif_handle_t)(a.data) + + id := C.GoString(dev.id) + t, found := devMap[id] + if !found { + fmt.Printf("should not be here id = [%s]\n", id) + panic(errors.New("where is my tunnel?")) + } + + for len(t.readQ) > 0 { + b := <- t.readQ + buf := C.CBytes(b) + C.call_on_packet(buf, C.ssize_t(len(b)), t.onPacket, t.onPacketCtx) + C.free(buf) + i++ + } +} + + +func (t *tunnel) runWriteLoop() { + fmt.Printf("starting Write Loop\n") + defer fmt.Println("write loop finished") + for { + select { + case p := <-t.writeQ: + if p == nil { + return + } + + n, err := t.dev.Write(p, 0) + if err != nil { + panic(err) + } + + if n < len(p) { + fmt.Println("Error short write") + } + } + } + +} + +func (t *tunnel) AddIntercept(service string, host string, port int) { + res := C.NF_tunneler_intercept_v1(t.tunCtx, unsafe.Pointer(nil), C.CString(service), C.CString(host), C.int(port)) + fmt.Println("intercept added", res) +} + +// 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) + } + + 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, + } + 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))) + if rc != 0 { + fmt.Println("NF_udp_reply rc=", rc) + } + } else { + fmt.Println("dns message error", err) + } +} + +/*******************************************************************/ +//export zitiDial +func zitiDial(service *C.char, ziti_dial_ctx unsafe.Pointer, tio C.tunneler_io_context) unsafe.Pointer { + fmt.Println("received dial request for ", C.GoString(service)) + defer fmt.Println("dial finished") + msg := []byte("welcome to Canadian translator\n") + + msgC := C.CBytes(msg) + C.NF_tunneler_write(tio, msgC, C.int(len(msg))) + // C.free(msgC) + + return unsafe.Pointer(tio) +} + +//export zitiClose +func zitiClose(ziti_dial_ctx unsafe.Pointer) { + fmt.Println("in zitiClose") +} + +//export zitiWrite +func zitiWrite(zio unsafe.Pointer, data unsafe.Pointer, length C.int) C.int { + msg := strings.TrimSpace(string(C.GoBytes(data, length))) + + reply := []byte(fmt.Sprint(msg, ", eh?\n")) + + replyC := C.CBytes(reply) + C.NF_tunneler_write(C.tunneler_io_context(zio), replyC, C.int(len(reply))) + //C.free(replyC) + + return C.ZITI_CONNECTED +} \ No newline at end of file diff --git a/wintun-testing/cziti/cziti-cli/main.go b/wintun-testing/cziti/cziti-cli/main.go new file mode 100644 index 00000000..6acecdb4 --- /dev/null +++ b/wintun-testing/cziti/cziti-cli/main.go @@ -0,0 +1,111 @@ +package main + +import "C" +import ( + "bufio" + "errors" + "fmt" + "os" + "strconv" + "strings" + "wintun-testing/cziti" +) + +func main() { + cziti.Start() + + fmt.Println("welcome to cziti-cli testing") + fmt.Println("----------------------------") + fmt.Println() + + reader := bufio.NewReader(os.Stdin) + for { + fmt.Print("-> ") + text, _ := reader.ReadString('\n') + + text = strings.TrimSpace(text) + cmd := strings.Split(text, " ") + + if f, found := commands[cmd[0]]; found { + err := f(cmd[1:]) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "error: %v", err) + } + fmt.Println() + } else { + fmt.Printf("command `%s' is not found\n", cmd[0]) + } + } +} + +var commands = make(map[string]func([]string)error) + +func init() { + commands["quit"] = quit + commands["help"] = help + commands["list"] = list + commands["load"] = load + commands["show-services"] = showServices +} + +func showServices(args []string) error { + if len(args) == 0 { + return errors.New("select context") + } + + idx, err := strconv.Atoi(args[0]) + if err != nil { + return err + } + + if idx >= len(contexts) { + return errors.New("invalid reference") + } + + ctx := contexts[idx] + + fmt.Printf("services available to %s@%s\n", ctx.Name(), ctx.Controller()) + for _, s := range *ctx.Services { + fmt.Printf("\t%+v\n", s) + } + return nil +} + +func quit(_ []string) error { + cziti.Stop() + os.Exit(0) + return nil +} + +func help(_[]string) error { + fmt.Println("available commands:") + for k, _ := range commands { + fmt.Println("\t", k) + } + return nil +} + +var contexts []*cziti.CZitiCtx + +func load(args []string) error { + if len(args) == 0 { + return fmt.Errorf("path to configfile required") + } + + if ctx, err := cziti.LoadZiti(args[0]); err != nil { + return err + } else { + fmt.Printf("successfully loaded %s@%s\n", ctx.Name(), ctx.Controller()) + contexts = append(contexts, ctx) + } + + return nil +} + +func list(args []string) error { + fmt.Println("loaded ziti identities:") + for i, c := range contexts { + 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.go b/wintun-testing/cziti/dns.go new file mode 100644 index 00000000..e7b1484e --- /dev/null +++ b/wintun-testing/cziti/dns.go @@ -0,0 +1,111 @@ +package cziti + +import ( + "encoding/binary" + "errors" + "fmt" + "net" + "sync" + "sync/atomic" +) + +type DnsManager interface { + Resolve(dnsName string) net.IP + + RegisterService(dnsName string, port uint16, ctx *CZitiCtx, name string) (net.IP, error) + DeregisterService(ctx *CZitiCtx, name string) + GetService(ip net.IP, port uint16) (*CZitiCtx, string, error) +} +const defaultCidr = "169.254.0.0" +const defaultMaskBits = 16 + +var initOnce = sync.Once{} +var DNS = &dnsImpl{} + +type dnsImpl struct { + cidr uint32 + counter uint32 + + serviceMap map[string]ctxService + + // dnsName -> ip address + hostnameMap map[string]net.IP + // ipv4 -> dnsName + ipMap map[uint32]string +} + +type ctxService struct { + ctx *CZitiCtx + name string +} + +func (dns *dnsImpl) RegisterService(dnsName string, port uint16, ctx *CZitiCtx, name string) (net.IP, error) { + DnsInit(defaultCidr, defaultMaskBits) + dnsName = dnsName + "." + key := fmt.Sprint(dnsName, ':', port) + if cs, found := dns.serviceMap[key]; found { + if cs.ctx != ctx || cs.name != name { + return nil, fmt.Errorf( + "service mapping conflict: %s:%d is already mapped for another context", dnsName, port) + } + return dns.hostnameMap[dnsName], nil + } + + dns.serviceMap[key] = ctxService{ + ctx: ctx, + name: name, + } + + if ip, mapped := dns.hostnameMap[dnsName]; mapped { + return ip, nil + } + + nextAddr := dns.cidr | atomic.AddUint32(&dns.counter, 1) + nextIp := make(net.IP, 4) + binary.BigEndian.PutUint32(nextIp, nextAddr) + dns.hostnameMap[dnsName] = nextIp + dns.ipMap[nextAddr] = dnsName + + return nextIp, nil +} + +func (dns *dnsImpl)Resolve(dnsName string) net.IP { + return dns.hostnameMap[dnsName] +} + +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) + return + } + } +} + +func (this *dnsImpl)GetService(ip net.IP, port uint16) (*CZitiCtx, string, error) { + ipv4 := binary.BigEndian.Uint32(ip) + dns, found := this.ipMap[ipv4] + if !found { + return nil, "", errors.New("service not available") + } + + key := fmt.Sprint(dns, ':', port) + sc, found := this.serviceMap[key] + if !found { + return nil, "", errors.New("service not available") + } + return sc.ctx, sc.name, nil +} + +func DnsInit(ip string, maskBits int) { + initOnce.Do(func() { + DNS.serviceMap = make(map[string]ctxService) + DNS.ipMap = make(map[uint32]string) + DNS.hostnameMap = make(map[string]net.IP) + i := net.ParseIP(ip).To4() + mask := net.CIDRMask(maskBits, 32) + DNS.cidr = binary.BigEndian.Uint32(i) & binary.BigEndian.Uint32(mask) + DNS.counter = 2 + }) +} + diff --git a/wintun-testing/cziti/sdk.c b/wintun-testing/cziti/sdk.c new file mode 100644 index 00000000..19666874 --- /dev/null +++ b/wintun-testing/cziti/sdk.c @@ -0,0 +1,59 @@ + +#include "sdk.h" +#include +#include + +libuv_ctx* new_libuv_ctx() { + return calloc(1, sizeof(libuv_ctx)); +} +void libuv_stopper(uv_async_t *a) { + uv_stop(a->loop); +} +void libuv_init(libuv_ctx *lctx) { + lctx->l = uv_default_loop(); + uv_async_init(lctx->l, &lctx->stopper, libuv_stopper); +} +void libuv_runner(void *arg) { + init_debug(); + printf("starting event loop\n"); + fflush(stdout); + uv_loop_t *l = arg; + uv_run(l, UV_RUN_DEFAULT); + + printf("event finished finished\n"); + +} + +void libuv_run(libuv_ctx *lctx) { + uv_thread_create(&lctx->t, libuv_runner, lctx->l); +} +void libuv_stop(libuv_ctx *lctx) { + uv_async_send(&lctx->stopper); + int err = uv_thread_join(&lctx->t); + if (err) { + fprintf(stderr, "%d: %s\n", err, uv_strerror(err)); + } +} + +extern void initCB(nf_context nf, int status, void *ctx); +extern void _init_cb(nf_context nf, int status, void *ctx) { +initCB(nf, status, ctx); +} + +static const char* _all[] = { + "all", NULL +}; + +const char** all_configs = _all; + +extern tunneler_sdk_options* new_tun_opts() { + return calloc(1, sizeof(tunneler_sdk_options)); +} + +extern void call_on_packet(const char *packet, ssize_t len, packet_cb cb, void *ctx) { + cb(packet, len, ctx); +} + +extern uv_async_t* new_async() { +return calloc(1, sizeof(uv_async_t)); +} \ No newline at end of file diff --git a/wintun-testing/cziti/sdk.go b/wintun-testing/cziti/sdk.go new file mode 100644 index 00000000..37266f09 --- /dev/null +++ b/wintun-testing/cziti/sdk.go @@ -0,0 +1,156 @@ +package cziti +/* +#cgo windows LDFLAGS: -l libziti.imp -luv -lws2_32 -lpsapi + +#include "sdk.h" +extern void initCB(nf_context nf, int status, void *ctx); +extern void serviceCB(nf_context nf, ziti_service*, int status, void *ctx); + */ +import "C" +import ( + "encoding/json" + "errors" + "fmt" + "unsafe" +) + +type sdk struct { + libuvCtx *C.libuv_ctx +} + +var _impl sdk + +func init() { + _impl.libuvCtx = C.new_libuv_ctx() + C.libuv_init(_impl.libuvCtx) +} + +func Start() { + v := C.NF_get_version() + fmt.Printf("starting ziti-sdk-c %s(%s)[%s]\n", + C.GoString(v.version), C.GoString(v.revision), C.GoString(v.build_date)) + + _impl.run() +} + +func (inst *sdk) run() { + C.libuv_run(inst.libuvCtx) +} + +func Stop() { + C.libuv_stop(_impl.libuvCtx) +} + +type Service struct { + Name string + Id string + InterceptHost string + InterceptPort int +} + +type CZitiCtx struct { + options C.nf_options + nf C.nf_context + + Services *map[string]Service +} + +func (c *CZitiCtx) Name() string { + return C.GoString(C.NF_get_identity(c.nf).name) +} + +func (c *CZitiCtx) Controller() string { + return C.GoString(C.NF_get_controller(c.nf)) +} + +var tunCfgName = C.CString("ziti-tunneler-client.v1") + +//export serviceCB +func serviceCB(nf C.nf_context, service *C.ziti_service, status C.int, data unsafe.Pointer) { + ctx := (*CZitiCtx)(data) + + fmt.Printf("%+v\n", ctx) + if ctx.Services == nil { + m := make(map[string]Service) + ctx.Services = &m + } + fmt.Printf("%+v\n", ctx) + + + name := C.GoString(service.name) + if status == C.ZITI_SERVICE_UNAVAILABLE { + DNS.DeregisterService(ctx, name) + delete(*ctx.Services, name) + } else if status == C.ZITI_OK { + cfg := C.ziti_service_get_raw_config(service, tunCfgName) + + host := "" + port := -1 + if cfg != nil { + var c map[string]interface{} + + if err := json.Unmarshal([]byte(C.GoString(cfg)), &c); err == nil { + host = c["hostname"].(string) + port = int(c["port"].(float64)) + } + } + (*ctx.Services)[name] = Service{ + Name: name, + Id: C.GoString(service.id), + InterceptHost: host, + InterceptPort: port, + } + if host != "" && port != -1 { + ip, err := DNS.RegisterService(host, uint16(port), ctx, name) + if err != nil { + fmt.Println(err) + } else { + fmt.Printf("service[%s] is mapped to <%s:%d>\n", name, ip.String(), port) + } + } + } +} + +//export initCB +func initCB(nf C.nf_context, status C.int, data unsafe.Pointer) { + ctx := (*CZitiCtx)(data) + fmt.Printf("status %d: ctx = %+v, nf = %+v\n", status, ctx, nf) + ctx.nf = nf + ctx.options.ctx = data + cfg := C.GoString(ctx.options.config) + if ch, ok := initMap[cfg]; ok { + ch <- ctx + } else { + fmt.Printf("respose channel not found\n") + } +} + +var initMap = make(map[string]chan interface{}) + +func zitiError(code C.int) error { + return errors.New(C.GoString(C.ziti_errorstr(code))) +} + +func LoadZiti(cfg string) (*CZitiCtx, error) { + ctx := CZitiCtx{} + ctx.options.config = C.CString(cfg) + ctx.options.init_cb = C.nf_init_cb(C.initCB) + ctx.options.service_cb = C.nf_service_cb(C.serviceCB) + ctx.options.refresh_interval = C.int(10) + ctx.options.config_types = C.all_configs + //ctx.options.ctx = unsafe.Pointer(&ctx) + + ch := make(chan interface{}) + initMap[cfg] = ch + rc := C.NF_init_opts(&ctx.options, _impl.libuvCtx.l, unsafe.Pointer(&ctx)) + if rc != C.ZITI_OK { + return nil, zitiError(rc) + } + + res := <- ch + + if c, ok := res.(*CZitiCtx); ok { + return c, nil + } + return nil, res.(error) +} diff --git a/wintun-testing/cziti/sdk.h b/wintun-testing/cziti/sdk.h new file mode 100644 index 00000000..8e9f4ca2 --- /dev/null +++ b/wintun-testing/cziti/sdk.h @@ -0,0 +1,29 @@ +#include +#include +#define USING_ZITI_SHARED +#include +#include + + +typedef struct cziti_ctx_s { + nf_options opts; + nf_context nf; + uv_async_t async; +} cziti_ctx; + +typedef struct libuv_ctx_s { + uv_loop_t *l; + uv_thread_t t; + uv_async_t stopper; +} libuv_ctx; + +libuv_ctx* new_libuv_ctx(); +void libuv_stopper(uv_async_t *a); +void libuv_init(libuv_ctx *lctx); +void libuv_runner(void *arg); +void libuv_run(libuv_ctx *lctx); +void libuv_stop(libuv_ctx *lctx); + +extern void _init_cb(nf_context nf, int status, void *ctx); + +extern const char** all_configs; \ No newline at end of file diff --git a/wintun-testing/go.mod b/wintun-testing/go.mod index 4388ec43..03dfb297 100644 --- a/wintun-testing/go.mod +++ b/wintun-testing/go.mod @@ -3,6 +3,7 @@ module wintun-testing go 1.14 require ( + github.com/miekg/dns v1.1.29 golang.org/x/sys v0.0.0-20200406113430-c6e801f48ba2 golang.zx2c4.com/wireguard v0.0.20200320 golang.zx2c4.com/wireguard/windows v0.1.0 diff --git a/wintun-testing/go.sum b/wintun-testing/go.sum index 5ed8cdb5..31b9b557 100644 --- a/wintun-testing/go.sum +++ b/wintun-testing/go.sum @@ -1,16 +1,25 @@ github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= +github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= +github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200301040627-c5d0d7b4ec88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -21,6 +30,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3-0.20191230102452-929e72ca90de h1:aYKJLPSrddB2N7/6OKyFqJ337SXpo61bBuvO5p1+7iY= golang.org/x/text v0.3.3-0.20191230102452-929e72ca90de/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wireguard v0.0.20200122-0.20200214175355-9cbcff10dd3e/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4= golang.zx2c4.com/wireguard v0.0.20200320 h1:1vE6zVeO7fix9cJX1Z9ZQ+ikPIIx7vIyU0o0tLDD88g= golang.zx2c4.com/wireguard v0.0.20200320/go.mod h1:lDian4Sw4poJ04SgHh35nzMVwGSYlPumkdnHcucAQoY= diff --git a/wintun-testing/ziti-wintun/main.go b/wintun-testing/ziti-wintun/main.go index 2601a95c..7077b2b0 100644 --- a/wintun-testing/ziti-wintun/main.go +++ b/wintun-testing/ziti-wintun/main.go @@ -7,10 +7,12 @@ import ( "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "net" "os" + "os/exec" "os/signal" user2 "os/user" "path/filepath" "syscall" + "wintun-testing/cziti" ) const bufferSize = 64 * 1024 @@ -20,7 +22,7 @@ func main() { fmt.Printf("user [%v]\n", user) - if len(os.Args) != 2 { + if len(os.Args) < 2 { fmt.Printf("usage: %s \n", filepath.Base(os.Args[0])) os.Exit(1) } @@ -38,13 +40,14 @@ func main() { fmt.Printf("error creating TUN device: (%v)\n", err) os.Exit(1) } + 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("169.254.100.200/32") + ip, ipnet, err := net.ParseCIDR("169.254.1.1/24") if err != nil { fatal(err) } @@ -66,20 +69,48 @@ func main() { term := make(chan os.Signal, 1) fmt.Println("running") + cziti.DnsInit("169.254.1.1", 24) - for { - buffer := make([]byte, bufferSize) - n, err := tunDevice.Read(buffer, 0) - if err != nil { - fatal(err) - } - fmt.Printf("read [%d] bytes [", n) - for i := 0; i < n; i++ { - fmt.Printf("%x ", buffer[i]) - } - fmt.Println("]") + cziti.Start() + _, err = cziti.HookupTun(tunDevice) + 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) signal.Notify(term, syscall.SIGTERM)