Giter Site home page Giter Site logo

jwhited / wgsd Goto Github PK

View Code? Open in Web Editor NEW
765.0 765.0 72.0 178 KB

A CoreDNS plugin that provides WireGuard peer information via DNS-SD semantics

Home Page: https://www.jordanwhited.com/posts/wireguard-endpoint-discovery-nat-traversal/

License: MIT License

Go 100.00%
coredns-plugin mesh-networks nat-traversal service-discovery udp-hole-punching wireguard

wgsd's People

Contributors

bganne avatar dependabot[bot] avatar julienbalestra avatar jwhited avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wgsd's Issues

Some questions on setup and clarifications of the DNS service configuration

First off, thanks for the writeup.

I've been looking into how to establish direct peer to peer connections between nodes without a concentrator node, and this really helps.

I have a couple of questions on the configuration you've mentioned in your blog post.

  1. When launching wgsd-client you're passing the parameter -dns=4.4.4.4:5353. But the zone record config earlier is mapped to .:53. Is this a typo, or is there something I missed about exposing the dns server on 5353?

  2. If I'm understanding this right, the DNS server resolver port has to be publicly accessible to allow the clients to resolve the peer IPs. Is this correct?

If yes, then is there a way to have it so that the DNS server is only available over the wireguard connection and therefore private to the nodes on the network? It would be more secure to ensure that node IP data is kept private to only those authorized to connect to the network.

Sorry, I just re-read your post and you're asking these questions as well, so its redundant atm.

Will play around with this to see if we can get the resolver to work over the tunnel.

same network discovery

What happens if both peers are on the same network, i.e. behind the same router/gateway/nat?
Would it be possible to figure this out by e.g. adding something unique about the network (gateway mac address? gateway public ip?) to the dns record and resolving to the all LAN IP addresses on that network so that peers could try to discover each other in a LAN?
Another option would be SSDP but then you would have to patch into a systems SSDP server like avahi.

No DNS record when CoreDNS running as a service

I am running CoreDNS as a service following instructions at https://akai-tsuki.hatenablog.com/entry/2018/08/19/000000 .

When I query for peers with dig @10.0.0.254 -p 5353 _wireguard._udp.example.org. PTR +noall +answer +additional, I get no DNS records in response, but the request is received by the plugin. Here is the service log:

Dec 12 19:03:13 WGtest1 systemd[1]: Started CoreDNS DNS server.
Dec 12 19:03:15 WGtest1 coredns[708]: .:5353 on 10.0.0.254
Dec 12 19:03:15 WGtest1 coredns[708]: CoreDNS-1.8.0
Dec 12 19:03:15 WGtest1 coredns[708]: linux/amd64, go1.15.6,
Dec 12 19:06:32 WGtest1 coredns[708]: [DEBUG] plugin/wgsd: received query for: _wireguard._udp. type: PTR

If I stop the service and start CoreDNS with /usr/bin/coredns -conf=/etc/coredns/Corefile, I get a correct list of peers.

You can setup a server to reproduce this issue with the following script: https://gist.github.com/alessionossa/5c3d839330571559df37643eeccb2a07 (replacing keys)

(Is running as a service the right way to use CoreDNS? It’s the first time I use it)

Publish macOS binaries for Releases

I successfully build wgsd-client for macOS and I have been using it for a long time, however, it's a lot of work to download an updated version of the code and build it every time there is an update. It would be a very appreciated addition to build for macOS too - GitHub Actions supports this.

Server panic when using wgsd-client

Corefile:

.:5353 {
        debug
        wgsd japuba.net.br wg0 {
            self
        }
}

Server output:

./coredns
.:5353
CoreDNS-1.8.0
linux/arm, go1.15.6, 
[DEBUG] plugin/wgsd: received query for: mql7ok6ufp76w6t3xf22vvkygx4x22gdka4ayhn76poqtkplxm3q====._wireguard._udp. type: SRV
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x119c0e4]

goroutine 58 [running]:
github.com/jwhited/wgsd.getHostRR(0x420c960, 0x57, 0x0, 0x1, 0x458e101)
        /home/alarm/downloads/wgsd/wgsd.go:232 +0x14
github.com/jwhited/wgsd.handleSRV(0x422f5e0, 0x1739fa8, 0x411ff50, 0x412ac10, 0xe, 0x0, 0x420c960, 0x57, 0x0, 0x0, ...)
        /home/alarm/downloads/wgsd/wgsd.go:106 +0x198
