- New simulation code under `cmd/yggdrasilsim` (work-in-progress)
### Changed
- Multi-threading in the switch
- Swich lookups happen independently for each (incoming) peer connection, instead of being funneled to a single dedicated switch worker
- Packets are queued for each (outgoing) peer connection, instead of being handled by a single dedicated switch worker
- Queue logic rewritten
- Heap structure per peer that traffic is routed to, with one FIFO queue per traffic flow
- The total size of each heap is configured automatically (we basically queue packets until we think we're blocked on a socket write)
- When adding to a full heap, the oldest packet from the largest queue is dropped
- Packets are popped from the queue in FIFO order (oldest packet from among all queues in the heap) to prevent packet reordering at the session level
- Removed global `sync.Pool` of `[]byte`
- Local `sync.Pool`s are used in the hot loops, but not exported, to avoid memory corruption if libraries are reused by other projects
- This may increase allocations (and slightly reduce speed in CPU-bound benchmarks) when interacting with the tun/tap device, but traffic forwarded at the switch layer should be unaffected
- Upgrade dependencies
- Upgrade build to Go 1.16
### Fixed
- Fixed a bug where the connection listener could exit prematurely due to resoruce exhaustion (if e.g. too many connections were opened)
- Fixed DefaultIfName for OpenBSD (`/dev/tun0` -> `tun0`)
- Fixed an issue where a peer could sometimes never be added to the switch
- Fixed a goroutine leak that could occur if a peer with an open connection continued to spam additional connection attempts
- 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
- 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:
- 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
- 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`
- 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
- 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
- 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`
- 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
- 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
- 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)
- Multicast TCP listeners will now be stopped correctly when the link-local address on the interface changes or disappears altogether
- On macOS, Yggdrasil will now try to wake up AWDL on start-up when `awdl0` is a configured multicast interface, to keep it awake after system sleep, and to stop waking it when no longer needed
- Added `LinkLocalTCPPort` option for controlling the port number that link-local TCP listeners will listen on by default when setting up `MulticastInterfaces` (a node restart is currently required for changes to `LinkLocalTCPPort` to take effect - it cannot be updated by reloading config during runtime)
- The `Listen` configuration statement is now an array instead of a string
- The `Listen` configuration statement should now conform to the same formatting as peers with the protocol prefix, e.g. `tcp://[::]:0`
- Session workers are now non-blocking
- Multicast interval is now fixed at every 15 seconds and network interfaces are reevaluated for eligibility on each interval (where before the interval depended upon the number of configured multicast interfaces and evaluation only took place at startup)
- Dead connections are now closed in the link handler as opposed to the switch
- Peer forwarding is now prioritised instead of randomised
### Fixed
- Admin socket `getTunTap` call now returns properly instead of claiming no interface is enabled in all cases
- Handling of `getRoutes` etc in `yggdrasilctl` is now working
- Local interface names are no longer leaked in multicast packets
- Link-local TCP connections, particularly those initiated because of multicast beacons, are now always correctly scoped for the target interface
- Yggdrasil now correctly responds to multicast interfaces going up and down during runtime
- Dynamic reconfiguration, which allows reloading the configuration file to make changes during runtime by sending a `SIGHUP` signal (note: this only works with `-useconffile` and not `-useconf` and currently reconfiguring TUN/TAP is not supported)
- Support for building Yggdrasil as an iOS or Android framework if the appropriate tools (e.g. `gomobile`/`gobind` + SDKs) are available
- Connection contexts used for TCP connections which allow more exotic socket options to be set, e.g.
- Reusing the multicast socket to allow multiple running Yggdrasil instances without having to disable multicast
- Allowing supported Macs to peer with other nearby Macs that aren't even on the same Wi-Fi network using AWDL
- Flexible logging support, which allows for logging at different levels of verbosity
### Changed
- Switch changes to improve parent selection
- Node configuration is now stored centrally, rather than having fragments/copies distributed at startup time
- Significant refactoring in various areas, including for link types (TCP, AWDL etc), generic streams and adapters
- macOS builds through CircleCI are now 64-bit only
- The admin socket is now multithreaded, greatly improving performance of the crawler and allowing concurrent lookups to take place
- The ability to hide NodeInfo defaults through either setting the `NodeInfoPrivacy` option or through setting individual `NodeInfo` attributes to `null`
### Changed
- The `armhf` build now targets ARMv6 instead of ARMv7, adding support for Raspberry Pi Zero and other older models, amongst others
### Fixed
- DHT entries are now populated using a copy in memory to fix various potential DHT bugs
- DHT traffic should now throttle back exponentially to reduce idle traffic
- Adjust how nodes are inserted into the DHT which should help to reduce some incorrect DHT traffic
- In TAP mode, the NDP target address is now correctly used when populating the peer MAC table. This fixes serious connectivity problems when in TAP mode, particularly on BSD
- In TUN mode, ICMPv6 packets are now ignored whereas they were incorrectly processed before
- The address range was moved from `fd00::/8` to `200::/7`. This range was chosen as it is marked as deprecated. The change prevents overlap with other ULA privately assigned ranges.
- UTF-16 detection conversion for configuration files, which can particularly be a problem on Windows 10 if a configuration file is generated from within PowerShell.
- 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
- UDP peering, this may be added again if/when a better implementation appears.