5
0
mirror of https://github.com/cwinfo/yggdrasil-network.github.io.git synced 2025-02-28 11:41:34 +00:00

Merge branch 'master' into doc-update-rpm-manual

This commit is contained in:
Neil Alexander 2020-05-17 13:54:27 +01:00 committed by GitHub
commit ff6e037009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1579 additions and 180 deletions

11
Gemfile Normal file
View File

@ -0,0 +1,11 @@
gem "jekyll", "~> 3.8"
gem "jekyll-theme-minimal", "~> 0.1.1"
gem "jekyll-feed", "~> 0.11.0"
gem "jekyll-sitemap", "~> 1.2"
gem "github-pages", group: :jekyll_plugins
gem "nokogiri", ">= 1.10.4"

251
Gemfile.lock Normal file
View File

@ -0,0 +1,251 @@
GEM
specs:
activesupport (4.2.11.1)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.5)
dnsruby (1.61.2)
addressable (~> 2.5)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.12.0)
ffi (>= 1.3.0)
eventmachine (1.2.7)
execjs (2.7.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.11.1)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (198)
activesupport (= 4.2.11.1)
github-pages-health-check (= 1.16.1)
jekyll (= 3.8.5)
jekyll-avatar (= 0.6.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.5)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.11.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.12.1)
jekyll-mentions (= 1.4.1)
jekyll-optional-front-matter (= 0.3.0)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.2.0)
jekyll-redirect-from (= 0.14.0)
jekyll-relative-links (= 0.6.0)
jekyll-remote-theme (= 0.3.1)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.5.0)
jekyll-sitemap (= 1.2.0)
jekyll-swiss (= 0.4.0)
jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.1)
jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1)
jekyll-theme-minimal (= 0.1.1)
jekyll-theme-modernist (= 0.1.1)
jekyll-theme-primer (= 0.5.3)
jekyll-theme-slate (= 0.1.1)
jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.1)
jemoji (= 0.10.2)
kramdown (= 1.17.0)
liquid (= 4.0.0)
listen (= 3.1.5)
mercenary (~> 0.3)
minima (= 2.5.0)
nokogiri (>= 1.8.5, < 2.0)
rouge (= 2.2.1)
terminal-table (~> 1.4)
github-pages-health-check (1.16.1)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (~> 3.0)
typhoeus (~> 1.3)
html-pipeline (2.11.1)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.8.5)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.6.0)
jekyll (~> 3.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.5)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1)
rouge (~> 2)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.11.0)
jekyll (~> 3.3)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.12.1)
jekyll (~> 3.4)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.4.1)
html-pipeline (~> 2.3)
jekyll (~> 3.0)
jekyll-optional-front-matter (0.3.0)
jekyll (~> 3.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.2.0)
jekyll (~> 3.0)
jekyll-redirect-from (0.14.0)
jekyll (~> 3.3)
jekyll-relative-links (0.6.0)
jekyll (~> 3.3)
jekyll-remote-theme (0.3.1)
jekyll (~> 3.5)
rubyzip (>= 1.2.1, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.5.0)
jekyll (~> 3.3)
jekyll-sitemap (1.2.0)
jekyll (~> 3.3)
jekyll-swiss (0.4.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.5.3)
jekyll (~> 3.5)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.1)
jekyll (~> 3.3)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.10.2)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (~> 3.0)
kramdown (1.17.0)
liquid (4.0.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
mercenary (0.3.6)
mini_portile2 (2.4.0)
minima (2.5.0)
jekyll (~> 3.5)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.11.3)
multipart-post (2.1.1)
nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
octokit (4.14.0)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.1.1)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rouge (2.2.1)
ruby-enum (0.7.2)
i18n
ruby_dep (1.5.0)
rubyzip (1.2.3)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.3.1)
ethon (>= 0.9.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
unicode-display_width (1.6.0)
PLATFORMS
ruby
DEPENDENCIES
github-pages
jekyll (~> 3.8)
jekyll-feed (~> 0.11.0)
jekyll-sitemap (~> 1.2)
jekyll-theme-minimal (~> 0.1.1)
BUNDLED WITH
1.16.1

View File

@ -100,7 +100,7 @@ So full connection process looks something like the following:
5. The node checks that the destination `NodeID` and bitmask match the `NodeID` of the closest node (if not, then it means the destination node doesn't exist / is offline / is unreachable while the network re-converges due some disruption).
6. The node sends a session ping to the destination.
7. The node receives a session pong from the destination, learning their public ephemeral key.
8. The nodes can now send regular IPv6 traffic to eachother, encrypted with the ephemeral shared secret, using the session's cached `coords` to avoid future lookups (unless the session is unresponsive for too long, in which case any new sends will also trigger a ping, or a new DHT lookup if the pings fail).
8. The nodes can now send regular IPv6 traffic to each other, encrypted with the ephemeral shared secret, using the session's cached `coords` to avoid future lookups (unless the session is unresponsive for too long, in which case any new sends will also trigger a ping, or a new DHT lookup if the pings fail).
### Conclusion

View File

@ -27,7 +27,7 @@ This post attempts to explain Yggdrasil's congestion control mechanism, why past
The first thing to try is not to implement any explicit buffering in Yggdrasil.
Packets are received from a socket, we look up where the packet needs to go next, and then we send on that socket.
This immediately leads to blocking network operations and poor performance, so we need need separate read and write threads (goroutines, in our case).
This immediately leads to blocking network operations and poor performance, so we need separate read and write threads (goroutines, in our case).
Initially, we used buffered channels and non-blocking channel sends.
This means that, instead of the reader goroutine writing to the socket to send, it would pass it to a channel which a dedicated writer goroutine would read from.
The problem with this approach is that Go channels with non-blocking sends are [FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) and [tail dropped](https://en.wikipedia.org/wiki/Tail_drop).
@ -56,7 +56,7 @@ What we want is for multiple streams of traffic to be handled independently, to
Then, we can reward different traffic streams to prioritize based on lowest bandwidth (i.e. size of queue / age of oldest packet in queue, with a separate queue per traffic stream).
Now we let traffic streams compete for bandwidth.
The winning strategy, to get more bandwidth during times of congestion, is to attempt to use *less* bandwidth, which I argue is exactly the behavior we want to encourage.
Streams of traffic that play nice get a fair share of bandwidth, which includes pretty much every sane TCP implementation, and streams that flood goto timeout.
Streams of traffic that play nice get a fair share of bandwidth, which includes pretty much every sane TCP implementation, and streams that flood go to timeout.
### Yggdrasil's congestion control
@ -99,7 +99,7 @@ Still, because we won't really know without trying, adding the required new pack
Yggdrasil has gone through a number of different congestion control mechanisms since the TCP link layer was introduced.
The current congestion control mechanism rewards traffic streams which utilize less bandwidth by prioritizing them higher than streams using more bandwidth.
Cooperative stream obtain a fair share of bandwidth, while stream which attempt to use more than their fair share are given lower priority, and are forced to throttle down as a result.
Cooperative streams obtain a fair share of bandwidth, while streams which attempt to use more than their fair share are given lower priority, and are forced to throttle down as a result.
When packet drops become necessary, a random drop mechanism is used which penalizes large queues the most, which should signal congestion to the worst offenders.
Much of this is a precursor to backpressure routing, which, if it works out in practice as well as it does on paper, should give the network a nearly-optimal latency/bandwidth trade-off.

View File

@ -33,62 +33,58 @@ is released:
TunnelRouting:
{
Enable: false
IPv6Destinations: {}
IPv6Sources: []
IPv4Destinations: {}
IPv4Sources: []
IPv6RemoteSubnets: {}
IPv6LocalSubnets: []
IPv4RemoteSubnets: {}
IPv4LocalSubnets: []
}
```
The `IPv6Destinations` and `IPv4Destinations` options are used to specify
The `IPv6RemoteSubnets` and `IPv4RemoteSubnets` options are used to specify
crypto-key routes. The subnet refers to an encryption public key of another
node, for example:
```
IPv6Destinations: {
IPv6RemoteSubnets: {
"fd64:642b:1a20::/48": "ef78da7fc983c6c210609529921a701ca3e43fa5cfd79f5f20cc67bf66e45c1a",
"fd25:8a33:9311:a53b::/64": "417fd0a66a104f050ae3544b3bc03eeb3648dded4a8c1fb085d65ffa25e83d6e"
}
```
As with a typical routing table, more specific routes are preferred.
The `IPv6Sources` and `IPv4Sources` options are used to specify which source
addresses are eligible to be routed across a tunnel. For IPv6, this is optional
as each Yggdrasil node already has an address and a routed subnet, and these are
always allowed as source addresses. Specifying additional source addresses means
that you can use the tunnel to route between networks. For IPv4, this is
mandatory as Yggdrasil nodes do not have IPv4 addresses by default.
The `IPv6LocalSubnets` and `IPv4LocalSubnets` options are used to specify which source
addresses are eligible to be routed across a tunnel. These options are mandatory.
### Bridging networks
Assume that node A is `a.a.a.a/24` and `aaaa:aaaa:aaaa:aaaa::/64` and node B is `b.b.b.b/24` and `bbbb:bbbb:bbbb:bbbb::/64`. On node A, use the following `TunnelRouting` configuration:
```
Enable: true
IPv6Destinations: {
IPv6RemoteSubnets: {
"bbbb:bbbb:bbbb:bbbb::/64": "xxxxxxxxxxxxxx"
}
IPv6Sources: {
IPv6LocalSubnets: {
aaaa:aaaa:aaaa:aaaa::/64
}
IPv4Destinations: {
IPv4RemoteSubnets: {
"b.b.b.b/24": "xxxxxxxxxxxxxx"
}
IPv4Sources: {
IPv4LocalSubnets: {
a.a.a.a/24
}
```
On node B, use the reverse `TunnelRouting` configuration:
```
Enable: true
IPv6Destinations: {
IPv6RemoteSubnets: {
"aaaa:aaaa:aaaa:aaaa::/64": "xxxxxxxxxxxxxx"
}
IPv6Sources: {
IPv6LocalSubnets: {
bbbb:bbbb:bbbb:bbbb::/64
}
IPv4Destinations: {
IPv4RemoteSubnets: {
"a.a.a.a/24": "xxxxxxxxxxxxxx"
}
IPv4Sources: {
IPv4LocalSubnets: {
b.b.b.b/24
}
```

View File

@ -56,7 +56,7 @@ Then, when a node needs to forward a packet, it checks the tree location of each
This is explained in more detail in earlier blog posts, if you're not familiar with how Yggdrasil routes and care to read more.
In our package delivery example, imagine if the streets in Alice's town were laid out in a grid, and then named and numbered systematically by blocks, with street signs to label where any off-grid bypasses go.
Alice and friends still haven't bought maps, but they they know each other's *addresses* instead.
Alice and friends still haven't bought maps, but they know each other's *addresses* instead.
So, if Alice wants to contact Carol, she first travels to Bob's house and asks him for Carol's address.
Now, when she wants to deliver a package to Carol, she can simply follow the block structure of the town until she arrives on Carol's block, and she has the option to take any bypass she happens to come across if it brings her closer to Carol's place.
That's basically how routing on the tree, or taking an off-tree shortcut, work in Yggdrasil's greedy routing scheme, except with a tree instead of a grid (which, in addition to working everywhere, seems to work *well* in the places we care about).

View File

@ -28,7 +28,7 @@ In addition, the number of peers you want to add depends on what you want to do.
### What happens when things go wrong
Lets imagine we have some nodes in New York, and initially they follow the peering rules outlined above. Now suppose that two of these nodes decide that they want to add connections to London. In Yggdrasil, nodes tend to select parents that minimize latency to the root, which happens to be a node in Paris at the time I'm writing this. As a result, both of the NY nodes are likely to select their respective London peers as their parents. If the nodes are following the peering rules, then at least one of them has also decided to peer with the other, so they have a shortcut they can use to talk to each-other (or any descendants in the tree).
Let's imagine we have some nodes in New York, and initially they follow the peering rules outlined above. Now suppose that two of these nodes decide that they want to add connections to London. In Yggdrasil, nodes tend to select parents that minimize latency to the root, which happens to be a node in Paris at the time I'm writing this. As a result, both of the NY nodes are likely to select their respective London peers as their parents. If the nodes are following the peering rules, then at least one of them has also decided to peer with the other, so they have a shortcut they can use to talk to each-other (or any descendants in the tree).
However, if they ignore the peering rules and *don't* peer with each other, then they are likely to route through London instead of communicating over their local mesh network. A shorter path exists, through their local mesh network, but it's not one that the network *must* know about for routing to work, so they won't necessarily know about it. As a result, the latency between these two nodes (or decedents thereof) will likely be an order of magnitude more than it needs to be (and probably lower bandwidth as well).

View File

@ -0,0 +1,114 @@
---
layout: post
title: "Version 0.3.6"
date: 2019-08-03 08:00:00 -0000
author: Neil Alexander
---
### New release!
It's been nearly five months since we released version 0.3.5 of Yggdrasil. In
that time we've seen the node count rise to over 400 nodes on the public network
at times (over 80% of which are running the latest released version) and we've
gained valuable insight to the kinds of challenges that our users have. We've
worked to fix a number of bugs and to improve Yggdrasil.
In terms of lines of code changed, version 0.3.6 is the biggest release of
Yggdrasil to date, with several thousands of lines of code affected. It
represents a massive refactoring exercise in which we've broken up and
modularised the code, dividing core Yggdrasil functionality, TUN/TAP, admin
socket and multicast features into their own respective Go packages.
### Fixes
Most of the user-facing changes in this release are fairly minimal, however some
bugs have been corrected. A complete list is available in the [changelog](/changelog.html).
Highlights include peers now being added correctly even when one or more
configured peers are unavailable or unreachable. Multicast interfaces are also
being evaluated more frequently now, which can help if an interface becomes
available or goes down after Yggdrasil has already started.
A number of bugs have been fixed in the TUN/TAP and IP-specific code, including
problems that affected ICMPv6 and Neighbour Discovery in TAP mode specifically.
This helps reliability on platforms where TAP mode is used more commonly, e.g.
on BSD platforms or on Windows, although this also improves TAP support on Linux
too.
### Refactoring and API
Around the previous release, it became obvious to us that our codebase was
turning into a monolith. We had pretty much all of the necessary behaviour in
a single `yggdrasil` package to run a single node, but this made our codebase
inflexible and difficult to maintain and extend. It also meant that Yggdrasil
was virtually impossible to integrate into other applications.
Our refactoring efforts in version 0.3.6 mean that our codebase is now easier to
manage and to understand. It also includes the first taste of our API! The
API makes it possible to take the Yggdrasil core, drop it into your own Go
application and use the Yggdrasil network as a fully end-to-end encrypted and
distributed transport layer. We've also moved all of the IP-specific code into
the TUN/TAP module, which means that Yggdrasil's core now provides a completely
protocol-agnostic transport.
Documentation on how to use the API to integrate Yggdrasil into your own
applications will follow soon—watch this space! In the meantime, [`godoc` can be
used to examine our new API functions](https://godoc.org/github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil).
Please note though that **API functions are not yet finalised and may be subject
to change** in future versions. Yggdrasil is still alpha-grade software at this
point so all of the usual warnings apply.
### Platform Support
We enjoy great support from our community in bringing and packaging Yggdrasil on
new platforms. Since the release of version 0.3.5, the following third-party
packages have cropped up, and we are very grateful to the maintainers:
- A [new RPM build](https://copr.fedorainfracloud.org/coprs/leisteth/yggdrasil/) for Red Hat, Fedora, CentOS etc.
- An [AUR package](https://aur.archlinux.org/packages/yggdrasil-git/) for Arch Linux
- A [Void package](https://github.com/void-linux/void-packages/tree/master/srcpkgs/yggdrasil) for Void Linux
- A [MacPorts package](https://github.com/macports/macports-ports/blob/master/net/yggdrasil-go/Portfile) for macOS
We expect that any third-party packages which have not yet been updated for
v0.3.6 will be updated soon!
We are aware of a few outstanding issues with Windows, which are largely related
to one or two bugs in the [Water](https://github.com/songgao/water) library
which we use for TUN/TAP support. We are hoping to address these problems with
the maintainer of this library soon. Using Yggdrasil in router-only mode does
work as expected, but some bugs when using the TAP adapter still remain. In the
meantime, we'd certainly welcome any assistance in maintaining the Windows port
of Yggdrasil.
The iOS build has been largely neglected due to API changes, although hopefully
a new TestFlight build for version 0.3.6 will be available before too long.
### Upgrading
We recommend that all Yggdrasil users always run the latest version of the code
wherever possible, so please upgrade as soon as it is convenient. New downloads
are available from our [Builds](/builds.html) page and
[Neil](https://github.com/neilalexander)'s S3 repositories are up-to-date for
Debian and EdgeRouter installs.
If you have installed through a package manager, you should be able to upgrade
in-place as soon as the new packages are available. On macOS, you can simply
install the new `.pkg` from the builds page over the top of the old one. On
Windows, and on any installation where the binary was installed by hand, you can
simply replace the `yggdrasil` and `yggdrasilctl` binaries with the newly
released builds.
Building from source is simple if you have Git and Go 1.11 or later installed:
```
git clone https://github.com/yggdrasil-network/yggdrasil-go
cd yggdrasil-go
./build
```
### Feedback
We always welcome feedback, so please do feel free to join us either in our
[Matrix channel](https://riot.im/app/#/room/%23yggdrasil:matrix.org) or on IRC
in `#yggdrasil` on Freenode. You can also raise bug reports and issues in [our
GitHub repository](https://github.com/yggdrasil-network/yggdrasil-go/issues).

237
_posts/2019-08-19-awdl.md Normal file
View File

@ -0,0 +1,237 @@
---
layout: post
title: "Meshing using Apple Wireless Direct Link (AWDL)"
date: 2019-08-19 08:00:00 -0000
author: Neil Alexander
---
### Wireless without borders
I was mostly prompted to write this post in response to a [Hacker News
thread](https://news.ycombinator.com/item?id=20735462) recently, which announced
the release of an open-source AirDrop implementation called
[OpenDrop](https://github.com/seemoo-lab/opendrop), from the same team at Seemoo
Lab who produced an open-source implementation of Apple Wireless Direct Link
(AWDL) protocol called [OWL](https://github.com/seemoo-lab/owl). AWDL is the
secret sauce behind AirDrop, peer-to-peer AirPlay and some other Apple wireless
technologies. Even though everything covered in this post was done some time
ago, I have never spent the time to document it.
With a few exceptions, most wireless networks in the world operate in
"infrastructure mode" which is where a wireless access point serves one or more
wireless clients. Think of your Wi-Fi at home, at work or in a coffee shop.
However, as implied by the name, reliable and usable infrastructure Wi-Fi is
often only available in certain physical locations with "good infrastructure".
If you wanted to connect some devices together anywhere not served by an
infrastructure Wi-Fi network, or in a location where you can't suddenly plug in
a wireless access point, you may not have many options (Bluetooth aside).
AWDL is designed to avoid this problem by extending the 802.11 wireless standard
to allow client devices to communicate directly with each other, without the
help of the central wireless access point. You can walk out into a field with a
couple of iPhones or Macs and they can use AWDL to discover each other and
exchange data, peer-to-peer. Even better is that nearby devices that are
connected to different infrastructure Wi-Fi networks can still communicate with
each other using AWDL!
### The science
Normally, when connected to a wireless access point, wireless clients remain
locked to the specific radio channel that the AP is using. AWDL works by
instructing the wireless adapter in the device to "hop" between channels so that
it can not only remain connected to the wireless access point, but can also
listen to other nearby devices.
Devices announce their presence and information about their services on a
"social channel" for other devices to hear, effectively creating peer-to-peer
service discovery. Once two devices have decided that they want to communicate
directly, they agree to jump to another channel for real data exchange so that
they don't interrupt existing Wi-Fi networks or, indeed, the social channel.
These "hops" between wireless channels happen so quickly that there's very
little disruption to what the user is doing with their Wi-Fi connection already
(except for some minor wireless performance degradation - to be covered later).
A number of papers have been published by the OWLink team on the inner workings
of the AWDL protocol, which can be [found
here](https://owlink.org/publications/). In particular, [this
paper](https://arxiv.org/pdf/1808.03156.pdf) from Mobicom 2018 contains a
significant amount of detail about the AWDL protocol itself, channel hopping
techniques and security considerations, amongst other things.
### Mesh opportunities
Yggdrasil is designed to create a mesh network automatically out of
interconnected nodes - the idea being that all nodes can route to all other
nodes on the mesh network by routing through other nodes.
Today, many of these connections happen between nodes across the Internet, since
the community is still relatively small and geographically dispersed. A node
joining the Yggdrasil network needs to only peer with a single device that is
already connected to the wider network in order to participate in the
fully-routable mesh.
However, it's not the goal of Yggdrasil to remain something that we just toy
with over the Internet. We want to build a protocol that can scale globally and
work ad-hoc, even in places where infrastructure might not be particularly
strong otherwise. We think that one of Yggdrasil's greatest strengths is that it
is very close to zero-configuration, beyond giving it a very small number of
configuration options, and it should scale well too in principle.
Yggdrasil can already discover potential peers on the same network segment by
using multicast service discovery, which sounds a lot like what AWDL does on the
social channel. You can configure which interfaces Yggdrasil beacons on with the
`MulticastInterfaces` configuration directive.
I wanted to know if we could blend the two so that Yggdrasil could automatically
discover other nearby devices and initiate peering connections with them using
AWDL.
### Getting started
Macs are a good target for developing and testing AWDL-aware applications as
AWDL is exposed to userspace through a network adapter called `awdl0`. It sits
there with a link-local IPv6 address, you can run `tcpdump` or Wireshark on it
to listen to AWDL traffic and you can even ping multicast group addresses on the
interface and get responses from other nearby devices, e.g. using `ping6
ff02::1%awdl0`! However, Apple devices don't always keep AWDL alive and
listening all of the time.
On macOS, the AWDL driver is only woken up when either AirDrop is being
actively used in Finder, or where a `NetService` has been created (usually
through Objective-C or Swift) which requests peer-to-peer networking. AWDL is
normally kept alive long enough to satisfy connectivity for these sessions and
then will be sent back to sleep after a period of idleness.
On iOS, the story is somewhat similar to above, except that AWDL is often woken
up as soon as the device is unlocked if AirDrop is enabled. The `NetService` API
otherwise functions the same way.
tvOS is the outlier in that it seems to wake up and listen to AWDL randomly,
even when the device is otherwise asleep, presumably because it is advertising
the ability to receive incoming AirPlay sessions to nearby devices.
From a user perspective, the `awdl0` interface looks entirely unremarkable. It
behaves largely like any other ethernet interface, carrying regular IPv6
traffic. In the background it's a bit more complicated, as the AWDL driver
performs traffic filtering for security reasons, namely, to stop someone sat
next to you in the airport from browsing your file shares. Regular listening
sockets won't accept connections over AWDL unless a specific socket option was
configured on the socket before it started listening.
Multicast traffic, however, does largely get passed through the filter
untouched. Bingo.
### Waking up AWDL
The `NetService` API is effectively a wrapper around multicast DNS-SD, which in
Apple's colourful language, is affectionately known as Bonjour. The API has the
added benefit of being able to tell the operating system to wake up the AWDL
driver pretty much on demand on behalf of "peer-to-peer" services.
So all we would need to do to wake up AWDL is to call the `NetService` API,
publish a service that requests peer-to-peer functionality and let the operating
system do the hard work for us. Yggdrasil, being written in Go, didn't have any
concept of `NetService` but thankfully we were able to use Cgo to do this
instead.
We wrote a Cgo function which calls the NetService API and advertises our new
fake service, `_yggdrasil._tcp`, which causes the operating system to wake up
the AWDL driver. Amazingly this worked.
Yggdrasil doesn't actually use DNS-SD - we currently use a custom-formatted
multicast beacon on a different multicast group. It is planned to eventually
migrate to something more standard, like DNS-SD, for service discovery. However,
in this instance, registering a fake DNS-SD service was just enough to wake up
AWDL.
### Peering automatically
Once the driver is active, the regular Yggdrasil multicast beacons on the
`ff02::114` multicast group address seem to be passed through to the driver
normally and the Yggdrasil nodes running on each machine start to hear each
other's calls.
The only thing that remained to be done was to configure the sockets with the
aforementioned socket option to allow them to communicate over the AWDL
interface. This socket option is called `SO_RECV_ANYIF` and is defined in
`sys/socket.h` on Darwin as `0x1104`.
We configure the socket option on our TCP peering socket:
```
err = unix.SetsockoptInt(int(fd), syscall.SOL_SOCKET, 0x1104, 1)
if err != nil {
...
}
```
Now that the Yggdrasil nodes can hear each other's advertisements over the
`awdl0` interface, the regular automatic peering process kicks in and a TCP
session is opened between the two devices, creating a peering. The net result?
AWDL peerings!
```
$ sudo yggdrasilctl getSwitchPeers
bytes_recvd bytes_sent coords endpoint ip port proto
1 244278 313907 [3 5 5 2 1] fe80::xxxx:xxxx:xxxx:xxxx%awdl0 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx 1 tcp
```
To further cement the experiment, we can actually disconnect the two devices
from each other, or connect to different Wi-Fi networks automatically, and the
peering over the `awdl0` interface still continues to function!
An `iperf3` test over Yggdrasil using the new AWDL link looks fairly good - the
devices are sat next to each other:
```
[ ID] Interval Transfer Bandwidth
[ 5] 0.00-1.00 sec 15.4 MBytes 129 Mbits/sec
[ 5] 1.00-2.00 sec 16.9 MBytes 141 Mbits/sec
[ 5] 2.00-3.00 sec 15.9 MBytes 133 Mbits/sec
[ 5] 3.00-4.00 sec 17.6 MBytes 147 Mbits/sec
[ 5] 4.00-5.00 sec 16.8 MBytes 141 Mbits/sec
[ 5] 5.00-6.00 sec 16.2 MBytes 136 Mbits/sec
[ 5] 6.00-7.00 sec 12.5 MBytes 105 Mbits/sec
[ 5] 7.00-8.00 sec 12.7 MBytes 106 Mbits/sec
[ 5] 8.00-9.00 sec 14.9 MBytes 125 Mbits/sec
[ 5] 9.00-10.00 sec 13.5 MBytes 113 Mbits/sec
```
### Observations and iOS
As the `iperf3` test above shows, the link performance is actually quite good!
It routinely exceeds 100mbps, although this is between only two devices. I have
not been able to test this with Yggdrasil nodes running over AWDL in any
particular density due to only having a limited number of Macs to hand.
One thing that I did notice though is that, while AWDL is active, my wireless
connection to my home Wi-Fi network does reduce in speed somewhat. This is to be
expected, given that the wireless chipset is hopping between channels rather
than spending all of its time on a single channel.
Sadly we weren't able to reproduce this test using iOS Testflight builds of
Yggdrasil. On iOS, we implement Yggdrasil as a VPN service which is subject to a
number of probably reasonable restrictions imposed by the OS, which presumably
exist to stop VPN extensions from spying on you.
We were able to create a `NetService` from within the VPN extension and the
service beacons were advertised as expected, however, we weren't able to
initiate any other kind of connections over the `awdl0` interface. After a chat
with an engineer at Apple, it turns out that the `awdl0` interface isn't scoped
for use within a VPN extension, thus squashing our hopes and dreams of being
able to sprinkle this kind of magic onto our iOS port of Yggdrasil. We have a
feature request radar open with Apple in the hope that they may be able to
change this restriction in the future.
But we were able to get this to work on macOS and that, itself, is quite
awesome.
### Conclusion
Yggdrasil doesn't enable AWDL by default because of the reduction in wireless
performance that AWDL being active can cause. Therefore, to enable AWDL peering,
you must add the `awdl0` interface specifically into the `MulticastInterfaces`
configuration option in `yggdrasil.conf`. However, we do have working support
for connecting Macs together and meshing automatically using AWDL, and you can
enable it very easily if you wish to experiment!
We'd love to hear if you are peering Yggdrasil nodes using AWDL, or have
performed any more extensive tests of how it performs in real-world scenarios -
join us on our [Matrix channel](https://matrix.to/#/#yggdrasil:matrix.org)!

171
_posts/2019-09-01-actors.md Normal file
View File

@ -0,0 +1,171 @@
---
layout: post
title: "Acting out"
date: 2019-09-01 21:00:00 +0000
author: Arceliar
---
### Overture
We've recently rewritten much of Yggdrasil's internals to change from Go's native [communicating sequential processes](https://en.wikipedia.org/wiki/Communicating_sequential_processes) (goroutine+channel) style to using an asynchronous [actor model](https://en.wikipedia.org/wiki/Actor_model) approach to concurrency. While this change should be invisible to the average user, it dramatically changes what we developers need to think about when working on the code. I thought it would be useful to explain a little about the motivation for rewriting things this way, and what the consequences are.
Caution: theatre puns and references throughout, because `Actor`s.
### Exposition
Yggdrasil is written in the Go programming language. Go makes it easy to start a function running concurrently, and gives developers the tools they need to make concurrently executing functions communicate, but it's not always easy to use them correctly. To be clear, the things I'm about to rant about are all fixable. Working around them is a normal thing to do in Go. More importantly, it's a case where doing things the obvious way (which is sometimes even safe in isolation) leads to *wrong* behavior in a larger program. I prefer models where the obvious thing is still correct, and non-obvious things are only needed as a performance optimization.
#### Composition
There's a common pattern that has emerged many times in the Yggdrasil code base. We'll have a `struct` with some mutable fields that need reading or updating, such as information about a particular cryptographic session, or the switch's table of idle peers and buffered traffic. Since shared mutable state is hard, and Go is all about "[Share Memory By Communicating](https://blog.golang.org/share-memory-by-communicating)", we'll have packets get passed to a dedicated worker goroutine that "owns" that particular `struct`. The worker uses information from the packet and the owned `struct` to do whatever it is needs to do, updates these things accordingly, and passes the packet along to the next goroutine in the pipeline.
This often results in a "`for select`" pattern, where goroutines sit in an infinite `for` loop and `select` on several channels, to wait for packets to process or various types of signals from other goroutines. There are a few ways around it (with heavy use of `reflect` or `chan interface{}`, for example), but in most cases, every `select` statement needs to fully enumerate every behavior that the goroutine may need to engage in at that point in the code. If there's a common set of `case`s that always need to be handled, and then a few exceptional `case`s that may or may not matter (possibly when the associated `struct`s the workers are using are similar but not exactly the same types, or as the state of a `struct`'s fields change), then that typically involves multiple `select` statements with only the addition or modification of one or two `case`s.
Go embraces composition in its type system, but `select` statements (and channel operations in general) make execution resistant to composition.
#### Deadlocks
The "`for select`" pattern is safe, as far as I know, if the flow of messages through the program form a directed acyclic graph. However, in our case, cycles emerge if we try to handle things in the obvious way. For example, a cryptographic session needs to somehow get outbound encrypted traffic to the switch, but incoming encrypted traffic also needs to make it from the switch to the sessions for decryption (via the router, which is responsible for, among other things, identify which session is associated with the traffic).
When cycles of goroutines naively pass messages over channels, deadlocks are all but inevitable. There are a few ways to address this, but they're not always appropriate. Ideally, we would change the design to remove cycles, but this is not always possible, and may require significant changes to the workflow in cases where it is possible. In practice, what we'd actually do is either buffer messages (having some dedicated reader goroutine to take the message, add it to a slice, and then pass it to the real destination ASAP) or drop messages entirely (with a `select` statement that aborts and does cleanup in a `default` case, or by having a dedicated reader that drops messages more intelligently, such as from the front of the queue, under the assumption that older messages are less useful).
#### Leaks
Typically, when a goroutine is started, it continues to run until either the function returns or the program exits. For this reason, if a goroutine executes any statements which can block (such as a channel operation), it's important to include some `case` which signals that it's time to return. Forgetting to do this can result in goroutine leaks. [Never start a goroutine without knowing how it will stop](https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop), or so the experts say.
This is sometimes harder than it needs to be. To be blunt, the single producer N consumer cases are fine, you just close the channel and have all the consumers take this as a signal to exit. Anything involving multiple producers requires some sort of signaling to indicate that all producers have exited. Since you're using a channel already, the obvious option is a `select` statement with another channel that closes to signal shutdown, and then something like e.g. a [`sync.WaitGroup`](https://golang.org/pkg/sync/#WaitGroup) to wait for all producers to exit before closing the channel. Until your number of producers needs to change at runtime, and you realize that this races if you start to `Wait` before `Add`ing everything to the group, so you need to implement a custom counter, and be careful that additions and subtractions can also race and cause it to shut down early. And have fun solving it, because with how much `select` resists composition and code reuse, you're going to be implementing the same patterns over, and over, and over, and over...
It's not that this is some impossible problem to solve, it's just that Go's take on the [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes), combined with the rest of the tools the language gives you, makes it easy and concise to run thing the *wrong* way, and leads to comparatively complex and delicate code when trying to run it the right way. At least, that's my personal view of it based on my experience so far, but it probably varies some based on the problem the code is trying to solve.
### Rising action
The [actor model](https://en.wikipedia.org/wiki/Actor_model) is another programming paradigm that embraces concurrency with a "share memory by communicating" philosophy.
For our purposes, an actor is basically a data type with a few special properties:
1. It has an inbox where messages to the actor are placed.
2. It has an associated unit of execution, such as a thread, which processes messages from the inbox one at a time.
3. Rather than exposing ordinary functions for other code to call, the actor exposes *behaviors*. A behavior is a function which has no return value, and is executed only for its side effects. When an actor `A` calls a behavior of an actor `B`, what really happens is that `A` places a message in `B`'s inbox, and `B` processes that message by executing some code.
Different implementations differ on details after that, such as what order messages are processed in, if actors are allowed to wait for a particular type of message before continuing, whether actors run locally or are distributed across a cluster, etc., but they tend to all include some version of the broad strokes above.
### Turing point
<!-- a play on "Turning point", aka the Climax of a classic 5-act play structure, which is what this post's structure is modeled after if you hadn't figured it out by this point -->
I'm particularly fond of the [pony](https://ponylang.io) programming language's take on the actor model. I really can't say enough nice things about their approach, and fully describing it is beyond the scope of this blog post, but if you come out of here with an interest in the actor model, then I highly recommend checking out that language. Maybe watch a few of the talks from the developers that have been posted to YouTube, or read their papers about what is *easily* the most promising approach to garbage collection I've ever come across.
Anyway, I don't actually work on anything written in pony, but I like their version of the actor model so much that I decided to see if I could trick Go's runtime into faking it. The result is [`phony`](https://github.com/Arceliar/phony), which manages to do most of what I want in under 70 lines of code. When we write code using this asynchronous message passing style, instead of ordinary goroutines+channels, the implications are pretty significant:
1. There are no deadlocks. Message sends always succeed, and are quite fast (it doesn't even require [CAS](https://en.wikipedia.org/wiki/Compare-and-swap) instructions in the normal case).
2. Inbox sizes stay small due to backpressure: if the sender sees that the receiver's inbox has too many pending messages, it will schedule itself to stop at some deadlock-free safe point in the future, to wait until the receiver signals that it's handled the message.
3. `Actor`s are *shockingly* lightweight: on a modern 64-bit processor, an idle `Actor`'s only resources are 24 bytes for an empty `Inbox`, some of which is padding that may not apply if embedded into a struct. In particular, an idle `Actor` with an empty `Inbox` has no associated goroutine, so it requires no stack.
4. The lack of a goroutine also means that idle `Actor`s, even cycles of `Actor`s, can be garbage collected automatically.
5. Any `struct` that embeds an `Inbox` satisfies the `Actor` interface. Since `Actor`s encapsulate their own unit of execution, it means the range of behaviors that unit of execution can engage in are encoded into the type system and can even be abstracted through `interface` types. In my opinion, the resulting code is cleaner, easier to read and understand, and far easier to reuse or extend than the `for select` pattern from goroutine+channel use.
### Falling action
I'm happy enough with the current state of `phony` that I decided to start migrating the `yggdrasil-go` code base to use it. This is still work in progress (there are some non-`Actor` goroutines around the edges of the code, mostly in main `Accept` loops and that sort of thing), but the hot paths are now `Actor` based.
Most of this was done in a weekend and came together with surprisingly little pain. I had exactly 2 crashes the entire time (1 accidental `nil` pointer deference and 1 legitimate bug I needed to fix in `phony`), and more importantly, 0 deadlocks. Most things just worked as intended the first time they compiled. There were a few bugs to work out when I was rewriting the `link` code, but nothing compared to the mess I had to deal with when writing the old code (which was a couple of horrifying interdependent `for select` loops to build a state machine).
So by now you're probably wondering what any of this looks like in practice. Just to give a generic example, suppose we have some struct with an exported function that needs to run code on a worker goroutine. We could end up with something like the following when writing Go in the CSP style:
```Go
// This is the function we want the worker to run.
func (n *NonActorStruct) theFunction(arg1 Type1, arg2 Type2) {
// this is where the code we actually care about goes, the rest is basically boilerplate
}
// This is the struct that we want the worker to own and manipulate.
type NonActorStruct struct {
inputForTheFunction chan argsForTheFunction
// fields we care about, plus maybe more channels for other things
}
// Needed to initialize the channel to a working state
func NewNonActorStruct() *NonActorStruct {
n := NonActorStruct{
inputForTheFunction: make(chan argsForTheFunction),
}
return &n
}
// This is just a helper struct to carry arguments for the function.
type argsForTheFunction struct {
Arg1 Type1
Arg2 Type2
}
// This is the function we export.
func (n *NonActorStruct) RunTheFunction(arg1 Type1, arg2 Type2) {
n.inputForTheFunction<-argsForTheFunction{arg1, arg2}
}
// This is needed to start the worker, otherwise things block.
func (n *NonActorStruct) Start() {
go func() {
for {
select{
// cases for other things we may need to do would also be here
// presumably at least one is involved in safely shutting down
case args := <-n.inputForTheFunction:
// We could possibly have a switch statement here
// Then switch on the arg type to pick which function to run
n.theFunction(args.Arg1, args.Arg2)
}
}
}()
}
// This is needed to stop the worker when we're done.
func (n *NonActorStruct) Stop() {
// Actual implemenation depends on what else the worker does in its loop,
// but it probably just sends a specific message and/or closes some channel.
}
// Then to use the code, we have something like:
myStruct := NewNonActorStruct()
myStruct.Start()
defer myStruct.Stop() // Or arrange this to happen somewhere else
myStruct.RunTheFunction(arg1, arg2)
```
<!-- just to reset ugly highlighting in my editor, ignore me -->
When migrating to the actor model, the basic pattern that emerged was to embed a `phony.Inbox` into any `struct` we wanted to make into a `phony.Actor`, and then define functions of the struct like so:
```Go
// This is the function we want the worker to run.
func (a *ActorStruct) theFunction(arg1 Type1, arg2 Type2) {
// this is where the code we actually care about goes, the rest is basically boilerplate
}
// This is the struct that we want the worker to own and manipulate.
type ActorStruct struct {
phony.Inbox // This defines the Act function, satisfying the Actor interface
// fields we care about
}
// This is the function we export.
func (a *ActorStruct) RunTheFunction(from phony.Actor, arg1 Type1, arg2 Type2) {
a.Act(from, func() {
a.theFunction(arg1, arg2)
})
}
// And then to use it, an Actor x would run something like:
myActor := new(ActorStruct)
myActor.RunTheFunction(x, arg1, arg2)
```
And that's about it. The first argument to `myActor.RunTheFunction` also `nil`able, if we have non-`Actor` code that needs to send a message, it just means there's no backpressure to slow down the non-`Actor` code if it's sending messages faster than the `Actor` can handle them. A `phony.Block` function exists to help non-`Actor`s wait for an `Actor` to process a message before continuing, since this seems like a common enough use case (especially when a package wants to export a non-`Actor` interface that uses `Actor` code internally).
What's great is that we don't need to think about starting or stopping workers, deadlocks and leaks are not possible outside of blocking operations (e.g. I/O), and we can add or reuse behaviors just as easily as any function. I find the code easier to read and reason about too.
I/O is one rough spot, since an `Actor` can block on a `Read` or a `Write` and not process incoming messages as a result. This isn't really any worse than working with normal Go code, and the pattern we've adopted is to have separate `Actor`s for `Read` and `Write`, where one mostly just sits in a `Read` loop and sends the results (and/or error) somewhere whenever a `Read` finishes. These two workers can be children of some parent `Actor`, which is the only one the rest of the code needs to know about, and then all we need to remember to do is close the `ReadWriteCloser` (e.g. socket) at some point when we're done. This is the sort of thing that we'll eventually want to write a standard `struct` for, update our code everywhere to use it, and then never have to think about it again. In the meantime, we have a couple of very similar implementations for working with sockets or the tun/tap device.
### Dénouement
The Go language makes concurrency easy, but for some problems it can be difficult to do safely out-of-the-box. However, the language provides the tools needed to implement an actor model approach very easily. While I won't claim that the actor model is a panacea for all development woes, Yggdrasil by its very nature requires us to think about networks of nodes communicating asynchronously, so it makes sense to use a programming paradigm that lets us model that approach more explicitly in our code base. Outside of a couple of corner cases (namely blocking I/O for the network sockets and the tun/tap device), we expect this to obviate any need to even thing about deadlocks, make development easier moving forward, and generally lead to a better user experience as a result. The code migration is still a work in progress, but `Actor`s have replace `for select` workers along the hot paths through the code (minus 1 crypto worker pool in the session code) and will slowly replace synchronization primitives in the remaining code base. The current code has been merged into our `develop` branch, and I'm quite excited to see it land in Yggdrasil `v0.3.9`, along with the usual bug fixes and incremental improvements, which we plan to release in the near future.

View File

@ -0,0 +1,121 @@
---
layout: post
title: "Release v0.3.13"
date: 2020-02-21 09:00:00 +0000
author: Neil Alexander
---
### Release time!
Our last Yggdrasil release, v0.3.12, was merged a couple of months ago at the
end of November. For the most part we have seen good stability with the v0.3.12
builds, not to mention good adoption (with the crawler showing over 500 nodes
running it). Today we are releasing our next version, v0.3.13.
Many of our releases tend not to warrant blog post entries, especially given
that the changelog documents the changes. However, there's some fairly big news
points associated with this version therefore this post aims to discuss them in
a bit more detail.
#### TUN adapter changes
The first big talking point is that this is the first Yggdrasil release that
departs entirely from the Water library and replaces it with the Wireguard TUN
library. There are a few reasons why we decided to switch from Water to the
Wireguard library, but one of the most prominent is that it gives us better TUN
support across all platforms and allows us to finally remove TAP support
altogether.
At a high-level, TUN interfaces are effectively emulating "Layer 3" interfaces -
they deal only in IP packets - whereas TAP interfaces are emulating "Layer 2"
full-fat Ethernet interfaces.
To run in TAP mode, Yggdrasil not only had to add and remove Ethernet headers
for each packet, but it also has to implement an entire NDP implementation and
track MAC addresses in order to trick the host operating system into believing
that there was a real Ethernet domain on the other end of the adapter. Needless
to say, the amount of boilerplate code in order to make TAP mode work correctly
was significant and much of that code was very fragile.
Although we implemented NDP, we did not ever get around to implementing ARP,
which also meant that sending tunnel-routed IPv4 traffic over TAP interfaces
invariably did not work either. We have now been able to remove much of this
code and simplify the TUN code massively, closing the gaps between some of our
supported platforms.
There is one platform that is negatively impacted by this change and that's
NetBSD. The Wireguard TUN package that we are using currently has **no support
for NetBSD**, so we are also removing NetBSD as a supported target until the
necessary code appears upstream. To our knowledge, we don't have a base of
NetBSD users anyway, but we will aim to re-add this soon.
The `IfTAPMode` configuration option has now been removed from Yggdrasil
entirely and it will be ignored if specified. **If you are using TAP mode today,
then this will affect you**. Please make sure to check your Yggdrasil
configuration since this may result in interface naming changes and you may have
to update network settings in your host operating system.
Initially we added TAP support into Yggdrasil as it was the only way to support
Windows, since the OpenVPN driver that we used at the time only supported TAP
mode. Thankfully, this is no longer a problem, as the Wireguard project have
also released [Wintun](https://wintun.net), which is supported by the Wireguard
TUN library. The net result is that we gain TUN support on Windows and the
performance is *far* better than the buggy OpenVPN driver, which is a nice segue
into...
#### Windows installer and performance
We have spent a lot of time trying to improve the installation and setup
experience on Windows. This mostly falls into two areas.
The first is that using the Wintun driver has *massively* improved performance,
in some cases by hundreds of MB/s, and starting the Yggdrasil process is now
much more reliable too - it should no longer be necessary to restart Yggdrasil
due to cases of the TAP adapter not being set up or configured correctly.
The second is that we now automatically generate Windows `.msi` installers using
Appveyor, which means that installing or upgrading Yggdrasil is now simpler than
ever. It is no longer necessary to create directories, copy files and register
Windows services by hand - a marked improvement!
The installer also bundles the Wintun driver and it is installed automatically
if required, therefore there is no longer a need to hunt down and install the
OpenVPN TAP driver separately. We hope that these changes will help to encourage
adoption of Yggdrasil on Windows platforms by significantly reducing the barrier
to entry.
As in the previous section, Yggdrasil on Windows has gone from supporting TAP
mode only to now supporting TUN mode only. **This may mean that you need to
review your configuration**. If you no longer need the OpenVPN TAP driver on
your system, it is best to entirely uninstall it. It is also important to make
sure that the `IfName` configuration option in your `yggdrasil.conf` does not
specify the same name as an existing OpenVPN TAP interface or Yggdrasil may fail
to start.
#### End of the v0.3 release cycle
Generally we try, where possible, to avoid make any changes which would damage
backward compatibility with previous versions. The last version that had
breaking changes was v0.2.1 - over a year and a half ago. However, maintaining
backward compatibility so tightly also prevents us from improving the Yggdrasil
design in various ways.
Therefore, unless any serious bugs or security vulnerabilities appear, it is
very likely that this version will be the last in the v0.3 release cycle.
Instead, we will start working on the v0.4 release, which is likely to include a
number of breaking protocol changes and will be incompatible with v0.3 releases
as a result.
More information will be announced on the types of changes in v0.4 as they
happen - expect to see more blog posts and chatter in the Matrix channel on this
subject - but we will aim to give as much notice as possible before releases
occur that contain breaking changes.
#### Final mentions
In addition to the release notes above, I'd like to relay the message that
[@mwarning](https://github.com/mwarning) has a proposal open for a Google Summer
of Code (GSoC) project under the Freifunk umbrella, comparing a number of mesh
routing protocols including Yggdrasil. More information about the proposal is
available [here](https://projects.freifunk.net/#/projects?project=freifunk_meshnet_protocol_evaluation&lang=en).
If you are interested, please reach out!

View File

@ -118,7 +118,7 @@ For each IPv6 address:
- `bytes_recvd` (`uint64`) contains the number of bytes received from that peer
- `endpoint` (`string`) contains the connected IPv4/IPv6 address and port of the peering
- `port` (`uint8`) contains the local switch port number for that peer
- `uptime` (`uint32`) contains the number of seconds since the peer connection was established
- `uptime` (`float64`) contains the number of seconds since the peer connection was established
#### `addPeer`
@ -252,7 +252,7 @@ Returns:
#### `removeRoute`
Expects:
- `subnet=` `string` for the subnet to remove the route route for
- `subnet=` `string` for the subnet to remove the route for
- `box_pub_key=` `string` for the public key that is routed to
Removes an existing crypto-key route.

View File

@ -22,15 +22,93 @@ div.wrapper section p a code {
section {
flex: auto;
max-width: 100vw;
margin-right: 20px;
@media screen and (max-width: 768px) {
margin-top: 20px;
border: 0;
float: none;
position: relative;
flex: initial;
word-break: break-word;
overflow: hidden;
table {
thead {
th {
min-width: 90px;
}
}
}
}
}
header {
flex: initial;
position: relative;
width: 240px !important;
margin-right: 1em;
@media screen and (max-width: 768px) {
> p {
padding-right: 20%;
}
font-size: 0;
margin: 0;
padding: 0;
&:before {
content:'\2261';
display: block;
position: absolute;
left: 0px;
font-size: 40px;
top: -38px;
}
img {
display: none;
}
> a {
position: absolute;
top: -23px;
left: 50px;
}
a {
&:hover {
font-weight: initial;
}
}
&:hover {
padding: 0;
font-size: initial;
> a {
pointer-events: none;
position: initial;
}
position: fixed;
overflow-y: scroll;
background-color: white;
top: 0px;
left: 0;
right: 0;
bottom: 0;
width: 100%;
z-index: 100;
padding-top: 20px;
padding-bottom: 50px;
padding-left: 20px;
p {
a {
font-size: 24px;
padding-top: 2px;
padding-bottom: 2px;
display: block;
}
br {
display: none;
}
}
&:before {
display: none;
}
}
}
}
pre {
overflow-x: scroll;
}
@ -77,3 +155,9 @@ div.blogpost div#overview div#excerpt {
text-decoration: none;
font-size: 1em;
}
a:hover, a:focus {
color:#0be;
font-weight: initial;
text-decoration: underline;
}

View File

@ -9,6 +9,8 @@ After every push to the `master` branch of the [GitHub repository](https://githu
If you prefer to live dangerously and want to test bleeding-edge features or changes, development builds are [available from the `develop` branch](builds-develop.md), although these may not be as stable.
Looking for Windows installers? [Click here to go to AppVeyor](https://ci.appveyor.com/project/neilalexander/yggdrasil-go/build/artifacts).
For convenience, the latest builds are linked below:
<h3>yggdrasil</h3>

View File

@ -25,6 +25,186 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- in case of vulnerabilities.
-->
## [0.3.14] - 2020-01-01
### Fixed
- Fixes a memory leak that may occur if packets are incorrectly never removed from a switch queue
### Changed
- Make DHT searches a bit more reliable by tracking the 16 most recently visited nodes
- CI builds are now built using Go 1.14.1
## [0.3.13] - 2020-02-21
### Added
- Support for the Wireguard TUN driver, which now replaces Water and provides far better support and performance on Windows
- Windows `.msi` installer files are now supported (bundling the Wireguard TUN driver)
- NodeInfo code is now actorised, should be more reliable
- The DHT now tries to store the two closest nodes in either direction instead of one, such that if a node goes offline, the replacement is already known
- The Yggdrasil API now supports dialing a remote node using the public key instead of the Node ID
### Changed
- The `-loglevel` command line parameter is now cumulative and automatically includes all levels below the one specified
- DHT search code has been significantly simplified and processes rumoured nodes in parallel, speeding up search time
- DHT search results are now sorted
- The systemd service now handles configuration generation in a different unit
- The Yggdrasil API now returns public keys instead of node IDs when querying for local and remote addresses
### Fixed
- The multicast code no longer panics when shutting down the node
- A potential OOB error when calculating IPv4 flow labels (when tunnel routing is enabled) has been fixed
- A bug resulting in incorrect idle notifications in the switch should now be fixed
- MTUs are now using a common datatype throughout the codebase
### Removed
- TAP mode has been removed entirely, since it is no longer supported with the Wireguard TUN package. Please note that if you are using TAP mode, you may need to revise your config!
- NetBSD support has been removed until the Wireguard TUN package supports NetBSD
## [0.3.12] - 2019-11-24
### Added
- New API functions `SetMaximumSessionMTU` and `GetMaximumSessionMTU`
- New command line parameters `-address` and `-subnet` for getting the address/subnet from the config file, for use with `-useconffile` or `-useconf`
- A warning is now produced in the Yggdrasil output at startup when the MTU in the config is invalid or has been adjusted for some reason
### Changed
- On Linux, outgoing `InterfacePeers` connections now use `SO_BINDTODEVICE` to prefer an outgoing interface
- The `genkeys` utility is now in `cmd` rather than `misc`
### Fixed
- A data race condition has been fixed when updating session coordinates
- A crash when shutting down when no multicast interfaces are configured has been fixed
- A deadlock when calling `AddPeer` multiple times has been fixed
- A typo in the systemd unit file (for some Linux packages) has been fixed
- The NodeInfo and admin socket now report `unknown` correctly when no build name/version is available in the environment at build time
- The MTU calculation now correctly accounts for ethernet headers when running in TAP mode
## [0.3.11] - 2019-10-25
### Added
- Support for TLS listeners and peers has been added, allowing the use of `tls://host:port` in `Peers`, `InterfacePeers` and `Listen` configuration settings - this allows hiding Yggdrasil peerings inside regular TLS connections
### Changed
- Go 1.13 or later is now required for building Yggdrasil
- Some exported API functions have been updated to work with standard Go interfaces:
- `net.Conn` instead of `yggdrasil.Conn`
- `net.Dialer` (the interface it would satisfy if it wasn't a concrete type) instead of `yggdrasil.Dialer`
- `net.Listener` instead of `yggdrasil.Listener`
- Session metadata is now updated correctly when a search completes for a node to which we already have an open session
- Multicast module reloading behaviour has been improved
### Fixed
- An incorrectly held mutex in the crypto-key routing code has been fixed
- Multicast module no longer opens a listener socket if no multicast interfaces are configured
## [0.3.10] - 2019-10-10
### Added
- The core library now includes several unit tests for peering and `yggdrasil.Conn` connections
### Changed
- On recent Linux kernels, Yggdrasil will now set the `tcp_congestion_control` algorithm used for its own TCP sockets to [BBR](https://github.com/google/bbr), which reduces latency under load
- The systemd service configuration in `contrib` (and, by extension, some of our packages) now attempts to load the `tun` module, in case TUN/TAP support is available but not loaded, and it restricts Yggdrasil to the `CAP_NET_ADMIN` capability for managing the TUN/TAP adapter, rather than letting it do whatever the (typically `root`) user can do
### Fixed
- The `yggdrasil.Conn.RemoteAddr()` function no longer blocks, fixing a deadlock when CKR is used while under heavy load
## [0.3.9] - 2019-09-27
### Added
- Yggdrasil will now complain more verbosely when a peer URI is incorrectly formatted
- Soft-shutdown methods have been added, allowing a node to shut down gracefully when terminated
- New multicast interval logic which sends multicast beacons more often when Yggdrasil is first started to increase the chance of finding nearby nodes quickly after startup
### Changed
- The switch now buffers packets more eagerly in an attempt to give the best link a chance to send, which appears to reduce packet reordering when crossing aggregate sets of peerings
- Substantial amounts of the codebase have been refactored to use the actor model, which should substantially reduce the chance of deadlocks
- Nonce tracking in sessions has been modified so that memory usage is reduced whilst still only allowing duplicate packets within a small window
- Soft-reconfiguration support has been simplified using new actor functions
- The garbage collector threshold has been adjusted for mobile builds
- The maximum queue size is now managed exclusively by the switch rather than by the core
### Fixed
- The broken `hjson-go` dependency which affected builds of the previous version has now been resolved in the module manifest
- Some minor memory leaks in the switch have been fixed, which improves memory usage on mobile builds
- A memory leak in the add-peer loop has been fixed
- The admin socket now reports the correct URI strings for SOCKS peers in `getPeers`
- A race condition when dialing a remote node by both the node address and routed prefix simultaneously has been fixed
- A race condition between the router and the dial code resulting in a panic has been fixed
- A panic which could occur when the TUN/TAP interface disappears (e.g. during soft-shutdown) has been fixed
- A bug in the semantic versioning script which accompanies Yggdrasil for builds has been fixed
- A panic which could occur when the TUN/TAP interface reads an undersized/corrupted packet has been fixed
### Removed
- A number of legacy debug functions have now been removed and a number of exported API functions are now better documented
## [0.3.8] - 2019-08-21
### Changed
- Yggdrasil can now send multiple packets from the switch at once, which results in improved throughput with smaller packets or lower MTUs
- Performance has been slightly improved by not allocating cancellations where not necessary
- Crypto-key routing options have been renamed for clarity
- `IPv4Sources` is now named `IPv4LocalSubnets`
- `IPv6Sources` is now named `IPv6LocalSubnets`
- `IPv4Destinations` is now named `IPv4RemoteSubnets`
- `IPv6Destinations` is now named `IPv6RemoteSubnets`
- The old option names will continue to be accepted by the configuration parser for now but may not be indefinitely
- When presented with multiple paths between two nodes, the switch now prefers the most recently used port when possible instead of the least recently used, helping to reduce packet reordering
- New nonce tracking should help to reduce the number of packets dropped as a result of multiple/aggregate paths or congestion control in the switch
### Fixed
- A deadlock was fixed in the session code which could result in Yggdrasil failing to pass traffic after some time
### Security
- Address verification was not strict enough, which could result in a malicious session sending traffic with unexpected or spoofed source or destination addresses which Yggdrasil could fail to reject
- Versions `0.3.6` and `0.3.7` are vulnerable - users of these versions should upgrade as soon as possible
- Versions `0.3.5` and earlier are not affected
## [0.3.7] - 2019-08-14
### Changed
- The switch should now forward packets along a single path more consistently in cases where congestion is low and multiple equal-length paths exist, which should improve stability and result in fewer out-of-order packets
- Sessions should now be more tolerant of out-of-order packets, by replacing a bitmask with a variable sized heap+map structure to track recently received nonces, which should reduce the number of packets dropped due to reordering when multiple paths are used or multiple independent flows are transmitted through the same session
- The admin socket can no longer return a dotfile representation of the known parts of the network, this could be rebuilt by clients using information from `getSwitchPeers`,`getDHT` and `getSessions`
### Fixed
- A number of significant performance regressions introduced in version 0.3.6 have been fixed, resulting in better performance
- Flow labels are now used to prioritise traffic flows again correctly
- In low-traffic scenarios where there are multiple peerings between a pair of nodes, Yggdrasil now prefers the most active peering instead of the least active, helping to reduce packet reordering
- The `Listen` statement, when configured as a string rather than an array, will now be parsed correctly
- The admin socket now returns `coords` as a correct array of unsigned 64-bit integers, rather than the internal representation
- The admin socket now returns `box_pub_key` in string format again
- Sessions no longer leak/block when no listener (e.g. TUN/TAP) is configured
- Incoming session connections no longer block when a session already exists, which results in less leaked goroutines
- Flooded sessions will no longer block other sessions
- Searches are now cleaned up properly and a couple of edge-cases with duplicate searches have been fixed
- A number of minor allocation and pointer fixes
## [0.3.6] - 2019-08-03
### Added
- Yggdrasil now has a public API with interfaces such as `yggdrasil.ConnDialer`, `yggdrasil.ConnListener` and `yggdrasil.Conn` for using Yggdrasil as a transport directly within applications
- Session gatekeeper functions, part of the API, which can be used to control whether to allow or reject incoming or outgoing sessions dynamically (compared to the previous fixed whitelist/blacklist approach)
- Support for logging to files or syslog (where supported)
- Platform defaults now include the ability to set sane defaults for multicast interfaces
### Changed
- Following a massive refactoring exercise, Yggdrasil's codebase has now been broken out into modules
- Core node functionality in the `yggdrasil` package with a public API
- This allows Yggdrasil to be integrated directly into other applications and used as a transport
- IP-specific code has now been moved out of the core `yggdrasil` package, making Yggdrasil effectively protocol-agnostic
- Multicast peer discovery functionality is now in the `multicast` package
- Admin socket functionality is now in the `admin` package and uses the Yggdrasil public API
- TUN/TAP, ICMPv6 and all IP-specific functionality is now in the `tuntap` package
- `PPROF` debug output is now sent to `stderr` instead of `stdout`
- Node IPv6 addresses on macOS are now configured as `secured`
- Upstream dependency references have been updated, which includes a number of fixes in the Water library
### Fixed
- Multicast discovery is no longer disabled if the nominated interfaces aren't available on the system yet, e.g. during boot
- Multicast interfaces are now re-evaluated more frequently so that Yggdrasil doesn't need to be restarted to use interfaces that have become available since startup
- Admin socket error cases are now handled better
- Various fixes in the TUN/TAP module, particularly surrounding Windows platform support
- Invalid keys will now cause the node to fail to start, rather than starting but silently not working as before
- Session MTUs are now always calculated correctly, in some cases they were incorrectly defaulting to 1280 before
- Multiple searches now don't take place for a single connection
- Concurrency bugs fixed
- Fixed a number of bugs in the ICMPv6 neighbor solicitation in the TUN/TAP code
- A case where peers weren't always added correctly if one or more peers were unreachable has been fixed
- Searches which include the local node are now handled correctly
- Lots of small bug tweaks and clean-ups throughout the codebase
## [0.3.5] - 2019-03-13
### Fixed
- The `AllowedEncryptionPublicKeys` option has now been fixed to handle incoming connections properly and no longer blocks outgoing connections (this was broken in v0.3.4)
@ -33,7 +213,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [0.3.4] - 2019-03-12
### Added
- Support for multiple listeners (although currently only TCP listeners are supported)
- New multicast behaviour where each multicast interface is given it's own link-local listener and does not depend on the `Listen` configuration
- New multicast behaviour where each multicast interface is given its own link-local listener and does not depend on the `Listen` configuration
- Blocking detection in the switch to avoid parenting a blocked peer
- Support for adding and removing listeners and multicast interfaces when reloading configuration during runtime
- Yggdrasil will now attempt to clean up UNIX admin sockets on startup if left behind by a previous crash
@ -227,7 +407,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Wire format changes (backwards incompatible).
- Less maintenance traffic per peer.
- Exponential back-off for DHT maintenance traffic (less maintenance traffic for known good peers).
- Iterative DHT (added some time between v0.1.0 and here).
- Iterative DHT (added sometime between v0.1.0 and here).
- Use local queue sizes for a sort of local-only backpressure routing, instead of the removed bandwidth estimates, when deciding where to send a packet.
### Removed

View File

@ -23,15 +23,15 @@ Otherwise, you can generate a configuration file in the following ways:
Yggdrasil can accept a configuration file either through `stdin` or by being given a path on the filesystem to a configuration file:
- **Using stdin**: `yggdrasilctl --useconf < /etc/yggdrasil.conf`
- **Using file:** `yggdrasilctl --useconffile /etc/yggdrasil.conf`
- **Using stdin**: `yggdrasil -useconf < /etc/yggdrasil.conf`
- **Using file:** `yggdrasil -useconffile /etc/yggdrasil.conf`
## Normalising Configuration
If you want to see the original format of the configuration file, or convert between HJSON and JSON formats, you can use the `-normaliseconf` option, e.g.
- **Convert from HJSON to JSON**: `yggdrasilctl -normaliseconf -useconffile /etc/yggdrasil.conf -json`
- **Convert from JSON to HJSON**: `yggdrasilctl -normaliseconf -useconffile /etc/yggdrasil.conf`
- **Convert from HJSON to JSON**: `yggdrasil -normaliseconf -useconffile /etc/yggdrasil.conf -json`
- **Convert from JSON to HJSON**: `yggdrasil -normaliseconf -useconffile /etc/yggdrasil.conf`
Normalising the configuration also adds any missing configuration items with their default values. This can be useful when upgrading to a newer version of Yggdrasil that adds new configuration options. Many of our distribution packages normalise the configuration automatically during upgrade.
@ -41,33 +41,55 @@ A new configuration file has the following format. Please note that some of the
```
{
# Listen address for peer connections. Default is to listen for all
# TCP connections over IPv4 and IPv6 with a random port.
Listen: "[::]:xxxxx"
# List of connection strings for outbound peer connections in URI format,
# e.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections
# will obey the operating system routing table, therefore you should
# use this section when you may connect via different interfaces.
Peers: [
tcp://a.b.c.d:xxxxx
socks://e.f.g.h:xxxxx/a.b.c.d:xxxxx
tls://a.b.c.d:xxxxx
]
# Listen address for admin connections Default is to listen for local
# List of connection strings for outbound peer connections in URI format,
# arranged by source interface, e.g. { "eth0": [ tcp://a.b.c.d:e ] }.
# Note that SOCKS peerings will NOT be affected by this option and should
# go in the "Peers" section instead.
InterfacePeers: {
"eth0": [
tcp://a.b.c.d:xxxxx
tls://a.b.c.d:xxxxx
]
}
# Listen addresses for incoming connections. You will need to add
# listeners in order to accept incoming peerings from non-local nodes.
# Multicast peer discovery will work regardless of any listeners set
# here. Each listener should be specified in URI format as above, e.g.
# tcp://0.0.0.0:0 or tcp://[::]:0 to listen on all interfaces.
Listen: [
tcp://[::]:xxxxx
tls://[::]:xxxxx
]
# Listen address for admin connections. Default is to listen for local
# connections either on TCP/9001 or a UNIX socket depending on your
# platform. Use this value for yggdrasilctl -endpoint=X.
# platform. Use this value for yggdrasilctl -endpoint=X. To disable
# the admin socket, use the value "none" instead.
AdminListen: tcp://localhost:9001
# List of connection strings for static peers in URI format, e.g.
# tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j.
Peers: []
# Regular expressions for which interfaces multicast peer discovery
# should be enabled on. If none specified, multicast peer discovery is
# disabled. The default value is .* which uses all interfaces.
MulticastInterfaces:
[
.*
]
# List of connection strings for static peers in URI format, arranged
# by source interface, e.g. { "eth0": [ tcp://a.b.c.d:e ] }. Note that
# SOCKS peerings will NOT be affected by this option and should go in
# the "Peers" section instead.
InterfacePeers: {}
# Read timeout for connections, specified in milliseconds. If less
# than 6000 and not negative, 6000 (the default) is used. If negative,
# reads won't time out.
ReadTimeout: 0
# List of peer encryption public keys to allow or incoming TCP
# connections from. If left empty/undefined then all connections
# will be allowed by default.
# List of peer encryption public keys to allow incoming TCP peering
# connections from. If left empty/undefined then all connections will
# be allowed by default. This does not affect outgoing peerings, nor
# does it affect link-local peers discovered via multicast.
AllowedEncryptionPublicKeys: []
# Your public encryption key. Your peers may ask you for this to put
@ -84,13 +106,12 @@ A new configuration file has the following format. Please note that some of the
# Your private signing key. DO NOT share this with anyone!
SigningPrivateKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Regular expressions for which interfaces multicast peer discovery
# should be enabled on. If none specified, multicast peer discovery is
# disabled. The default value is .* which uses all interfaces.
MulticastInterfaces:
[
.*
]
# The port number to be used for the link-local TCP listeners for the
# configured MulticastInterfaces. This option does not affect listeners
# specified in the Listen option. Unless you plan to firewall link-local
# traffic, it is best to leave this as the default value of 0. This
# option cannot currently be changed by reloading config during runtime.
LinkLocalTCPPort: 0
# Local network interface name for TUN/TAP adapter, or "auto" to select
# an interface automatically, or "none" to run without TUN/TAP.
@ -146,24 +167,22 @@ A new configuration file has the following format. Please note that some of the
# Enable or disable tunnel routing.
Enable: false
# IPv6 CIDR subnets, mapped to the EncryptionPublicKey to which they
# should be routed, e.g. { "aaaa:bbbb:cccc::/e": "boxpubkey", ... }
IPv6Destinations: {}
# IPv6 subnets belonging to remote nodes, mapped to the node's public
# key, e.g. { "aaaa:bbbb:cccc::/e": "boxpubkey", ... }
IPv6RemoteSubnets: {}
# Optional IPv6 source subnets which are allowed to be tunnelled in
# addition to this node's Yggdrasil address/subnet. If not
# specified, only traffic originating from this node's Yggdrasil
# address or subnet will be tunnelled.
IPv6Sources: []
# IPv6 subnets belonging to this node's end of the tunnels. Only traffic
# from these ranges (or the Yggdrasil node's IPv6 address/subnet)
# will be tunnelled.
IPv6LocalSubnets: []
# IPv4 CIDR subnets, mapped to the EncryptionPublicKey to which they
# should be routed, e.g. { "a.b.c.d/e": "boxpubkey", ... }
IPv4Destinations: {}
# IPv4 subnets belonging to remote nodes, mapped to the node's public
# key, e.g. { "a.b.c.d/e": "boxpubkey", ... }
IPv4RemoteSubnets: {}
# IPv4 source subnets which are allowed to be tunnelled. Unlike for
# IPv6, this option is required for bridging IPv4 traffic. Only
# traffic with a source matching these subnets will be tunnelled.
IPv4Sources: []
# IPv4 subnets belonging to this node's end of the tunnels. Only traffic
# from these ranges will be tunnelled.
IPv4LocalSubnets: []
}
# Advanced options for tuning the switch. Normally you will not need
@ -174,6 +193,13 @@ A new configuration file has the following format. Please note that some of the
MaxTotalQueueSize: 4194304
}
# By default, nodeinfo contains some defaults including the platform,
# architecture and Yggdrasil version. These can help when surveying
# the network and diagnosing network routing problems. Enabling
# nodeinfo privacy prevents this, so that only items specified in
# "NodeInfo" are sent back if specified.
NodeInfoPrivacy: false
# Optional node info. This must be a { "key": "value", ... } map
# or set as null. This is entirely optional but, if set, is visible
# to the whole network on request.
@ -186,20 +212,21 @@ Note that any field not specified in the configuration will use its default valu
## Configuration Options
- `Listen`
- A string, in the form of `"ip:port"`, on which to listen for (TCP) connections from peers.
- A list of strings in the form `[ "tcp://listenAddress:listenPort", "tls://listenAddress:listenPort", ... ]`, on which to listen for TCP or TLS connections from peers.
- Note that, due to Go language design choices, `[::]` listens on IPv4 and IPv6 on most platforms, while an empty IP or `0.0.0.0` listens only to IPv4.
- The default is to listen on all addresses (`[::]`) with a random port.
- Note that a `tcp://` listener can only accept `tcp://` peer connections, and a `tls://` listener can only accept `tls://` peer connections
- `AdminListen`
- Port to listen on for the admin socket, specified in URI format, i.e. `tcp://localhost:9001`.
- On supported platforms, the admin socket can listen on a UNIX domain socket instead, i.e. `unix:///var/run/yggdrasil.sock`.
- The default is to listen on the loopback interface (`tcp://localhost:9001`) which ensures that only local connections to the admin socket are allowed.
- Note that if you change the listen address to a non-loopback address, this may allow other hosts on the network to manage the Yggdrasil process. This probably isn't desirable.
- `Peers`
- A list of strings in the form `[ "tcp://peerAddress:peerPort", "socks://proxyAddress:proxyPort/peerAddress:peerPort", ... ]` of peers to connect to.
- A list of strings in the form `[ "tcp://peerAddress:peerPort", "tls://peerAddress:peerPort", "socks://proxyAddress:proxyPort/peerAddress:peerPort", ... ]` of peers to connect to.
- Peer hostnames can be specified either using IPv4 addresses, IPv6 addresses or DNS names.
- Each entry should begin with `tcp://` or `socks://proxyAddress:proxyPort/`.
- `InterfacePeers`
- Like peers above, but arranged using specific interface names: `{ "eth0": [ "tcp://peerAddress:peerPort", "socks://proxyAddress:proxyPort/peerAddress:peerPort", ... ], "eth1": [], ... }` of peers to connect to.
- Like peers above, but arranged using specific interface names: `{ "eth0": [ "tcp://peerAddress:peerPort", "tls://peerAddress:peerPort", "socks://proxyAddress:proxyPort/peerAddress:peerPort", ... ], "eth1": [], ... }` of peers to connect to.
- Note that a `tcp://` peer connection can only connect to a `tcp://` listener, and a `tls://` peer connection can only connect to a `tls://` listener
- `AllowedEncryptionPublicKeys`
- A list of strings in the form `["key", "key", ...]`, where `key` is each node's `EncryptionPublicKey` key which you would like to allow connections from.
- This option allows you to restrict which other nodes can connect to your Yggdrasil node as a peer. It applies to incoming TCP connections.
@ -267,17 +294,17 @@ Note that any field not specified in the configuration will use its default valu
- `Enable`
- Enables crypto-key routing.
- If enabled, the following crypto-key routes will be used by Yggdrasil. If disabled, the below options have no effect.
- `IPv6Destinations`
- `IPv6RemoteSubnets`
- A list of routes in the form `{ "aaaa:bbbb:cccc::/e": "EncryptionPublicKey", ... }`
- For each entry, an IPv6 route entry will be created that sends traffic destined for `aaaa:bbbb:cccc::/e` to the node with the specified `EncryptionPublicKey` (effectively your "remote" ranges).
- `IPv6Sources`
- `IPv6LocalSubnets`
- A list of allowed source subnets in the form `[ "aaaa:bbbb:cccc::/e" ]`
- Specifies a list of source IPv6 addresses which are allowed to be sent over the tunnel (essentially your "local" ranges).
- Traffic from the Yggdrasil node's IPv6 address and routed subnet are always allowed.
- `IPv4Destinations`
- `IPv4RemoteSubnets`
- A list of routes in the form `{ "a.b.c.d/e": "EncryptionPublicKey", ... }`
- For each entry, an IPv4 route entry will be created that sends traffic destined for `a.b.c.d/e` to the node with the specified `EncryptionPublicKey` (effectively your "remote" ranges).
- `IPv4Sources`
- `IPv4LocalSubnets`
- A list of allowed source subnets in the form `[ "a.b.c.d/e" ]`
- Specifies a list of source IPv4 addresses which are allowed to be sent over the tunnel (essentially your "local" ranges).
- `SwitchOptions`
@ -344,7 +371,7 @@ interface eth0
```
Note that a `/64` prefix has fewer bits of address space available to check against the node's ID, which in turn means hash collisions are more likely.
As such, it is unwise to rely on addresses as a form of identify verification for the `300::/8` address range.
As such, it is unwise to rely on addresses as a form of identity verification for the `300::/8` address range.
## Generating Stronger Addresses (and Prefixes)
@ -356,7 +383,7 @@ This can partially mitigate the fact that IPv6 addresses are only 128 bits long,
In short, if you plan to advertise a prefix, or if you want your address to be exceptionally difficult to collide with, then it is strongly advised that you burn some CPU cycles generating a harder-to-collide set of keys, using the following tool:
```
GOPATH=$PWD go run -tags debug misc/genkeys.go
go run cmd/genkeys/main.go
```
This continually generates new keys and prints them out each time a new best set of keys is discovered.

8
faq.md
View File

@ -83,6 +83,14 @@ yggdrasilctl -endpoint=127.0.0.1:12345
You can set the `IfName` configuration setting to `"none"`. This will load Yggdrasil, but will not create a TUN/TAP adapter, meaning that your host will not be exposed to the Yggdrasil network. This does of course mean that you won't be able to send any traffic from that node to Yggdrasil either!
### Does Yggdrasil work alongside an existing VPN?
Yes, Yggdrasil should not interfere with existing VPNs. VPN traffic can be sent while using Yggdrasil.
### Does Yggdrasil work with networks like Tor or I2P?
Yggdrasil can peer over Tor or I2P. See [/public-peers/tree/master/other](https://github.com/yggdrasil-network/public-peers/tree/master/other) for public peers.
### I want to allow outgoing connections from my machine but prevent unwanted incoming connections.
Generally this requires you to use a firewall. The steps for this will vary from platform to platform.

View File

@ -11,7 +11,7 @@ Although Yggdrasil shares many similarities with [cjdns](https://github.com/cjde
## Project Status
The project is currently in early stages but it is being actively developed. We have recently released [version 0.3.5](changelog.md) and are still regularly working on updates.
The project is currently in early stages but it is being actively developed. We have recently released [version 0.3.14](changelog.md) and are still regularly working on updates.
A small number of users have been using and stress-testing Yggdrasil quite heavily for a number of purposes, including but not limited to secure remote access (SSH and VNC), access to Matrix, Jabber and IRC servers and even some video streams, large file transfers and performance tests. We have a number of [internal services](services.md) available, contributed and operated by the community.
@ -21,7 +21,7 @@ Binaries are [automatically built](https://circleci.com/gh/yggdrasil-network/ygg
## Implementation
Yggdrasil is written in Go. The codebase is fairly small and easy to navigate. It has been tested on a number of platforms (including [Linux](platform-linux.md), [Windows](platform-windows.md), [macOS](platform-macos.md), NetBSD, FreeBSD, OpenBSD and [Ubiquiti EdgeOS](platform-edgerouter.md)) although with various minor caveats. See the [Platforms](platforms.md) page for more information.
Yggdrasil is written in Go. The codebase is fairly small and easy to navigate. It has been tested on a number of platforms (including [Linux](platform-linux.md), [Windows](platform-windows.md), [macOS](platform-macos.md), FreeBSD, OpenBSD and [Ubiquiti EdgeOS](platform-edgerouter.md)) although with various minor caveats. See the [Platforms](platforms.md) page for more information.
## Get Involved

View File

@ -22,13 +22,13 @@ sudo apt-get install dirmngr
Then import the repository key to your `gpg` keyring and export it to your
`apt` keyring:
```
gpg --fetch-keys https://neilalexander.s3.eu-west-2.amazonaws.com/deb/key.txt
gpg --fetch-keys https://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/key.txt
gpg --export 569130E8CA20FBC4CB3FDE555898470A764B32C9 | sudo apt-key add -
```
Add the repository into your `apt` sources:
```
echo 'deb http://neilalexander.s3.eu-west-2.amazonaws.com/deb/ debian yggdrasil' | sudo tee /etc/apt/sources.list.d/yggdrasil.list
echo 'deb http://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/ debian yggdrasil' | sudo tee /etc/apt/sources.list.d/yggdrasil.list
sudo apt-get update
```

View File

@ -16,7 +16,7 @@ configured.
Start by adding the GPG key:
```
curl -o- https://neilalexander.s3.eu-west-2.amazonaws.com/deb/key.txt | sudo apt-key add -
curl -o- https://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/key.txt | sudo apt-key add -
```
Then add the repository:
@ -24,7 +24,7 @@ Then add the repository:
configure
set system package repository yggdrasil distribution edgerouter
set system package repository yggdrasil components yggdrasil
set system package repository yggdrasil url http://neilalexander.s3.eu-west-2.amazonaws.com/deb/
set system package repository yggdrasil url http://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/
commit
save
```

View File

@ -0,0 +1,79 @@
---
tags: dontlink
sitemap: true
---
# Installing on Gentoo Linux
Yggdrasil is hosted in the Gentoo GURU repository as the
[net-p2p/yggdrasil-go](https://gitweb.gentoo.org/repo/proj/guru.git/tree/net-p2p/yggdrasil-go)
package.
## Package install from the GURU repository
The GURU repository has to be enabled using `eselect repository`.
```
sudo eselect repository enable guru
```
And then synchronized with `emerge`:
```
sudo emerge --sync
```
Now, the `net-p2p/yggdrasil-go` package is masked and marked as unstable using
the `~amd64` keyword. So we have to unmask it by accepting the keyword, there
are two alternatives.
1. If `/etc/portage/package.accept_keywords` is a directory:
```
echo "net-p2p/yggdrasil-go ~amd64" | sudo tee /etc/portage/package.accept_keywords/yggdrasil-go
```
2. If `/etc/portage/package.accept_keywords` is a file:
```
echo "net-p2p/yggdrasil-go ~amd64" | sudo tee -a /etc/portage/package.accept_keywords
```
Now `net-p2p/yggdrasil-go` can be merged and installed with:
```
sudo emerge --ask net-p2p/yggdrasil-go
```
And you're good to go!
## Making configuration changes
Modify the `/etc/yggdrasil.conf` file and then either reload the config:
1. OpenRC
```
rc-service yggdrasil reload
```
2. systemd
```
systemctl reload yggdrasil
```
... or restart the Yggdrasil daemon altogether:
1. OpenRC
```
rc-service yggdrasil restart
```
2. systemd
```
systemctl restart yggdrasil
```
## After installation
Read the [Linux platform page](platform-linux.md) page for further
information about Linux platform support.

View File

@ -0,0 +1,32 @@
---
tags: dontlink
sitemap: true
---
# Installing on OpenWrt 19.07
Yggdrasil is supported on the OpenWrt based router.
Perform installation steps over SSH by connecting to the Router as the
`root` user, e.g. `ssh root@192.168.1.1`, or another admin-level user if
configured.
## Package install from repository
Install the `yggdrasil` package:
```
opkg update
opkg install yggdrasil
```
Yggdrasil can then be updated in the future by updating the packages:
```
opkg update
opkg upgrade yggdrasil
```
## After installation
Read the [OpenWrt platform page](platform-openwrt.md) page for information
on how to configure Yggdrasil and guidance on modifying the configuration.

69
installation-windows.md Normal file
View File

@ -0,0 +1,69 @@
---
tags: dontlink
sitemap: true
---
# Installing using the Windows installer
Yggdrasil is supported on Windows. You can [download the latest installer from
GitHub](https://github.com/yggdrasil-network/yggdrasil-go/releases).
## TUN driver
Starting with version 0.3.13, Yggdrasil on Windows uses the Wireguard TUN
driver. If this is not installed on the system already, it will be installed
automatically by the Yggdrasil installer.
For this reason, it is important that you use the correct installer for your
architecture - make sure to use the `x64` installer on 64-bit Windows and the
`x86` installer on 32-bit Windows.
Please note that the OpenVPN TAP driver is **no longer supported**.
Once Yggdrasil is started, a new virtual network adapter will be created called
`Yggdrasil` by default, although this can be renamed using the `IfName` option
in the configuration file (below). The virtual network adapter will *not* be
visible on the system when Yggdrasil is not running.
## Configuration
The Yggdrasil installer will automatically generate an `yggdrasil.conf`
configuration file, if one does not exist, in the following locations:
- 64-bit Windows: `C:\Program Files\Yggdrasil`
- 32-bit Windows: `C:\Program Files (x86)\Yggdrasil`
## Windows Service
Yggdrasil is installed as a Windows service that starts automatically with
Windows. You can start, stop and restart Yggdrasil using the Services MMC
snap-in (`services.msc`) or, in more recent versions of Windows, the "Services"
tab in Task Manager.
You will need to restart the Yggdrasil service after each change to the
configuration file.
## Windows Firewall
Windows Firewall may prompt for the Yggdrasil process to allow incoming or
outgoing connections. If so, you should allow this or Yggdrasil may not be able
to establish peerings correctly.
Note that Yggdrasil, by default, does allow incoming traffic over the
`Yggdrasil` virtual adapter, therefore you may wish to designate the `Yggdrasil`
virtual network adapter as a public network in the Windows Firewall so that
unexpected incoming connections are blocked automatically.
If you do, pay particular attention to ensure that file sharing (SMB), remote
procedure call (RPC) or remote desktop (RDP) services are not allowed on public
networks unless you explicitly need them to be accessible from remote Yggdrasil
hosts.
## yggdrasilctl
The `yggdrasilctl` utility is also installed into the same location above. You
can query Yggdrasil's runtime state using this tool using a Command Prompt or
PowerShell command line, e.g.
```
"C:\Program Files\Yggdrasil\yggdrasilctl.exe" getPeers
```

View File

@ -10,6 +10,7 @@ Installation guides are available for the following platforms/distributions.
- [Debian, Ubuntu, elementaryOS, Linux Mint and similar](installation-linux-deb.md)
- [Red Hat Enterprise Linux, Fedora, CentOS and similar](installation-linux-rpm.md)
- [Gentoo Linux](installation-linux-gentoo.md)
- [Ubiquiti EdgeOS](installation-linux-edgeos.md)
- [Manual install or build from source](installation-linux-other.md)
@ -21,3 +22,7 @@ Installation guides are available for the following platforms/distributions.
## iOS
- [App installation](installation-ios-app.md)
## Windows
- [Windows `.msi` installer](installation-windows.md)

View File

@ -13,3 +13,4 @@ Yggdrasil is well supported on Linux.
- The maximum MTU size supported on Linux is 65535 in TUN mode and 65521 in TAP mode.
- IPv6 needs to be enabled in order for Yggdrasil to work - IPv6 is usually enabled by default, but if not, enable using `sysctl -w net.ipv6.conf.all.disable_ipv6=0` or similar.
- If using TUN/TAP then `/dev/net/tun` should be present on your system.
- The [BBR](https://github.com/google/bbr) congestion control algorithm is strongly recommended, as it can significantly reduce latency when under load. On recent distributions, this can be done with `sysctl -w net.ipv4.tcp_congestion_control=bbr` or similar.

View File

@ -1,74 +0,0 @@
---
tags: dontlink
sitemap: true
---
# Windows
Yggdrasil has been tested and is working on the following versions of Windows:
- Windows 7
- Windows 8.1
- Windows 10
- Windows Server 2016
It may work on other versions of Windows too, although these are untested.
## TAP Driver
Yggdrasil depends on the OpenVPN TAP driver to work on Windows. There are two flavours of this driver:
- [NDIS 5](https://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe) (`tap-windows-9.9.2_3`) - recommended
- [NDIS 6](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe) (`tap-windows-9.21.2`) - functional
Yggdrasil works with either driver, although the performance is remarkably better with the older NDIS 5 driver, therefore it is recommended to use that instead of the NDIS 6 driver.
Please note that if you already have OpenVPN for Windows, you likely have one of the two drivers installed already and should not install it again.
## Notes
- TUN mode is not supported on Windows, and attempts to configure TUN mode will default to TAP mode automatically.
## Installation
Start by [downloading the latest Yggdrasil binary](builds.md) and use Windows Explorer to copy it into a sensible location and rename it to `yggdrasil.exe`.
The below examples assume that you placed `yggdrasil.exe` into `C:\Program Files\Yggdrasil`.
## Generate configuration
Before starting Yggdrasil, you should generate configuration. Open a Command Prompt as Administrator:
```
"C:\Program Files\Yggdrasil\yggdrasil.exe" -genconf > "C:\Program Files\Yggdrasil\yggdrasil.conf"
```
## Run Yggdrasil
### Run once
Open a Command Prompt as Administrator and start Yggdrasil using your generated configuration:
```
"C:\Program Files\Yggdrasil\yggdrasil.exe" -useconffile "C:\Program Files\Yggdrasil\yggdrasil.conf"
```
Alternatively, start Yggdrasil in auto-configuration mode:
```
"C:\Program Files\Yggdrasil\yggdrasil.exe" -autoconf
```
### Run as a background service
Running as a background system service means that Yggdrasil will automatically start up in the background when Windows boots.
Assuming that Yggdrasil is installed into `C:\Program Files\Yggdrasil` and your configuration *already exists* in `C:\Program Files\Yggdrasil\yggdrasil.conf`, as above, then you can install Yggdrasil as a Windows service. Open a Command Prompt as Administrator:
```
sc create yggdrasil binpath= "\"C:\Program Files\Yggdrasil\yggdrasil.exe\" -useconffile \"C:\Program Files\Yggdrasil\yggdrasil.conf\""
sc config yggdrasil displayname= "Yggdrasil Service"
sc config yggdrasil start= "auto"
sc start yggdrasil
```
Alternatively, if you want the service to autoconfigure instead of using an `yggdrasil.conf`, replace the `sc create` line from above with:
```
sc create yggdrasil binpath= "\"C:\Program Files\Yggdrasil\yggdrasil.exe\" -autoconf"
```
The Yggdrasil service can then be stopped and started using `services.msc`, or in more recent versions of Windows, the Task Manager.

View File

@ -16,10 +16,6 @@ sitemap: true
- See the [iOS platform page](platform-ios.md).
## Windows
- See the [Windows platform page](platform-windows.md).
## EdgeRouter
- See the [EdgeRouter platform page](platform-edgerouter.md).

View File

@ -20,13 +20,28 @@ The following services are available on the Yggdrasil network, courtesy of our c
----
### Clearnet Tunnel Service
- Automated GRE over Yggdrasil service for clearnet IPv4 access.
- Accessible at http://[301:a003:3f0f:1aa0::1001]/dokuwiki/doku.php?id=ygre:howto
## Websites
### Search
- [YaCy](http://[301:4541:2f84:1188:216:3eff:fe38:cefc]:8090/) - an internal search engine.
- Accessible via Yggdrasil at `http://[301:4541:2f84:1188:216:3eff:fe38:cefc]:8090/`.
### Forums
- [Mesh Forum](http://[303:60d4:3d32:a2b9::4]/) - a chit-chat forum about everything. Run by @pztrn.
- Accessible via Yggdrasil at `http://[303:60d4:3d32:a2b9::4]/`.
- Accessible via I2P at `http://meshforum.i2p` or `http://hp2uzysaur74tbeojtlcsl7apsy2jgqxydd7b5asgvztihz76jia.b32.i2p/`.
- [Yggedit](http://[301:b614:c68e:b27f::1]/) - a link aggregator / reddit alternative
- Accessible via Yggdrasil at `http://[301:b614:c68e:b27f::1]/`.
- [Yggy Forum](http://[301:b614:c68e:b27f::2]/) - a fast forum with many features
- Accessible via Yggdrasil at `http://[301:b614:c68e:b27f::2]/`.
### Wikis
@ -34,6 +49,7 @@ The following services are available on the Yggdrasil network, courtesy of our c
----
## Shell accounts
### BAN.AI Public Access Multics Service
@ -82,13 +98,37 @@ The following services are available on the Yggdrasil network, courtesy of our c
- Yggdrasil's SSL port uses same certificate as the public Internet node, so you **will** receive SSL warning, this is expected
- Join `#en` for english discussions
### ED12 IRC
- `y.kaotisk-hund.tk` is accessible via Yggdrasil at `202:68fd:1f72:8505:74d6:b751:29ce:b5bb` port `6667` (TCP)
- Main channel is `#general`
- Other channels can be listed with description as their topic
- Also accessible via cjdns at `fc42:7cfa:b830:e988:f192:717f:6576:ed12` port `6667` (TCP)
----
## Matrix
## XMPP
### chat.station.moe
- `chat.station.moe`, run by [zhoreeq](https://github.com/zhoreeq)
- Webchat is at [http://[305:1bba:6a3:7f24::23]/](http://[305:1bba:6a3:7f24::23]/) or http://chat.station.moe/. General chat room is at `ygg@conference.station.moe`.
- Unnecessary TLS is removed. XMPP clients should allow authorization over plaintext and disable TLS/SSL/STARTTLS enforcement.
- XMPP federation is enabled inside Yggdrasil network. [Example config file for Prosody](https://gist.github.com/zhoreeq/0f293cc7c338554369261cfdfab55ddc).
### netwhood.online
- `http://[202:12a9:e5:4474:d473:82be:16ac:9381]:8008` run by [abslimit](http://netwhood.online/feedback/)
- `netwhood.online`, run by [abslimit](http://netwhood.online/feedback/)
- SRV record `_xmpp-client._tcp` is prioritized for `y.netwhood.online` (`202:12a9:e5:4474:d473:82be:16ac:9381`). XMPP-client must try yggdrasil address at first.
- SRV record `_xmpp-server._tcp` is prioritized for `y.netwhood.online` too. XMPP s2s connections must try yggdrasil address at first. Lets peer?
- "HTTP upload" XEP module is tied to `netwhood.online`, it will connect through the Internet. It can not be prioritized for yggdrasil.
### infradian.icu and ultradian.club
- `infradian.icu` and `ultradian.club`, run by [Umbrellix](http://yww.umbrellix.net/contact/)
- The SRV record `_xmpp-server._tcp` for all of the relevant subdomains has a domain that points to `202:8fb5:1490:594d:7e29:98fd:8d79:953f` at priority 1, and the clearnet machine which that represents at priority 2 (so that clearnet XMPPers/Snikketers/Jabberers will be able to message you if you are on infradian or ultradian)
- The SRV record `_xmpp-client._tcp` for @ only has the domain which points to `202:8fb5:1490:594d:7e29:98fd:8d79:953f`. There is a non-obvious way to connect over clearnet, which will not be disclosed here.
- HTTP upload, unlike on the other domain Umbrellix has which is clearnet-based, is disabled.
----
@ -105,6 +145,23 @@ The following services are available on the Yggdrasil network, courtesy of our c
- [Arceliar's Interactive Network Map](http://[21f:dd73:7cdb:773b:a924:7ec0:800b:221e])
- [y.yakamo.org Static World Map](http://[301:4541:2f84:1188:216:3eff:feb6:65a3]:3000/static/map.png)
### IPv6 address information
- http://[300:aa35:f9c1:dcce::2]/
----
## NNTP
### pztrn's NNTP server
- [Website with rules, news and documentation](https://nntp.pztrn.name).
- Registration required to access all groups beyond `local.regreq` which is used for registration requests. No anonymous postings allowed.
- ygg.* hierarchy for talks about Yggdrasil! :)
- Accessible via Yggdrasil at `201:e64d:1a9:d2b0:9c74:f285:ea73:5e05` ports `119` (plain text) and `563` (TLSv1.0+ only).
- Accessible via public Internet at `nntp.pztrn.name` ports `119` (plain text) and `563` (TLSv1.0+ only).
- SSL warnings via Yggdrasil expected, certificate is for *.pztrn.name. You can workaround it by adding entry in hosts file.
- Peering is welcome, especially via Yggdrasil.
----
## BitTorrent
@ -118,6 +175,11 @@ The following services are available on the Yggdrasil network, courtesy of our c
- [neilalexander](https://matrix.to/#/@neilalexander:matrix.org)'s IPFS gateway is available at `http://ipfs.y.neilalexander.eu/ipfs/` ([test link](http://ipfs.y.neilalexander.eu/ipfs/QmZiSAYkU7gZtqYeZWL21yuwgFtRnJu1JjDzR6Qd2qdDBr/))
### IPFS Bootstrap Swarm
- Irvine, CA Based Server Boostrap Node hosted by @KylerChin
`/ip6/202:d0ca:a9d7:b4e8:bd3c:ffde:5c89:a3d7/tcp/4001/ipfs/QmZEiPvrfZHapq4uiyTDEcR2szCUhDnjdS4q3Uv2b1Uh88`
----
## Gaming
@ -127,6 +189,13 @@ The following services are available on the Yggdrasil network, courtesy of our c
- DNS name: `mc.y.creativeserver.net`
- Survival mode map, ask piele to be whitelisted
### Minetest
- `300:aa35:f9c1:dcce::3:30000`, admin Admin
### Xonotic
- `201:9d54:3c57:d6d2:e8d7:a8ce:841f:eb89:26000`
- DNS name: `xonotic.y.netwhood.online:26000`
----
## DNS
@ -143,7 +212,10 @@ The following services are available on the Yggdrasil network, courtesy of our c
- Will ask 1.1.1.1 over TLS, recursive resolving currently disabled due to inferior speed.
- `200:a120:8cf8:2ad5:7509:7341:c861:34aa` port 53 hosted by [sin](https://2f30.org)
- Supports clearnet resolution of standard DNS domains via root lookups
- `200:d0c4:68ee:e87b:c206:67b8:5fa5:d4be` port 53, hosted by [Medium](https://github.com/medium-isp)
- Internal Yggdrasil services resolver
- `200:5bf2:a7a5:27c7:54b8:6669:eb74:1813` port 53, hosted by [User2k](https://user2k.eu)
- Medium DNS, OpenDNS, Google DNS and CloudFlare DNS
----
## ZeroNet
@ -172,5 +244,22 @@ The following services are available on the Yggdrasil network, courtesy of our c
## Direct Connect
- DC-hub by *whoami* `adc://[202:9877:2815:cd91:336:2a16:bfd9:7258]:1511`
- Works with clients who support IPv6 and ADC. Ncdc or Airdcpp for example (eiskaltdc++ not support IPv6)
- bepis DC-hub run by *Jeff* `adc://[203:e0b0:ec08:4e1f:f004:19a9:577a:90ba]:1511`
----
## [iPerf3](https://iperf.fr)
- `iperf3 -6 -c y.thingylabs.io` on [ygg.thingylabs.io](https://ygg.thingylabs.io/)
- Link: 10 GBit
- Location: Nuremberg, Germany
----
## Bitcoin
### Node by [vkeb6rza](https://vkeb6rza.github.io/) at `204:381:4c98:df09:d15b:ab1e:894b:d99e`
- Port 8333 - Bitcoin Core with BIP157 and BIP158 experimental support
- Port 9735 - Lightning Network - `038758ca700b8c4c73d1b86440acb963be93e5b11f9d6f363041be43572c8cbd43@[204:381:4c98:df09:d15b:ab1e:894b:d99e]:9735`
- Port 9911 - LND Watchtower
- Port 50001 - Electrum server