github.com/jwhited/wgsd.(*WGSD).ServeDNS(0x44c6760, 0x1733540, 0x42ea360, 0x1739fa8, 0x411ff50, 0x422f5e0, 0x1b710, 0x411ff40, 0x10)
        /home/alarm/downloads/wgsd/wgsd.go:227 +0x2c8
github.com/coredns/coredns/core/dnsserver.(*Server).ServeDNS(0x44cb080, 0x1733540, 0x42ea360, 0x1739fa8, 0x411ff50, 0x422f5e0)
        /home/alarm/go/pkg/mod/github.com/coredns/[email protected]/core/dnsserver/server.go:289 +0x3b4
github.com/coredns/coredns/core/dnsserver.(*Server).ServePacket.func1(0x173ae18, 0x4480960, 0x422f5e0)
        /home/alarm/go/pkg/mod/github.com/coredns/[email protected]/core/dnsserver/server.go:126 +0x80
github.com/miekg/dns.HandlerFunc.ServeDNS(0x41ea030, 0x173ae18, 0x4480960, 0x422f5e0)
        /home/alarm/go/pkg/mod/github.com/miekg/[email protected]/server.go:37 +0x34
github.com/miekg/dns.(*Server).serveDNS(0x41f20a0, 0x40e4200, 0x68, 0x200, 0x4480960)
        /home/alarm/go/pkg/mod/github.com/miekg/[email protected]/server.go:617 +0x298
github.com/miekg/dns.(*Server).serveUDPPacket(0x41f20a0, 0x41e8060, 0x40e4200, 0x68, 0x200, 0x44c8368, 0x411ff10)
        /home/alarm/go/pkg/mod/github.com/miekg/[email protected]/server.go:557 +0x98
created by github.com/miekg/dns.(*Server).serveUDP
        /home/alarm/go/pkg/mod/github.com/miekg/[email protected]/server.go:487 +0x1fc

Client output:

./wgsd-client -device wg0 -dns 10.34.33.2:5353 -zone japuba.net.br
2021/01/06 22:52:28 [ZBf3K9Qr/+t6e7l1qtVYNfl9aMNQOAwdv/PdCanruzc=] failed to lookup SRV: read udp 10.34.33.10:45163->10.34.33.2:5353: i/o timeout
2021/01/06 22:52:28 [RP2teEPOF6La6jkqUGt/zXeiYRLdwYnbNNdqV7898RE=] failed to lookup SRV: read udp 10.34.33.10:41977->10.34.33.2:5353: read: connection refused
2021/01/06 22:52:29 [h4E4dbJoTSwfQGtudK+qmSUjd0hhR3zPTYs8tDbW21Q=] failed to lookup SRV: read udp 10.34.33.10:47761->10.34.33.2:5353: read: connection refused
2021/01/06 22:52:29 [OxmA/ZUQlTWrRSV+2QLyPb9AS6YkeB3ZSYGLcH8zBl4=] failed to lookup SRV: read udp 10.34.33.10:55267->10.34.33.2:5353: read: connection refused
2021/01/06 22:52:29 [EYu9sqfU/7ebk/dYWQ4y4UxYve/PGPwNSdOipVpIqEY=] failed to lookup SRV: read udp 10.34.33.10:46015->10.34.33.2:5353: read: connection refused

update docs & release

  • support of TXT data w/public key and allowed-ips
  • support serving data about self and overriding endpoint/allowed-ips
  • support multiple instances of plugin

Add a "retrieve all" mode for wgsd-client

Adding a "retrieve all" mode, and trigger it via -mode all flag. This will allow the registry to act as a peer distributor, greatly reducing the effort for building a mesh-based network.

This mode will make wgsd an all-in-one solution to replace n2n fully, and replace Tailscale to a certain extent.

Explanation of authoritative server

This tool looks amazing, I am looking forward to using it to enable a kick-ass road-warrior set-up that enable me to have access to multiple sites with the click of a button. All with greater reliability and performance than my current hub and spokes model.

I just had a question from the readme that I'm not sure about.

In the readme, you say

ZONE is the zone name wgsd should be authoritative for, e.g. example.com.

In terms of set-up what does this actually entail? Do I have to ensure that the registry is an authoritative name server? Ensure that example.com is not registered elsewhere?

Edit:
Looking at the code, it looks as if ZONE could be anything, even a domain I don't own as long as it was configured the same in corefile and wg-client? Or will coredns forward the query if it knows about a true authoritative server for the address?

Run wgsd-client as daemon

For now, this is just a one-time script to establish connections between fairly stable positioned devices. What if one is a mobile device that will change addresses frequently? Apparently, wgsd needs to run in a daemon mode to adapt to changes. Also for now wgsd just write IP:PORT pairs to those already registered endpoints. It would be nice to have a mode propagate all endpoints connected to the registry(especially for small private networks) automatically. Since the DNS already has a query for all endpoints, I don't really see any obstacles in implementing such a mode

Exclude some peers from being propogated

In order to see why this might be useful I need to explain the use-case.

Several sites (some with and without NATs) and a cloud hosted registry server all connect via a wgsd generated mesh - great 👍

Now some road-warriors want access to the networks and devices within the mesh and have their internet traffic encrypted. So their wireguard clients are added to the most readily accessible and fastest node on the mesh - the registry.

But now this very mobile device is being propagated by wgsd and all mesh members are listing it as a peer, but the device is not returning the favour as it is not running wgsd-client.

Now having a load of redundant peers on each mesh node is not the end of the world but it would be neat if there was a way to specify peers that should not be propagated by wgsd - allowing these road-warrior devices to be spikes off one node of the mesh.

I understand this could be done with a separate wireguard interface on the registry that is then bridged but the forwarding/routing of all the AllowedIPs would get confusing.

How to use the wgsd on Windows

hi,

I've been trying to use the wgsd recently, and I understand how to use it on linux.But I have trouble using it under windows.

DEVICE is the name of the WireGuard interface, e.g. wg0

can you tell me how to set 'DEVICE' on windows?
Thanks.

Usage without wgsd-client for e.g. iOS / Android

I was wondering, if this could even work with vanilla WireGuard clients only. At least for iOS there is no way to get wgsd-client without building an own app.

So why not using fixed udp source ports, and DNS records with short TTL?

For example Alice's config could look like:

[Interface]
Address = 10.0.0.1/32
PrivateKey = 0CtieMOYKa2RduPbJss/Um9BiQPSjgvHW+B7Mor5OnE=
ListenPort = 51820
DNS = 10.0.0.254

# Registry
[Peer]
PublicKey = JeZlz14G8tg1Bqh6apteFCwVhNhpexJ19FDPfuxQtUY=
Endpoint = 4.4.4.4:51820
PersistentKeepalive = 5
AllowedIPs = 10.0.0.254/32

# Bob
[Peer]
PublicKey = syKB97XhGnvC+kynh2KqQJPXoOoOpx/HmpMRTc+r4js=
Endpoint = YUTRLED535IGKL7BDLERL6M4VJXSXM3UQQPL4NMSN27MT56AD4HA====._wireguard._udp.<zone>:51820
PersistentKeepalive = 5
AllowedIPs = 10.0.0.2/32

I'm completely fine with doing any possible quirk on the registry, also further config on "Server-Peers" is possible. Even relaying or WG over WG would be okish. But not touching the mobile clients. Also I'm aware that we're building poor man's tailscale / headscale here.

Can wgsd work properly in the Symmetric NAT scenario?

According to STUN RFC 3489:

Symmetric: A symmetric NAT is one where all requests from the same internal IP address and port, to a specific destination IP address and port, are mapped to the same external IP address and port. If the same host sends a packet with the same source address and port, but to a different destination, a different mapping is used. Furthermore, only the external host that receives a packet can send a UDP packet back to the internal host.

In the Symmetric NAT scenario, when Alice accesses Bob and Registry respectively, Alice's external IP and port may be different because of the different destinations. I wonder if wgsd works properly in this scenario. Thanks!

Security question: can peer information be queried without the public key?

I just found this project, and it looks like it solves an important problem for me (fully open source tail scale alternative). However, I didn't understand from the post how peer information is secured. Could an adversary theoretically connect to the registry and then directly to a peer just by issuing the registry a DNS query from the open internet?

If so, you'd basically be able to scan the entire IPv4 space for registries, and connect to internal mesh networks that the owners thought were secure.

improve build instructions

as a golang newbie, I am having trouble building from source (ubuntu)

just building with the commands given:

~/wgsd/cmd/coredns$ go build       
main.go:7:2: cannot find package "github.com/coredns/coredns/core/dnsserver" in any of:
        /usr/lib/go-1.10/src/github.com/coredns/coredns/core/dnsserver (from $GOROOT)
        /home/florian/go/src/github.com/coredns/coredns/core/dnsserver (from $GOPATH)
main.go:4:2: cannot find package "github.com/coredns/coredns/core/plugin" in any of:
        /usr/lib/go-1.10/src/github.com/coredns/coredns/core/plugin (from $GOROOT)
        /home/florian/go/src/github.com/coredns/coredns/core/plugin (from $GOPATH)
main.go:8:2: cannot find package "github.com/coredns/coredns/coremain" in any of:
        /usr/lib/go-1.10/src/github.com/coredns/coredns/coremain (from $GOROOT)
        /home/florian/go/src/github.com/coredns/coredns/coremain (from $GOPATH)
main.go:5:2: cannot find package "github.com/jwhited/wgsd" in any of:
        /usr/lib/go-1.10/src/github.com/jwhited/wgsd (from $GOROOT)
        /home/florian/go/src/github.com/jwhited/wgsd (from $GOPATH)

trying to get dependencies:

~/wgsd/cmd/coredns$ go get -d
package github.com/caddyserver/caddy/caddyfile: cannot find package "github.com/caddyserver/caddy/caddyfile" in any of:
        /usr/lib/go-1.10/src/github.com/caddyserver/caddy/caddyfile (from $GOROOT)
        /home/florian/go/src/github.com/caddyserver/caddy/caddyfile (from $GOPATH)
package crypto/ed25519: unrecognized import path "crypto/ed25519" (import path does not begin with hostname)
package github.com/caddyserver/caddy/onevent/hook: cannot find package "github.com/caddyserver/caddy/onevent/hook" in any of:
        /usr/lib/go-1.10/src/github.com/caddyserver/caddy/onevent/hook (from $GOROOT)
        /home/florian/go/src/github.com/caddyserver/caddy/onevent/hook (from $GOPATH)
^C

compilation with plugin coredns breaks

root@50a42f:~/core/coredns# go build

github.com/jwhited/wgsd

/root/go/pkg/mod/github.com/jwhited/[email protected]/setup.go:14:18: cannot use setup (type func(*"github.com/caddyserver/caddy".Controller) error) as type "github.com/coredns/caddy".SetupFunc in argument to plugin.Register
/root/go/pkg/mod/github.com/jwhited/[email protected]/setup.go:45:21: cannot use c (type *"gi thub.com/caddyserver/caddy".Controller) as type *"github.com/coredns/caddy".Controller in argument to dnsserver.Get Config
root@50a42f:~/core/coredns#

used go lang 14

some hint `?

Using wgsd when registry is a DNS

I am interested in using wgsd to create a mesh between my wireguard nodes (I currently use a hub and spokes model).

The device I would like to use as the registry (my current hub) runs a PiHole DNS Docker (port 53). Would this conflict with wgsd?

Allow serving SRV records without "====" suffixes

Some implementations of DNS resolver only consider [0-9a-z.-] as valid characters (e.g. Deno), and will start to throw errors if an equal sign is encountered.
Allowing serving SRV records both with and without the ==== suffix will get around such a problem.

self endpoint unspecified returns socket bind addr over UDP

with this config:

.:5353 {
  debug
  wgsd example.com. wg0 {
    self
  }
}

querying for the host info returns:

% dig @<redacted> -p 5353 xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. SRV
[...]
;; ADDITIONAL SECTION:
xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. 0	IN AAAA	::
xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. 0	IN TXT "txtvers=1" "pub=uwysLkwik5Z+qhbYC9y1qku2PBgvqJ4W1qe9MvDrnl8=" "allowed="

using tcp we get the actual addr:

% dig +tcp @<redacted>-p 5353 xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. SRV
[...]
;; ADDITIONAL SECTION:
xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. 0	IN A 172.31.1.108
xmgkylsmekjzm7vkc3maxxfvvjf3mpayf6uj4fwwu66tf4hltzpq====._wireguard._udp.example.com. 0	IN TXT "txtvers=1" "pub=uwysLkwik5Z+qhbYC9y1qku2PBgvqJ4W1qe9MvDrnl8=" "allowed="

We populate the A/AAAA data from the dns.ResponseWriter.LocalAddr() which comes from https://github.com/miekg/dns/blob/master/server.go

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.