mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-29 22:55:06 +03:00
cleaned up develop branch
This commit is contained in:
parent
bfe42d8899
commit
2d36105eeb
17 changed files with 102 additions and 817 deletions
64
CHANGELOG.md
64
CHANGELOG.md
|
@ -27,9 +27,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## [0.4.0] - 2021-07-04
|
## [0.4.0] - 2021-07-04
|
||||||
### Added
|
### Added
|
||||||
- New routing scheme, which is backwards incompatible with previous versions of Mesh
|
- New routing scheme, which is backwards incompatible with previous versions of Yggdrasil
|
||||||
- The wire protocol version number, exchanged as part of the peer setup handshake, has been increased to 0.4
|
- The wire protocol version number, exchanged as part of the peer setup handshake, has been increased to 0.4
|
||||||
- Nodes running this new version **will not** be able to peer with earlier versions of Mesh
|
- Nodes running this new version **will not** be able to peer with earlier versions of Yggdrasil
|
||||||
- Please note that **the network may be temporarily unstable** while infrastructure is being upgraded to the new release
|
- Please note that **the network may be temporarily unstable** while infrastructure is being upgraded to the new release
|
||||||
- TLS connections now use public key pinning
|
- TLS connections now use public key pinning
|
||||||
- If no public key was already pinned, then the public key received as part of the TLS handshake is pinned to the connection
|
- If no public key was already pinned, then the public key received as part of the TLS handshake is pinned to the connection
|
||||||
|
@ -38,7 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
### Changed
|
### Changed
|
||||||
- IP addresses are now derived from ed25519 public (signing) keys
|
- IP addresses are now derived from ed25519 public (signing) keys
|
||||||
- Previously, addresses were derived from a hash of X25519 (Diffie-Hellman) keys
|
- Previously, addresses were derived from a hash of X25519 (Diffie-Hellman) keys
|
||||||
- Importantly, this means that **all internal IPv6 addresses will change with this release** — this will affect anyone running public services or relying on Mesh for remote access
|
- Importantly, this means that **all internal IPv6 addresses will change with this release** — this will affect anyone running public services or relying on Yggdrasil for remote access
|
||||||
- It is now recommended to peer over TLS
|
- It is now recommended to peer over TLS
|
||||||
- Link-local peers from multicast peer discovery will now connect over TLS, with the key from the multicast beacon pinned to the connection
|
- Link-local peers from multicast peer discovery will now connect over TLS, with the key from the multicast beacon pinned to the connection
|
||||||
- `socks://` peers now expect the destination endpoint to be a `tls://` listener, instead of a `tcp://` listener
|
- `socks://` peers now expect the destination endpoint to be a `tls://` listener, instead of a `tcp://` listener
|
||||||
|
@ -64,7 +64,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
### Removed
|
### Removed
|
||||||
- Tunnel routing (a.k.a. crypto-key routing or "CKR") has been removed
|
- Tunnel routing (a.k.a. crypto-key routing or "CKR") has been removed
|
||||||
- It was far too easy to accidentally break routing altogether by capturing the route to peers with the TUN adapter
|
- It was far too easy to accidentally break routing altogether by capturing the route to peers with the TUN adapter
|
||||||
- We recommend tunnelling an existing standard over Mesh instead (e.g. `ip6gre`, `ip6gretap` or other similar encapsulations, using Mesh IPv6 addresses as the tunnel endpoints)
|
- We recommend tunnelling an existing standard over Yggdrasil instead (e.g. `ip6gre`, `ip6gretap` or other similar encapsulations, using Yggdrasil IPv6 addresses as the tunnel endpoints)
|
||||||
- All `TunnelRouting` configuration options will no longer take effect
|
- All `TunnelRouting` configuration options will no longer take effect
|
||||||
- Session firewall has been removed
|
- Session firewall has been removed
|
||||||
- This was never a true firewall — it didn't behave like a stateful IP firewall, often allowed return traffic unexpectedly and was simply a way to prevent a node from being flooded with unwanted sessions, so the name could be misleading and usually lead to a false sense of security
|
- This was never a true firewall — it didn't behave like a stateful IP firewall, often allowed return traffic unexpectedly and was simply a way to prevent a node from being flooded with unwanted sessions, so the name could be misleading and usually lead to a false sense of security
|
||||||
|
@ -109,7 +109,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- By encryption public key: `tcp://host:port?curve25519=key`
|
- By encryption public key: `tcp://host:port?curve25519=key`
|
||||||
- By both: `tcp://host:port?ed25519=key&curve25519=key`
|
- By both: `tcp://host:port?ed25519=key&curve25519=key`
|
||||||
- By multiple, in case of DNS round-robin or similar: `tcp://host:port?curve25519=key&curve25519=key&ed25519=key&ed25519=key`
|
- By multiple, in case of DNS round-robin or similar: `tcp://host:port?curve25519=key&curve25519=key&ed25519=key&ed25519=key`
|
||||||
- Some checks to prevent Mesh-over-Mesh peerings have been added
|
- Some checks to prevent Yggdrasil-over-Yggdrasil peerings have been added
|
||||||
- Added support for SOCKS proxy authentication, e.g. `socks://user@password:host/...`
|
- Added support for SOCKS proxy authentication, e.g. `socks://user@password:host/...`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -136,14 +136,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Windows `.msi` installer files are now supported (bundling the Wireguard TUN driver)
|
- Windows `.msi` installer files are now supported (bundling the Wireguard TUN driver)
|
||||||
- NodeInfo code is now actorised, should be more reliable
|
- 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 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 Mesh API now supports dialing a remote node using the public key instead of the Node ID
|
- The Yggdrasil API now supports dialing a remote node using the public key instead of the Node ID
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- The `-loglevel` command line parameter is now cumulative and automatically includes all levels below the one specified
|
- 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 code has been significantly simplified and processes rumoured nodes in parallel, speeding up search time
|
||||||
- DHT search results are now sorted
|
- DHT search results are now sorted
|
||||||
- The systemd service now handles configuration generation in a different unit
|
- The systemd service now handles configuration generation in a different unit
|
||||||
- The Mesh API now returns public keys instead of node IDs when querying for local and remote addresses
|
- The Yggdrasil API now returns public keys instead of node IDs when querying for local and remote addresses
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- The multicast code no longer panics when shutting down the node
|
- The multicast code no longer panics when shutting down the node
|
||||||
|
@ -159,7 +159,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
### Added
|
### Added
|
||||||
- New API functions `SetMaximumSessionMTU` and `GetMaximumSessionMTU`
|
- 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`
|
- 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 Mesh output at startup when the MTU in the config is invalid or has been adjusted for some reason
|
- 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
|
### Changed
|
||||||
- On Linux, outgoing `InterfacePeers` connections now use `SO_BINDTODEVICE` to prefer an outgoing interface
|
- On Linux, outgoing `InterfacePeers` connections now use `SO_BINDTODEVICE` to prefer an outgoing interface
|
||||||
|
@ -175,10 +175,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## [0.3.11] - 2019-10-25
|
## [0.3.11] - 2019-10-25
|
||||||
### Added
|
### 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 Mesh peerings inside regular TLS connections
|
- 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
|
### Changed
|
||||||
- Go 1.13 or later is now required for building Mesh
|
- Go 1.13 or later is now required for building Yggdrasil
|
||||||
- Some exported API functions have been updated to work with standard Go interfaces:
|
- Some exported API functions have been updated to work with standard Go interfaces:
|
||||||
- `net.Conn` instead of `mesh.Conn`
|
- `net.Conn` instead of `mesh.Conn`
|
||||||
- `net.Dialer` (the interface it would satisfy if it wasn't a concrete type) instead of `mesh.Dialer`
|
- `net.Dialer` (the interface it would satisfy if it wasn't a concrete type) instead of `mesh.Dialer`
|
||||||
|
@ -195,17 +195,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- The core library now includes several unit tests for peering and `mesh.Conn` connections
|
- The core library now includes several unit tests for peering and `mesh.Conn` connections
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- On recent Linux kernels, Mesh 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
|
- 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 Mesh to the `CAP_NET_ADMIN` capability for managing the TUN/TAP adapter, rather than letting it do whatever the (typically `root`) user can do
|
- 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
|
### Fixed
|
||||||
- The `mesh.Conn.RemoteAddr()` function no longer blocks, fixing a deadlock when CKR is used while under heavy load
|
- The `mesh.Conn.RemoteAddr()` function no longer blocks, fixing a deadlock when CKR is used while under heavy load
|
||||||
|
|
||||||
## [0.3.9] - 2019-09-27
|
## [0.3.9] - 2019-09-27
|
||||||
### Added
|
### Added
|
||||||
- Mesh will now complain more verbosely when a peer URI is incorrectly formatted
|
- 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
|
- 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 Mesh is first started to increase the chance of finding nearby nodes quickly after startup
|
- 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
|
### 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
|
- 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
|
||||||
|
@ -223,7 +223,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- A race condition when dialing a remote node by both the node address and routed prefix simultaneously has been fixed
|
- 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 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 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 Mesh for builds 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
|
- A panic which could occur when the TUN/TAP interface reads an undersized/corrupted packet has been fixed
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
@ -231,7 +231,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## [0.3.8] - 2019-08-21
|
## [0.3.8] - 2019-08-21
|
||||||
### Changed
|
### Changed
|
||||||
- Mesh can now send multiple packets from the switch at once, which results in improved throughput with smaller packets or lower MTUs
|
- 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
|
- Performance has been slightly improved by not allocating cancellations where not necessary
|
||||||
- Crypto-key routing options have been renamed for clarity
|
- Crypto-key routing options have been renamed for clarity
|
||||||
- `IPv4Sources` is now named `IPv4LocalSubnets`
|
- `IPv4Sources` is now named `IPv4LocalSubnets`
|
||||||
|
@ -243,10 +243,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- 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
|
- 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
|
### Fixed
|
||||||
- A deadlock was fixed in the session code which could result in Mesh failing to pass traffic after some time
|
- A deadlock was fixed in the session code which could result in Yggdrasil failing to pass traffic after some time
|
||||||
|
|
||||||
### Security
|
### 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 Mesh could fail to reject
|
- 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.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
|
- Versions `0.3.5` and earlier are not affected
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
### Fixed
|
### Fixed
|
||||||
- A number of significant performance regressions introduced in version 0.3.6 have been fixed, resulting in better performance
|
- 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
|
- 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, Mesh now prefers the most active peering instead of the least active, helping to reduce packet reordering
|
- 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 `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 `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
|
- The admin socket now returns `box_pub_key` in string format again
|
||||||
|
@ -271,18 +271,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## [0.3.6] - 2019-08-03
|
## [0.3.6] - 2019-08-03
|
||||||
### Added
|
### Added
|
||||||
- Mesh now has a public API with interfaces such as `mesh.ConnDialer`, `mesh.ConnListener` and `mesh.Conn` for using Mesh as a transport directly within applications
|
- Yggdrasil now has a public API with interfaces such as `mesh.ConnDialer`, `mesh.ConnListener` and `mesh.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)
|
- 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)
|
- Support for logging to files or syslog (where supported)
|
||||||
- Platform defaults now include the ability to set sane defaults for multicast interfaces
|
- Platform defaults now include the ability to set sane defaults for multicast interfaces
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Following a massive refactoring exercise, Mesh's codebase has now been broken out into modules
|
- Following a massive refactoring exercise, Yggdrasil's codebase has now been broken out into modules
|
||||||
- Core node functionality in the `mesh` package with a public API
|
- Core node functionality in the `mesh` package with a public API
|
||||||
- This allows Mesh to be integrated directly into other applications and used as a transport
|
- 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 `mesh` package, making Mesh effectively protocol-agnostic
|
- IP-specific code has now been moved out of the core `mesh` package, making Yggdrasil effectively protocol-agnostic
|
||||||
- Multicast peer discovery functionality is now in the `multicast` package
|
- Multicast peer discovery functionality is now in the `multicast` package
|
||||||
- Admin socket functionality is now in the `admin` package and uses the Mesh public API
|
- 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
|
- 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`
|
- `PPROF` debug output is now sent to `stderr` instead of `stdout`
|
||||||
- Node IPv6 addresses on macOS are now configured as `secured`
|
- Node IPv6 addresses on macOS are now configured as `secured`
|
||||||
|
@ -290,7 +290,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Multicast discovery is no longer disabled if the nominated interfaces aren't available on the system yet, e.g. during boot
|
- 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 Mesh doesn't need to be restarted to use interfaces that have become available since startup
|
- 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
|
- Admin socket error cases are now handled better
|
||||||
- Various fixes in the TUN/TAP module, particularly surrounding Windows platform support
|
- 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
|
- Invalid keys will now cause the node to fail to start, rather than starting but silently not working as before
|
||||||
|
@ -313,9 +313,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- New multicast behaviour where each multicast interface is given its 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
|
- 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
|
- Support for adding and removing listeners and multicast interfaces when reloading configuration during runtime
|
||||||
- Mesh will now attempt to clean up UNIX admin sockets on startup if left behind by a previous crash
|
- Yggdrasil will now attempt to clean up UNIX admin sockets on startup if left behind by a previous crash
|
||||||
- Admin socket `getTunnelRouting` and `setTunnelRouting` calls for enabling and disabling crypto-key routing during runtime
|
- Admin socket `getTunnelRouting` and `setTunnelRouting` calls for enabling and disabling crypto-key routing during runtime
|
||||||
- On macOS, Mesh 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
|
- 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)
|
- 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)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -331,14 +331,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Handling of `getRoutes` etc in `meshctl` is now working
|
- Handling of `getRoutes` etc in `meshctl` is now working
|
||||||
- Local interface names are no longer leaked in multicast packets
|
- 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
|
- Link-local TCP connections, particularly those initiated because of multicast beacons, are now always correctly scoped for the target interface
|
||||||
- Mesh now correctly responds to multicast interfaces going up and down during runtime
|
- Yggdrasil now correctly responds to multicast interfaces going up and down during runtime
|
||||||
|
|
||||||
## [0.3.3] - 2019-02-18
|
## [0.3.3] - 2019-02-18
|
||||||
### Added
|
### Added
|
||||||
- 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)
|
- 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 Mesh as an iOS or Android framework if the appropriate tools (e.g. `gomobile`/`gobind` + SDKs) are available
|
- 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.
|
- 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 Mesh instances without having to disable multicast
|
- 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
|
- 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
|
- Flexible logging support, which allows for logging at different levels of verbosity
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## [0.3.0] - 2018-12-12
|
## [0.3.0] - 2018-12-12
|
||||||
### Added
|
### Added
|
||||||
- Crypto-key routing support for tunnelling both IPv4 and IPv6 over Mesh
|
- Crypto-key routing support for tunnelling both IPv4 and IPv6 over Yggdrasil
|
||||||
- Add advanced `SwitchOptions` in configuration file for tuning the switch
|
- Add advanced `SwitchOptions` in configuration file for tuning the switch
|
||||||
- Add `dhtPing` to the admin socket to aid in crawling the network
|
- Add `dhtPing` to the admin socket to aid in crawling the network
|
||||||
- New macOS .pkgs built automatically by CircleCI
|
- New macOS .pkgs built automatically by CircleCI
|
||||||
|
@ -409,7 +409,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Cleaned up some of the parameter naming in the admin socket
|
- Cleaned up some of the parameter naming in the admin socket
|
||||||
- Latency-based parent selection for the switch instead of uptime-based (should help to avoid high latency links somewhat)
|
- Latency-based parent selection for the switch instead of uptime-based (should help to avoid high latency links somewhat)
|
||||||
- Real peering endpoints now shown in the admin socket `getPeers` call to help identify peerings
|
- Real peering endpoints now shown in the admin socket `getPeers` call to help identify peerings
|
||||||
- Reuse the multicast port on supported platforms so that multiple Mesh processes can run
|
- Reuse the multicast port on supported platforms so that multiple Yggdrasil processes can run
|
||||||
- `meshctl` now has more useful help text (with `-help` or when no arguments passed)
|
- `meshctl` now has more useful help text (with `-help` or when no arguments passed)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
32
README.md
32
README.md
|
@ -1,22 +1,19 @@
|
||||||
# RiV-mesh
|
# Yggdrasil
|
||||||
|
|
||||||
[](https://circleci.com/gh/RiV-chain/RiV-mesh)
|
)](https://circleci.com/gh/RiV-chain/RiV-mesh)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
RiV-mesh is an implementation of a fully end-to-end encrypted IPv6
|
Yggdrasil is an early-stage implementation of a fully end-to-end encrypted IPv6
|
||||||
network, created in the scope to produce the Transport Layer for RiV Chain Blockchain,
|
network. It is lightweight, self-arranging, supported on multiple platforms and
|
||||||
also to facilitate secure conectivity between a wide spectrum of endpoint devices like IoT devices,
|
allows pretty much any IPv6-capable application to communicate securely with
|
||||||
desktop computers or even routers.
|
other Yggdrasil nodes. Yggdrasil does not require you to have IPv6 Internet
|
||||||
It is lightweight, self-arranging, supported on multiple
|
connectivity - it also works over IPv4.
|
||||||
platforms and allows pretty much any IPv6-capable application
|
|
||||||
to communicate securely with other RiV-mesh nodes.
|
|
||||||
RiV-mesh does not require you to have IPv6 Internet connectivity - it also works over IPv4.
|
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
|
|
||||||
RiV-mesh works on a number of platforms, including Linux, macOS, Ubiquiti
|
Yggdrasil works on a number of platforms, including Linux, macOS, Ubiquiti
|
||||||
EdgeRouter, VyOS, Windows, FreeBSD, OpenBSD and OpenWrt.
|
EdgeRouter, VyOS, Windows, FreeBSD, OpenBSD and OpenWrt.
|
||||||
|
|
||||||
Please see our [Installation](https://RiV-chain.github.io/installation.html)
|
Please see our [Installation](https://RiV-chain.github.io/installation.html)
|
||||||
|
@ -57,7 +54,7 @@ programmatically):
|
||||||
You will need to edit the `mesh.conf` file to add or remove peers, modify
|
You will need to edit the `mesh.conf` file to add or remove peers, modify
|
||||||
other configuration such as listen addresses or multicast addresses, etc.
|
other configuration such as listen addresses or multicast addresses, etc.
|
||||||
|
|
||||||
### Run RiV-mesh
|
### Run Yggdrasil
|
||||||
|
|
||||||
To run with the generated static configuration:
|
To run with the generated static configuration:
|
||||||
```
|
```
|
||||||
|
@ -71,23 +68,24 @@ at each startup, instead of using a static configuration file):
|
||||||
./mesh -autoconf
|
./mesh -autoconf
|
||||||
```
|
```
|
||||||
|
|
||||||
You will likely need to run RiV-mesh as a privileged user or under `sudo`,
|
You will likely need to run Yggdrasil as a privileged user or under `sudo`,
|
||||||
unless you have permission to create TUN/TAP adapters. On Linux this can be done
|
unless you have permission to create TUN/TAP adapters. On Linux this can be done
|
||||||
by giving the RiV-mesh binary the `CAP_NET_ADMIN` capability.
|
by giving the Yggdrasil binary the `CAP_NET_ADMIN` capability.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Documentation is available [on our website](https://RiV-chain.github.io).
|
Documentation is available [on our website](https://RiV-chain.github.io).
|
||||||
|
|
||||||
- [Installing RiV-mesh](https://RiV-chain.github.io/installation.html)
|
- [Installing Yggdrasil](https://RiV-chain.github.io/installation.html)
|
||||||
- [Configuring RiV-mesh](https://RiV-chain.github.io/configuration.html)
|
- [Configuring Yggdrasil](https://RiV-chain.github.io/configuration.html)
|
||||||
- [Frequently asked questions](https://RiV-chain.github.io/faq.html)
|
- [Frequently asked questions](https://RiV-chain.github.io/faq.html)
|
||||||
- [Version changelog](CHANGELOG.md)
|
- [Version changelog](CHANGELOG.md)
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
Feel free to join us on our [Telegram
|
Feel free to join us on our [Matrix
|
||||||
channel](https://t.me/rivchain).
|
channel](https://matrix.to/#/#mesh:matrix.org) at `#mesh:matrix.org`
|
||||||
|
or in the `#mesh` IRC channel on [libera.chat](https://libera.chat).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
2
build
2
build
|
@ -33,7 +33,7 @@ fi
|
||||||
if [ $IOS ]; then
|
if [ $IOS ]; then
|
||||||
echo "Building framework for iOS"
|
echo "Building framework for iOS"
|
||||||
go get golang.org/x/mobile/bind
|
go get golang.org/x/mobile/bind
|
||||||
gomobile bind -target ios -tags mobile -o Mesh.framework -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
|
gomobile bind -target ios -tags mobile -o Yggdrasil.framework -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
|
||||||
github.com/RiV-chain/RiV-mesh-extras/src/mobile \
|
github.com/RiV-chain/RiV-mesh-extras/src/mobile \
|
||||||
github.com/RiV-chain/RiV-mesh/src/config
|
github.com/RiV-chain/RiV-mesh/src/config
|
||||||
elif [ $ANDROID ]; then
|
elif [ $ANDROID ]; then
|
||||||
|
|
|
@ -224,7 +224,7 @@ func getArgs() yggArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The main function is responsible for configuring and starting Mesh.
|
// The main function is responsible for configuring and starting Yggdrasil.
|
||||||
func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
// Create a new logger that logs output to stdout.
|
// Create a new logger that logs output to stdout.
|
||||||
|
@ -325,11 +325,11 @@ func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the Mesh node itself. The node{} type includes a Core, so we
|
// Setup the Yggdrasil node itself. The node{} type includes a Core, so we
|
||||||
// don't need to create this manually.
|
// don't need to create this manually.
|
||||||
n := node{config: cfg}
|
n := node{config: cfg}
|
||||||
// Now start Mesh - this starts the DHT, router, switch and other core
|
// Now start Yggdrasil - this starts the DHT, router, switch and other core
|
||||||
// components needed for Mesh to operate
|
// components needed for Yggdrasil to operate
|
||||||
if err = n.core.Start(cfg, logger); err != nil {
|
if err = n.core.Start(cfg, logger); err != nil {
|
||||||
logger.Errorln("An error occurred during startup")
|
logger.Errorln("An error occurred during startup")
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -43,7 +43,7 @@ func run() int {
|
||||||
if cmdLineEnv.ver {
|
if cmdLineEnv.ver {
|
||||||
fmt.Println("Build name:", version.BuildName())
|
fmt.Println("Build name:", version.BuildName())
|
||||||
fmt.Println("Build version:", version.BuildVersion())
|
fmt.Println("Build version:", version.BuildVersion())
|
||||||
fmt.Println("To get the version number of the running Mesh node, run", os.Args[0], "getSelf")
|
fmt.Println("To get the version number of the running Yggdrasil node, run", os.Args[0], "getSelf")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,11 @@ Architecture: $PKGARCH
|
||||||
Replaces: $PKGREPLACES
|
Replaces: $PKGREPLACES
|
||||||
Conflicts: $PKGREPLACES
|
Conflicts: $PKGREPLACES
|
||||||
Maintainer: Neil Alexander <neilalexander@users.noreply.github.com>
|
Maintainer: Neil Alexander <neilalexander@users.noreply.github.com>
|
||||||
Description: Mesh Network
|
Description: Yggdrasil Network
|
||||||
Mesh is an early-stage implementation of a fully end-to-end encrypted IPv6
|
Yggdrasil is an early-stage implementation of a fully end-to-end encrypted IPv6
|
||||||
network. It is lightweight, self-arranging, supported on multiple platforms and
|
network. It is lightweight, self-arranging, supported on multiple platforms and
|
||||||
allows pretty much any IPv6-capable application to communicate securely with
|
allows pretty much any IPv6-capable application to communicate securely with
|
||||||
other Mesh nodes.
|
other Yggdrasil nodes.
|
||||||
EOF
|
EOF
|
||||||
cat > /tmp/$PKGNAME/debian/copyright << EOF
|
cat > /tmp/$PKGNAME/debian/copyright << EOF
|
||||||
Please see https://github.com/RiV-chain/RiV-mesh/
|
Please see https://github.com/RiV-chain/RiV-mesh/
|
||||||
|
@ -93,7 +93,7 @@ then
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Generating initial configuration file /etc/mesh.conf"
|
echo "Generating initial configuration file /etc/mesh.conf"
|
||||||
echo "Please familiarise yourself with this file before starting Mesh"
|
echo "Please familiarise yourself with this file before starting Yggdrasil"
|
||||||
sh -c 'umask 0027 && /usr/bin/mesh -genconf > /etc/mesh.conf'
|
sh -c 'umask 0027 && /usr/bin/mesh -genconf > /etc/mesh.conf'
|
||||||
chgrp mesh /etc/mesh.conf
|
chgrp mesh /etc/mesh.conf
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -45,19 +45,19 @@ cat > pkgbuild/scripts/postinstall << EOF
|
||||||
# Normalise the config if it exists, generate it if it doesn't
|
# Normalise the config if it exists, generate it if it doesn't
|
||||||
if [ -f /etc/mesh.conf ];
|
if [ -f /etc/mesh.conf ];
|
||||||
then
|
then
|
||||||
mkdir -p /Library/Preferences/Mesh
|
mkdir -p /Library/Preferences/Yggdrasil
|
||||||
echo "Backing up configuration file to /Library/Preferences/Mesh/mesh.conf.`date +%Y%m%d`"
|
echo "Backing up configuration file to /Library/Preferences/Yggdrasil/mesh.conf.`date +%Y%m%d`"
|
||||||
cp /etc/mesh.conf /Library/Preferences/Mesh/mesh.conf.`date +%Y%m%d`
|
cp /etc/mesh.conf /Library/Preferences/Yggdrasil/mesh.conf.`date +%Y%m%d`
|
||||||
echo "Normalising /etc/mesh.conf"
|
echo "Normalising /etc/mesh.conf"
|
||||||
/usr/local/bin/mesh -useconffile /Library/Preferences/Mesh/mesh.conf.`date +%Y%m%d` -normaliseconf > /etc/mesh.conf
|
/usr/local/bin/mesh -useconffile /Library/Preferences/Yggdrasil/mesh.conf.`date +%Y%m%d` -normaliseconf > /etc/mesh.conf
|
||||||
else
|
else
|
||||||
/usr/local/bin/mesh -genconf > /etc/mesh.conf
|
/usr/local/bin/mesh -genconf > /etc/mesh.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Unload existing Mesh launchd service, if possible
|
# Unload existing Yggdrasil launchd service, if possible
|
||||||
test -f /Library/LaunchDaemons/mesh.plist && (launchctl unload /Library/LaunchDaemons/mesh.plist || true)
|
test -f /Library/LaunchDaemons/mesh.plist && (launchctl unload /Library/LaunchDaemons/mesh.plist || true)
|
||||||
|
|
||||||
# Load Mesh launchd service and start Mesh
|
# Load Yggdrasil launchd service and start Yggdrasil
|
||||||
launchctl load /Library/LaunchDaemons/mesh.plist
|
launchctl load /Library/LaunchDaemons/mesh.plist
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ EOF
|
||||||
cat > pkgbuild/flat/Distribution << EOF
|
cat > pkgbuild/flat/Distribution << EOF
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">
|
<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">
|
||||||
<title>Mesh (${PKGNAME}-${PKGVERSION})</title>
|
<title>Yggdrasil (${PKGNAME}-${PKGVERSION})</title>
|
||||||
<options customize="never" allow-external-scripts="no"/>
|
<options customize="never" allow-external-scripts="no"/>
|
||||||
<domains enable_anywhere="true"/>
|
<domains enable_anywhere="true"/>
|
||||||
<installation-check script="pm_install_check();"/>
|
<installation-check script="pm_install_check();"/>
|
||||||
|
@ -101,7 +101,7 @@ cat > pkgbuild/flat/Distribution << EOF
|
||||||
function pm_install_check() {
|
function pm_install_check() {
|
||||||
if(!(system.compareVersions(system.version.ProductVersion,'10.10') >= 0)) {
|
if(!(system.compareVersions(system.version.ProductVersion,'10.10') >= 0)) {
|
||||||
my.result.title = 'Failure';
|
my.result.title = 'Failure';
|
||||||
my.result.message = 'You need at least Mac OS X 10.10 to install Mesh.';
|
my.result.message = 'You need at least Mac OS X 10.10 to install Yggdrasil.';
|
||||||
my.result.type = 'Fatal';
|
my.result.type = 'Fatal';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# This script generates an MSI file for Mesh for a given architecture. It
|
# This script generates an MSI file for Yggdrasil for a given architecture. It
|
||||||
# needs to run on Windows within MSYS2 and Go 1.13 or later must be installed on
|
# needs to run on Windows within MSYS2 and Go 1.13 or later must be installed on
|
||||||
# the system and within the PATH. This is ran currently by Appveyor (see
|
# the system and within the PATH. This is ran currently by Appveyor (see
|
||||||
# appveyor.yml in the repository root) for both x86 and x64.
|
# appveyor.yml in the repository root) for both x86 and x64.
|
||||||
|
@ -47,7 +47,7 @@ then
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build Mesh!
|
# Build Yggdrasil!
|
||||||
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./build
|
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./build
|
||||||
[ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=0 ./build
|
[ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=0 ./build
|
||||||
[ "${PKGARCH}" == "arm" ] && GOOS=windows GOARCH=arm CGO_ENABLED=0 ./build
|
[ "${PKGARCH}" == "arm" ] && GOOS=windows GOARCH=arm CGO_ENABLED=0 ./build
|
||||||
|
@ -55,12 +55,12 @@ fi
|
||||||
|
|
||||||
# Create the postinstall script
|
# Create the postinstall script
|
||||||
cat > updateconfig.bat << EOF
|
cat > updateconfig.bat << EOF
|
||||||
if not exist %ALLUSERSPROFILE%\\Mesh (
|
if not exist %ALLUSERSPROFILE%\\Yggdrasil (
|
||||||
mkdir %ALLUSERSPROFILE%\\Mesh
|
mkdir %ALLUSERSPROFILE%\\Yggdrasil
|
||||||
)
|
)
|
||||||
if not exist %ALLUSERSPROFILE%\\Mesh\\mesh.conf (
|
if not exist %ALLUSERSPROFILE%\\Yggdrasil\\mesh.conf (
|
||||||
if exist mesh.exe (
|
if exist mesh.exe (
|
||||||
mesh.exe -genconf > %ALLUSERSPROFILE%\\Mesh\\mesh.conf
|
mesh.exe -genconf > %ALLUSERSPROFILE%\\Yggdrasil\\mesh.conf
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
EOF
|
EOF
|
||||||
|
@ -93,9 +93,9 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $PKGNAME != "master" ]; then
|
if [ $PKGNAME != "master" ]; then
|
||||||
PKGDISPLAYNAME="Mesh Network (${PKGNAME} branch)"
|
PKGDISPLAYNAME="Yggdrasil Network (${PKGNAME} branch)"
|
||||||
else
|
else
|
||||||
PKGDISPLAYNAME="Mesh Network"
|
PKGDISPLAYNAME="Yggdrasil Network"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate the wix.xml file
|
# Generate the wix.xml file
|
||||||
|
@ -114,8 +114,8 @@ cat > wix.xml << EOF
|
||||||
<Package
|
<Package
|
||||||
Id="*"
|
Id="*"
|
||||||
Keywords="Installer"
|
Keywords="Installer"
|
||||||
Description="Mesh Network Installer"
|
Description="Yggdrasil Network Installer"
|
||||||
Comments="Mesh Network standalone router for Windows."
|
Comments="Yggdrasil Network standalone router for Windows."
|
||||||
Manufacturer="github.com/RiV-chain"
|
Manufacturer="github.com/RiV-chain"
|
||||||
InstallerVersion="200"
|
InstallerVersion="200"
|
||||||
InstallScope="perMachine"
|
InstallScope="perMachine"
|
||||||
|
@ -134,11 +134,11 @@ cat > wix.xml << EOF
|
||||||
|
|
||||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
<Directory Id="${PKGINSTFOLDER}" Name="PFiles">
|
<Directory Id="${PKGINSTFOLDER}" Name="PFiles">
|
||||||
<Directory Id="MeshInstallFolder" Name="Mesh">
|
<Directory Id="YggdrasilInstallFolder" Name="Yggdrasil">
|
||||||
|
|
||||||
<Component Id="MainExecutable" Guid="c2119231-2aa3-4962-867a-9759c87beb24">
|
<Component Id="MainExecutable" Guid="c2119231-2aa3-4962-867a-9759c87beb24">
|
||||||
<File
|
<File
|
||||||
Id="Mesh"
|
Id="Yggdrasil"
|
||||||
Name="mesh.exe"
|
Name="mesh.exe"
|
||||||
DiskId="1"
|
DiskId="1"
|
||||||
Source="mesh.exe"
|
Source="mesh.exe"
|
||||||
|
@ -153,14 +153,14 @@ cat > wix.xml << EOF
|
||||||
<ServiceInstall
|
<ServiceInstall
|
||||||
Id="ServiceInstaller"
|
Id="ServiceInstaller"
|
||||||
Account="LocalSystem"
|
Account="LocalSystem"
|
||||||
Description="Mesh Network router process"
|
Description="Yggdrasil Network router process"
|
||||||
DisplayName="Mesh Service"
|
DisplayName="Yggdrasil Service"
|
||||||
ErrorControl="normal"
|
ErrorControl="normal"
|
||||||
LoadOrderGroup="NetworkProvider"
|
LoadOrderGroup="NetworkProvider"
|
||||||
Name="Mesh"
|
Name="Yggdrasil"
|
||||||
Start="auto"
|
Start="auto"
|
||||||
Type="ownProcess"
|
Type="ownProcess"
|
||||||
Arguments='-useconffile "%ALLUSERSPROFILE%\\Mesh\\mesh.conf" -logto "%ALLUSERSPROFILE%\\Mesh\\mesh.log"'
|
Arguments='-useconffile "%ALLUSERSPROFILE%\\Yggdrasil\\mesh.conf" -logto "%ALLUSERSPROFILE%\\Yggdrasil\\mesh.log"'
|
||||||
Vital="yes" />
|
Vital="yes" />
|
||||||
|
|
||||||
<ServiceControl
|
<ServiceControl
|
||||||
|
@ -173,7 +173,7 @@ cat > wix.xml << EOF
|
||||||
|
|
||||||
<Component Id="CtrlExecutable" Guid="a916b730-974d-42a1-b687-d9d504cbb86a">
|
<Component Id="CtrlExecutable" Guid="a916b730-974d-42a1-b687-d9d504cbb86a">
|
||||||
<File
|
<File
|
||||||
Id="Meshctl"
|
Id="Yggdrasilctl"
|
||||||
Name="meshctl.exe"
|
Name="meshctl.exe"
|
||||||
DiskId="1"
|
DiskId="1"
|
||||||
Source="meshctl.exe"
|
Source="meshctl.exe"
|
||||||
|
@ -192,7 +192,7 @@ cat > wix.xml << EOF
|
||||||
</Directory>
|
</Directory>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
<Feature Id="MeshFeature" Title="Mesh" Level="1">
|
<Feature Id="YggdrasilFeature" Title="Yggdrasil" Level="1">
|
||||||
<ComponentRef Id="MainExecutable" />
|
<ComponentRef Id="MainExecutable" />
|
||||||
<ComponentRef Id="CtrlExecutable" />
|
<ComponentRef Id="CtrlExecutable" />
|
||||||
<ComponentRef Id="ConfigScript" />
|
<ComponentRef Id="ConfigScript" />
|
||||||
|
@ -200,7 +200,7 @@ cat > wix.xml << EOF
|
||||||
|
|
||||||
<CustomAction
|
<CustomAction
|
||||||
Id="UpdateGenerateConfig"
|
Id="UpdateGenerateConfig"
|
||||||
Directory="MeshInstallFolder"
|
Directory="YggdrasilInstallFolder"
|
||||||
ExeCommand="cmd.exe /c updateconfig.bat"
|
ExeCommand="cmd.exe /c updateconfig.bat"
|
||||||
Execute="deferred"
|
Execute="deferred"
|
||||||
Return="check"
|
Return="check"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
The config package contains structures related to the configuration of an
|
The config package contains structures related to the configuration of an
|
||||||
Mesh node.
|
Yggdrasil node.
|
||||||
|
|
||||||
The configuration contains, amongst other things, encryption keys which are used
|
The configuration contains, amongst other things, encryption keys which are used
|
||||||
to derive a node's identity, information about peerings and node information
|
to derive a node's identity, information about peerings and node information
|
||||||
|
@ -11,7 +11,7 @@ In order for a node to maintain the same identity across restarts, you should
|
||||||
persist the configuration onto the filesystem or into some configuration storage
|
persist the configuration onto the filesystem or into some configuration storage
|
||||||
so that the encryption keys (and therefore the node ID) do not change.
|
so that the encryption keys (and therefore the node ID) do not change.
|
||||||
|
|
||||||
Note that Mesh will automatically populate sane defaults for any
|
Note that Yggdrasil will automatically populate sane defaults for any
|
||||||
configuration option that is not provided.
|
configuration option that is not provided.
|
||||||
*/
|
*/
|
||||||
package config
|
package config
|
||||||
|
@ -23,8 +23,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeConfig is the main configuration structure, containing configuration
|
// NodeConfig is the main configuration structure, containing configuration
|
||||||
// options that are necessary for an Mesh node to run. You will need to
|
// options that are necessary for an Yggdrasil node to run. You will need to
|
||||||
// supply one of these structs to the Mesh core when starting a node.
|
// supply one of these structs to the Yggdrasil core when starting a node.
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
sync.RWMutex `json:"-"`
|
sync.RWMutex `json:"-"`
|
||||||
Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tls://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."`
|
Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tls://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."`
|
||||||
|
@ -37,21 +37,10 @@ type NodeConfig struct {
|
||||||
PrivateKey string `comment:"Your private key. DO NOT share this with anyone!"`
|
PrivateKey string `comment:"Your private key. DO NOT share this with anyone!"`
|
||||||
IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."`
|
IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."`
|
||||||
IfMTU uint64 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
|
IfMTU uint64 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
|
||||||
TunnelRouting TunnelRouting `comment:"Allow tunneling non-Mesh traffic over Mesh. This effectively\nallows you to use Mesh to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."`
|
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
|
||||||
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Mesh version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
|
|
||||||
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
|
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TunnelRouting contains the crypto-key routing tables for tunneling regular
|
|
||||||
// IPv4 or IPv6 subnets across the Mesh network.
|
|
||||||
type TunnelRouting struct {
|
|
||||||
Enable bool `comment:"Enable or disable tunnel routing."`
|
|
||||||
IPv6RemoteSubnets map[string]string `comment:"IPv6 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"aaaa:bbbb:cccc::/e\": \"boxpubkey\", ... }"`
|
|
||||||
IPv6LocalSubnets []string `comment:"IPv6 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges (or the Mesh node's IPv6 address/subnet)\nwill be tunnelled."`
|
|
||||||
IPv4RemoteSubnets map[string]string `comment:"IPv4 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"a.b.c.d/e\": \"boxpubkey\", ... }"`
|
|
||||||
IPv4LocalSubnets []string `comment:"IPv4 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges will be tunnelled."`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MulticastInterfaceConfig struct {
|
type MulticastInterfaceConfig struct {
|
||||||
Regex string
|
Regex string
|
||||||
Beacon bool
|
Beacon bool
|
||||||
|
|
|
@ -122,7 +122,7 @@ func (c *Core) Listen(u *url.URL, sintf string) (*TcpListener, error) {
|
||||||
return c.links.tcp.listenURL(u, sintf)
|
return c.links.tcp.listenURL(u, sintf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address gets the IPv6 address of the Mesh node. This is always a /128
|
// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
|
||||||
// address. The IPv6 address is only relevant when the node is operating as an
|
// address. The IPv6 address is only relevant when the node is operating as an
|
||||||
// IP router and often is meaningless when embedded into an application, unless
|
// IP router and often is meaningless when embedded into an application, unless
|
||||||
// that application also implements either VPN functionality or deals with IP
|
// that application also implements either VPN functionality or deals with IP
|
||||||
|
@ -132,7 +132,7 @@ func (c *Core) Address() net.IP {
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subnet gets the routed IPv6 subnet of the Mesh node. This is always a
|
// Subnet gets the routed IPv6 subnet of the Yggdrasil node. This is always a
|
||||||
// /64 subnet. The IPv6 subnet is only relevant when the node is operating as an
|
// /64 subnet. The IPv6 subnet is only relevant when the node is operating as an
|
||||||
// IP router and often is meaningless when embedded into an application, unless
|
// IP router and often is meaningless when embedded into an application, unless
|
||||||
// that application also implements either VPN functionality or deals with IP
|
// that application also implements either VPN functionality or deals with IP
|
||||||
|
@ -143,7 +143,7 @@ func (c *Core) Subnet() net.IPNet {
|
||||||
return net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
return net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogger sets the output logger of the Mesh node after startup. This
|
// SetLogger sets the output logger of the Yggdrasil node after startup. This
|
||||||
// may be useful if you want to redirect the output later. Note that this
|
// may be useful if you want to redirect the output later. Note that this
|
||||||
// expects a Logger from the github.com/gologme/log package and not from Go's
|
// expects a Logger from the github.com/gologme/log package and not from Go's
|
||||||
// built-in log package.
|
// built-in log package.
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
"github.com/RiV-chain/RiV-mesh/src/version"
|
"github.com/RiV-chain/RiV-mesh/src/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Core object represents the Mesh node. You should create a Core
|
// The Core object represents the Yggdrasil node. You should create a Core
|
||||||
// object for each Mesh node you plan to run.
|
// object for each Yggdrasil node you plan to run.
|
||||||
type Core struct {
|
type Core struct {
|
||||||
// This is the main data structure that holds everything else for a node
|
// This is the main data structure that holds everything else for a node
|
||||||
// We're going to keep our own copy of the provided config - that way we can
|
// We're going to keep our own copy of the provided config - that way we can
|
||||||
|
@ -116,7 +116,7 @@ func (c *Core) _addPeerLoop() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts up Mesh using the provided config.NodeConfig, and outputs
|
// Start starts up Yggdrasil using the provided config.NodeConfig, and outputs
|
||||||
// debug logging through the provided log.Logger. The started stack will include
|
// debug logging through the provided log.Logger. The started stack will include
|
||||||
// TCP and UDP sockets, a multicast discovery socket, an admin socket, router,
|
// TCP and UDP sockets, a multicast discovery socket, an admin socket, router,
|
||||||
// switch and DHT node. A config.NodeState is returned which contains both the
|
// switch and DHT node. A config.NodeState is returned which contains both the
|
||||||
|
@ -159,7 +159,7 @@ func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop shuts down the Mesh node.
|
// Stop shuts down the Yggdrasil node.
|
||||||
func (c *Core) Stop() {
|
func (c *Core) Stop() {
|
||||||
phony.Block(c, func() {
|
phony.Block(c, func() {
|
||||||
c.log.Infoln("Stopping...")
|
c.log.Infoln("Stopping...")
|
||||||
|
|
|
@ -10,7 +10,7 @@ func GetDefaults() platformDefaultParameters {
|
||||||
DefaultAdminListen: "tcp://localhost:9001",
|
DefaultAdminListen: "tcp://localhost:9001",
|
||||||
|
|
||||||
// Configuration (used for meshctl)
|
// Configuration (used for meshctl)
|
||||||
DefaultConfigFile: "C:\\Program Files\\Mesh\\mesh.conf",
|
DefaultConfigFile: "C:\\Program Files\\Yggdrasil\\mesh.conf",
|
||||||
|
|
||||||
// Multicast interfaces
|
// Multicast interfaces
|
||||||
DefaultMulticastInterfaces: []MulticastInterfaceConfig{
|
DefaultMulticastInterfaces: []MulticastInterfaceConfig{
|
||||||
|
@ -20,6 +20,6 @@ func GetDefaults() platformDefaultParameters {
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU: 65535,
|
MaximumIfMTU: 65535,
|
||||||
DefaultIfMTU: 65535,
|
DefaultIfMTU: 65535,
|
||||||
DefaultIfName: "Mesh",
|
DefaultIfName: "Yggdrasil",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Multicast represents the multicast advertisement and discovery mechanism used
|
// Multicast represents the multicast advertisement and discovery mechanism used
|
||||||
// by Mesh to find peers on the same subnet. When a beacon is received on a
|
// by Yggdrasil to find peers on the same subnet. When a beacon is received on a
|
||||||
// configured multicast interface, Mesh will attempt to peer with that node
|
// configured multicast interface, Yggdrasil will attempt to peer with that node
|
||||||
// automatically.
|
// automatically.
|
||||||
type Multicast struct {
|
type Multicast struct {
|
||||||
phony.Inbox
|
phony.Inbox
|
||||||
|
|
|
@ -1,430 +0,0 @@
|
||||||
package tuntap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/ed25519"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This module implements crypto-key routing, similar to Wireguard, where we
|
|
||||||
// allow traffic for non-Mesh ranges to be routed over Mesh.
|
|
||||||
|
|
||||||
type cryptokey struct {
|
|
||||||
tun *TunAdapter
|
|
||||||
enabled atomic.Value // bool
|
|
||||||
ipv4remotes []cryptokey_route
|
|
||||||
ipv6remotes []cryptokey_route
|
|
||||||
ipv4cache map[address.Address]cryptokey_route
|
|
||||||
ipv6cache map[address.Address]cryptokey_route
|
|
||||||
ipv4locals []net.IPNet
|
|
||||||
ipv6locals []net.IPNet
|
|
||||||
mutexremotes sync.RWMutex
|
|
||||||
mutexcaches sync.RWMutex
|
|
||||||
mutexlocals sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type cryptokey_route struct {
|
|
||||||
subnet net.IPNet
|
|
||||||
destination ed25519.PublicKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise crypto-key routing. This must be done before any other CKR calls.
|
|
||||||
func (c *cryptokey) init(tun *TunAdapter) {
|
|
||||||
c.tun = tun
|
|
||||||
c.configure()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the CKR routes. This should only ever be ran by the TUN/TAP actor.
|
|
||||||
func (c *cryptokey) configure() {
|
|
||||||
//current := c.tun.config.GetCurrent()
|
|
||||||
|
|
||||||
// Set enabled/disabled state
|
|
||||||
c.setEnabled(c.tun.config.TunnelRouting.Enable)
|
|
||||||
|
|
||||||
// Clear out existing routes
|
|
||||||
c.mutexremotes.Lock()
|
|
||||||
c.ipv6remotes = make([]cryptokey_route, 0)
|
|
||||||
c.ipv4remotes = make([]cryptokey_route, 0)
|
|
||||||
c.mutexremotes.Unlock()
|
|
||||||
|
|
||||||
// Add IPv6 routes
|
|
||||||
for ipv6, pubkey := range c.tun.config.TunnelRouting.IPv6RemoteSubnets {
|
|
||||||
if err := c.addRemoteSubnet(ipv6, pubkey); err != nil {
|
|
||||||
c.tun.log.Errorln("Error adding CKR IPv6 remote subnet:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add IPv4 routes
|
|
||||||
for ipv4, pubkey := range c.tun.config.TunnelRouting.IPv4RemoteSubnets {
|
|
||||||
if err := c.addRemoteSubnet(ipv4, pubkey); err != nil {
|
|
||||||
c.tun.log.Errorln("Error adding CKR IPv4 remote subnet:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear out existing sources
|
|
||||||
c.mutexlocals.Lock()
|
|
||||||
c.ipv6locals = make([]net.IPNet, 0)
|
|
||||||
c.ipv4locals = make([]net.IPNet, 0)
|
|
||||||
c.mutexlocals.Unlock()
|
|
||||||
|
|
||||||
// Add IPv6 sources
|
|
||||||
c.ipv6locals = make([]net.IPNet, 0)
|
|
||||||
for _, source := range c.tun.config.TunnelRouting.IPv6LocalSubnets {
|
|
||||||
if err := c.addLocalSubnet(source); err != nil {
|
|
||||||
c.tun.log.Errorln("Error adding CKR IPv6 local subnet:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add IPv4 sources
|
|
||||||
c.ipv4locals = make([]net.IPNet, 0)
|
|
||||||
for _, source := range c.tun.config.TunnelRouting.IPv4LocalSubnets {
|
|
||||||
if err := c.addLocalSubnet(source); err != nil {
|
|
||||||
c.tun.log.Errorln("Error adding CKR IPv4 local subnet:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wipe the caches
|
|
||||||
c.mutexcaches.Lock()
|
|
||||||
c.ipv4cache = make(map[address.Address]cryptokey_route, 0)
|
|
||||||
c.ipv6cache = make(map[address.Address]cryptokey_route, 0)
|
|
||||||
c.mutexcaches.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable or disable crypto-key routing.
|
|
||||||
func (c *cryptokey) setEnabled(enabled bool) {
|
|
||||||
c.enabled.Store(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if crypto-key routing is enabled.
|
|
||||||
func (c *cryptokey) isEnabled() bool {
|
|
||||||
enabled, ok := c.enabled.Load().(bool)
|
|
||||||
return ok && enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the given address (with the address length specified in bytes)
|
|
||||||
// matches either the current node's address, the node's routed subnet or the
|
|
||||||
// list of subnets specified in ipv4locals/ipv6locals.
|
|
||||||
func (c *cryptokey) isValidLocalAddress(addr address.Address, addrlen int) bool {
|
|
||||||
c.mutexlocals.RLock()
|
|
||||||
defer c.mutexlocals.RUnlock()
|
|
||||||
// Does it match a configured CKR source?
|
|
||||||
if c.isEnabled() {
|
|
||||||
ip := net.IP(addr[:addrlen])
|
|
||||||
// Build our references to the routing sources
|
|
||||||
var routingsources *[]net.IPNet
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if addrlen == net.IPv6len {
|
|
||||||
routingsources = &c.ipv6locals
|
|
||||||
} else if addrlen == net.IPv4len {
|
|
||||||
routingsources = &c.ipv4locals
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, subnet := range *routingsources {
|
|
||||||
if subnet.Contains(ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doesn't match any of the above
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a source subnet, which allows traffic with these source addresses to
|
|
||||||
// be tunnelled using crypto-key routing.
|
|
||||||
func (c *cryptokey) addLocalSubnet(cidr string) error {
|
|
||||||
c.mutexlocals.Lock()
|
|
||||||
defer c.mutexlocals.Unlock()
|
|
||||||
|
|
||||||
// Is the CIDR we've been given valid?
|
|
||||||
_, ipnet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the prefix length and size
|
|
||||||
_, prefixsize := ipnet.Mask.Size()
|
|
||||||
|
|
||||||
// Build our references to the routing sources
|
|
||||||
var routingsources *[]net.IPNet
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if prefixsize == net.IPv6len*8 {
|
|
||||||
routingsources = &c.ipv6locals
|
|
||||||
} else if prefixsize == net.IPv4len*8 {
|
|
||||||
routingsources = &c.ipv4locals
|
|
||||||
} else {
|
|
||||||
return errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we already have this CIDR
|
|
||||||
for _, subnet := range *routingsources {
|
|
||||||
if subnet.String() == ipnet.String() {
|
|
||||||
return errors.New("local subnet already configured")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the source subnet
|
|
||||||
*routingsources = append(*routingsources, *ipnet)
|
|
||||||
c.tun.log.Infoln("Added CKR local subnet", cidr)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a destination route for the given CIDR to be tunnelled to the node
|
|
||||||
// with the given BoxPubKey.
|
|
||||||
func (c *cryptokey) addRemoteSubnet(cidr string, dest string) error {
|
|
||||||
c.mutexremotes.Lock()
|
|
||||||
c.mutexcaches.Lock()
|
|
||||||
defer c.mutexremotes.Unlock()
|
|
||||||
defer c.mutexcaches.Unlock()
|
|
||||||
|
|
||||||
// Is the CIDR we've been given valid?
|
|
||||||
ipaddr, ipnet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the prefix length and size
|
|
||||||
_, prefixsize := ipnet.Mask.Size()
|
|
||||||
|
|
||||||
// Build our references to the routing table and cache
|
|
||||||
var routingtable *[]cryptokey_route
|
|
||||||
var routingcache *map[address.Address]cryptokey_route
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if prefixsize == net.IPv6len*8 {
|
|
||||||
routingtable = &c.ipv6remotes
|
|
||||||
routingcache = &c.ipv6cache
|
|
||||||
} else if prefixsize == net.IPv4len*8 {
|
|
||||||
routingtable = &c.ipv4remotes
|
|
||||||
routingcache = &c.ipv4cache
|
|
||||||
} else {
|
|
||||||
return errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the route an Mesh destination?
|
|
||||||
var addr address.Address
|
|
||||||
var snet address.Subnet
|
|
||||||
copy(addr[:], ipaddr)
|
|
||||||
copy(snet[:], ipnet.IP)
|
|
||||||
if addr.IsValid() || snet.IsValid() {
|
|
||||||
return errors.New("can't specify Mesh destination as crypto-key route")
|
|
||||||
}
|
|
||||||
// Do we already have a route for this subnet?
|
|
||||||
for _, route := range *routingtable {
|
|
||||||
if route.subnet.String() == ipnet.String() {
|
|
||||||
return fmt.Errorf("remote subnet already exists for %s", cidr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Decode the public key
|
|
||||||
if bpk, err := hex.DecodeString(dest); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(bpk) != ed25519.PublicKeySize {
|
|
||||||
return fmt.Errorf("incorrect key length for %s", dest)
|
|
||||||
} else {
|
|
||||||
// Add the new crypto-key route
|
|
||||||
var key ed25519.PublicKey
|
|
||||||
copy(key[:], bpk)
|
|
||||||
*routingtable = append(*routingtable, cryptokey_route{
|
|
||||||
subnet: *ipnet,
|
|
||||||
destination: key,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Sort so most specific routes are first
|
|
||||||
sort.Slice(*routingtable, func(i, j int) bool {
|
|
||||||
im, _ := (*routingtable)[i].subnet.Mask.Size()
|
|
||||||
jm, _ := (*routingtable)[j].subnet.Mask.Size()
|
|
||||||
return im > jm
|
|
||||||
})
|
|
||||||
|
|
||||||
// Clear the cache as this route might change future routing
|
|
||||||
// Setting an empty slice keeps the memory whereas nil invokes GC
|
|
||||||
for k := range *routingcache {
|
|
||||||
delete(*routingcache, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.tun.log.Infoln("Added CKR remote subnet", cidr)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Looks up the most specific route for the given address (with the address
|
|
||||||
// length specified in bytes) from the crypto-key routing table. An error is
|
|
||||||
// returned if the address is not suitable or no route was found.
|
|
||||||
func (c *cryptokey) getPublicKeyForAddress(addr address.Address, addrlen int) (ed25519.PublicKey, error) {
|
|
||||||
|
|
||||||
// Check if the address is a valid Mesh address - if so it
|
|
||||||
// is exempt from all CKR checking
|
|
||||||
if addr.IsValid() {
|
|
||||||
return ed25519.PublicKey{}, errors.New("cannot look up CKR for Mesh addresses")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build our references to the routing table and cache
|
|
||||||
var routingtable *[]cryptokey_route
|
|
||||||
var routingcache *map[address.Address]cryptokey_route
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if addrlen == net.IPv6len {
|
|
||||||
routingcache = &c.ipv6cache
|
|
||||||
} else if addrlen == net.IPv4len {
|
|
||||||
routingcache = &c.ipv4cache
|
|
||||||
} else {
|
|
||||||
return ed25519.PublicKey{}, errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there's a cache entry for this addr
|
|
||||||
c.mutexcaches.RLock()
|
|
||||||
if route, ok := (*routingcache)[addr]; ok {
|
|
||||||
c.mutexcaches.RUnlock()
|
|
||||||
return route.destination, nil
|
|
||||||
}
|
|
||||||
c.mutexcaches.RUnlock()
|
|
||||||
|
|
||||||
c.mutexremotes.RLock()
|
|
||||||
defer c.mutexremotes.RUnlock()
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if addrlen == net.IPv6len {
|
|
||||||
routingtable = &c.ipv6remotes
|
|
||||||
} else if addrlen == net.IPv4len {
|
|
||||||
routingtable = &c.ipv4remotes
|
|
||||||
} else {
|
|
||||||
return ed25519.PublicKey{}, errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// No cache was found - start by converting the address into a net.IP
|
|
||||||
ip := make(net.IP, addrlen)
|
|
||||||
copy(ip[:addrlen], addr[:])
|
|
||||||
|
|
||||||
// Check if we have a route. At this point c.ipv6remotes should be
|
|
||||||
// pre-sorted so that the most specific routes are first
|
|
||||||
for _, route := range *routingtable {
|
|
||||||
// Does this subnet match the given IP?
|
|
||||||
if route.subnet.Contains(ip) {
|
|
||||||
c.mutexcaches.Lock()
|
|
||||||
defer c.mutexcaches.Unlock()
|
|
||||||
|
|
||||||
// Check if the routing cache is above a certain size, if it is evict
|
|
||||||
// a random entry so we can make room for this one. We take advantage
|
|
||||||
// of the fact that the iteration order is random here
|
|
||||||
for k := range *routingcache {
|
|
||||||
if len(*routingcache) < 1024 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
delete(*routingcache, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the entry for future packets to get a faster lookup
|
|
||||||
(*routingcache)[addr] = route
|
|
||||||
|
|
||||||
// Return the boxPubKey
|
|
||||||
return route.destination, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No route was found if we got to this point
|
|
||||||
return ed25519.PublicKey{}, fmt.Errorf("no route to %s", ip.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes a source subnet, which allows traffic with these source addresses to
|
|
||||||
// be tunnelled using crypto-key routing.
|
|
||||||
func (c *cryptokey) removeLocalSubnet(cidr string) error {
|
|
||||||
c.mutexlocals.Lock()
|
|
||||||
defer c.mutexlocals.Unlock()
|
|
||||||
|
|
||||||
// Is the CIDR we've been given valid?
|
|
||||||
_, ipnet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the prefix length and size
|
|
||||||
_, prefixsize := ipnet.Mask.Size()
|
|
||||||
|
|
||||||
// Build our references to the routing sources
|
|
||||||
var routingsources *[]net.IPNet
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if prefixsize == net.IPv6len*8 {
|
|
||||||
routingsources = &c.ipv6locals
|
|
||||||
} else if prefixsize == net.IPv4len*8 {
|
|
||||||
routingsources = &c.ipv4locals
|
|
||||||
} else {
|
|
||||||
return errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we already have this CIDR
|
|
||||||
for idx, subnet := range *routingsources {
|
|
||||||
if subnet.String() == ipnet.String() {
|
|
||||||
*routingsources = append((*routingsources)[:idx], (*routingsources)[idx+1:]...)
|
|
||||||
c.tun.log.Infoln("Removed CKR local subnet", cidr)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.New("local subnet not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes a destination route for the given CIDR to be tunnelled to the node
|
|
||||||
// with the given BoxPubKey.
|
|
||||||
func (c *cryptokey) removeRemoteSubnet(cidr string, dest string) error {
|
|
||||||
c.mutexremotes.Lock()
|
|
||||||
c.mutexcaches.Lock()
|
|
||||||
defer c.mutexremotes.Unlock()
|
|
||||||
defer c.mutexcaches.Unlock()
|
|
||||||
|
|
||||||
// Is the CIDR we've been given valid?
|
|
||||||
_, ipnet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the prefix length and size
|
|
||||||
_, prefixsize := ipnet.Mask.Size()
|
|
||||||
|
|
||||||
// Build our references to the routing table and cache
|
|
||||||
var routingtable *[]cryptokey_route
|
|
||||||
var routingcache *map[address.Address]cryptokey_route
|
|
||||||
|
|
||||||
// Check if the prefix is IPv4 or IPv6
|
|
||||||
if prefixsize == net.IPv6len*8 {
|
|
||||||
routingtable = &c.ipv6remotes
|
|
||||||
routingcache = &c.ipv6cache
|
|
||||||
} else if prefixsize == net.IPv4len*8 {
|
|
||||||
routingtable = &c.ipv4remotes
|
|
||||||
routingcache = &c.ipv4cache
|
|
||||||
} else {
|
|
||||||
return errors.New("unexpected prefix size")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the public key
|
|
||||||
bpk, err := hex.DecodeString(dest)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(bpk) != ed25519.PrivateKeySize {
|
|
||||||
return fmt.Errorf("incorrect key length for %s", dest)
|
|
||||||
}
|
|
||||||
netStr := ipnet.String()
|
|
||||||
|
|
||||||
for idx, route := range *routingtable {
|
|
||||||
if bytes.Equal(route.destination[:], bpk) && route.subnet.String() == netStr {
|
|
||||||
*routingtable = append((*routingtable)[:idx], (*routingtable)[idx+1:]...)
|
|
||||||
for k := range *routingcache {
|
|
||||||
delete(*routingcache, k)
|
|
||||||
}
|
|
||||||
c.tun.log.Infof("Removed CKR remote subnet %s via %s\n", cidr, dest)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("route does not exists for %s", cidr)
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
package tuntap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/ed25519"
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Arceliar/phony"
|
|
||||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
|
||||||
"github.com/RiV-chain/RiV-mesh/src/util"
|
|
||||||
"github.com/RiV-chain/RiV-mesh/src/mesh"
|
|
||||||
"golang.org/x/net/icmp"
|
|
||||||
"golang.org/x/net/ipv6"
|
|
||||||
)
|
|
||||||
|
|
||||||
const tunConnTimeout = 2 * time.Minute
|
|
||||||
|
|
||||||
type tunConn struct {
|
|
||||||
phony.Inbox
|
|
||||||
tun *TunAdapter
|
|
||||||
conn *mesh.Conn
|
|
||||||
addr address.Address
|
|
||||||
snet address.Subnet
|
|
||||||
stop chan struct{}
|
|
||||||
alive *time.Timer // From calling time.AfterFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) close() {
|
|
||||||
s.tun.Act(s, s._close_from_tun)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) _close_from_tun() {
|
|
||||||
go s.conn.Close() // Just in case it blocks on actor operations
|
|
||||||
delete(s.tun.addrToConn, s.addr)
|
|
||||||
delete(s.tun.subnetToConn, s.snet)
|
|
||||||
func() {
|
|
||||||
defer func() { recover() }()
|
|
||||||
close(s.stop) // Closes reader/writer goroutines
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) _read(bs []byte) (err error) {
|
|
||||||
select {
|
|
||||||
case <-s.stop:
|
|
||||||
err = errors.New("session was already closed")
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
if len(bs) == 0 {
|
|
||||||
err = errors.New("read packet with 0 size")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ipv4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
|
|
||||||
ipv6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
|
|
||||||
isCGA := true
|
|
||||||
// Check source addresses
|
|
||||||
switch {
|
|
||||||
case ipv6 && bs[8] == 0x02 && bytes.Equal(s.addr[:16], bs[8:24]): // source
|
|
||||||
case ipv6 && bs[8] == 0x03 && bytes.Equal(s.snet[:8], bs[8:16]): // source
|
|
||||||
default:
|
|
||||||
isCGA = false
|
|
||||||
}
|
|
||||||
// Check destination addresses
|
|
||||||
switch {
|
|
||||||
case ipv6 && bs[24] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[24:40]): // destination
|
|
||||||
case ipv6 && bs[24] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[24:32]): // destination
|
|
||||||
default:
|
|
||||||
isCGA = false
|
|
||||||
}
|
|
||||||
// Decide how to handle the packet
|
|
||||||
var skip bool
|
|
||||||
switch {
|
|
||||||
case isCGA: // Allowed
|
|
||||||
case s.tun.ckr.isEnabled() && (ipv4 || ipv6):
|
|
||||||
var srcAddr address.Address
|
|
||||||
var dstAddr address.Address
|
|
||||||
var addrlen int
|
|
||||||
if ipv4 {
|
|
||||||
copy(srcAddr[:], bs[12:16])
|
|
||||||
copy(dstAddr[:], bs[16:20])
|
|
||||||
addrlen = 4
|
|
||||||
}
|
|
||||||
if ipv6 {
|
|
||||||
copy(srcAddr[:], bs[8:24])
|
|
||||||
copy(dstAddr[:], bs[24:40])
|
|
||||||
addrlen = 16
|
|
||||||
}
|
|
||||||
if !s.tun.ckr.isValidLocalAddress(dstAddr, addrlen) {
|
|
||||||
// The destination address isn't in our CKR allowed range
|
|
||||||
skip = true
|
|
||||||
} else if key, err := s.tun.ckr.getPublicKeyForAddress(srcAddr, addrlen); err == nil {
|
|
||||||
if *s.conn.RemoteAddr().(*ed25519.PublicKey) == key {
|
|
||||||
// This is the one allowed CKR case, where source and destination addresses are both good
|
|
||||||
} else {
|
|
||||||
// The CKR key associated with this address doesn't match the sender's NodeID
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We have no CKR route for this source address
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
if skip {
|
|
||||||
err = errors.New("address not allowed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.tun.writer.writeFrom(s, bs)
|
|
||||||
s.stillAlive()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) writeFrom(from phony.Actor, bs []byte) {
|
|
||||||
s.Act(from, func() {
|
|
||||||
s._write(bs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) _write(bs []byte) (err error) {
|
|
||||||
select {
|
|
||||||
case <-s.stop:
|
|
||||||
err = errors.New("session was already closed")
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
v4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
|
|
||||||
v6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
|
|
||||||
isCGA := true
|
|
||||||
// Check source addresses
|
|
||||||
switch {
|
|
||||||
case v6 && bs[8] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[8:24]): // source
|
|
||||||
case v6 && bs[8] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[8:16]): // source
|
|
||||||
default:
|
|
||||||
isCGA = false
|
|
||||||
}
|
|
||||||
// Check destiantion addresses
|
|
||||||
switch {
|
|
||||||
case v6 && bs[24] == 0x02 && bytes.Equal(s.addr[:16], bs[24:40]): // destination
|
|
||||||
case v6 && bs[24] == 0x03 && bytes.Equal(s.snet[:8], bs[24:32]): // destination
|
|
||||||
default:
|
|
||||||
isCGA = false
|
|
||||||
}
|
|
||||||
// Decide how to handle the packet
|
|
||||||
var skip bool
|
|
||||||
switch {
|
|
||||||
case isCGA: // Allowed
|
|
||||||
case s.tun.ckr.isEnabled() && (v4 || v6):
|
|
||||||
var srcAddr address.Address
|
|
||||||
var dstAddr address.Address
|
|
||||||
var addrlen int
|
|
||||||
if v4 {
|
|
||||||
copy(srcAddr[:], bs[12:16])
|
|
||||||
copy(dstAddr[:], bs[16:20])
|
|
||||||
addrlen = 4
|
|
||||||
}
|
|
||||||
if v6 {
|
|
||||||
copy(srcAddr[:], bs[8:24])
|
|
||||||
copy(dstAddr[:], bs[24:40])
|
|
||||||
addrlen = 16
|
|
||||||
}
|
|
||||||
if !s.tun.ckr.isValidLocalAddress(srcAddr, addrlen) {
|
|
||||||
// The source address isn't in our CKR allowed range
|
|
||||||
skip = true
|
|
||||||
} else if key, err := s.tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
|
|
||||||
if *s.conn.RemoteAddr().(*crypto.BoxPubKey) == key {
|
|
||||||
// This is the one allowed CKR case, where source and destination addresses are both good
|
|
||||||
} else {
|
|
||||||
// The CKR key associated with this address doesn't match the sender's NodeID
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We have no CKR route for this destination address... why do we have the packet in the first place?
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
skip = true
|
|
||||||
}
|
|
||||||
if skip {
|
|
||||||
err = errors.New("address not allowed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := mesh.FlowKeyMessage{
|
|
||||||
FlowKey: util.GetFlowKey(bs),
|
|
||||||
Message: bs,
|
|
||||||
}
|
|
||||||
s.conn.WriteFrom(s, msg, func(err error) {
|
|
||||||
if err == nil {
|
|
||||||
// No point in wasting resources to send back an error if there was none
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.Act(s.conn, func() {
|
|
||||||
if e, eok := err.(mesh.ConnError); !eok {
|
|
||||||
if e.Closed() {
|
|
||||||
s.tun.log.Debugln(s.conn.String(), "TUN/TAP generic write debug:", err)
|
|
||||||
} else {
|
|
||||||
s.tun.log.Errorln(s.conn.String(), "TUN/TAP generic write error:", err)
|
|
||||||
}
|
|
||||||
} else if e.PacketTooBig() {
|
|
||||||
// TODO: This currently isn't aware of IPv4 for CKR
|
|
||||||
ptb := &icmp.PacketTooBig{
|
|
||||||
MTU: int(e.PacketMaximumSize()),
|
|
||||||
Data: bs[:900],
|
|
||||||
}
|
|
||||||
if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
|
|
||||||
s.tun.writer.writeFrom(s, packet)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if e.Closed() {
|
|
||||||
s.tun.log.Debugln(s.conn.String(), "TUN/TAP conn write debug:", err)
|
|
||||||
} else {
|
|
||||||
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn write error:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
s.stillAlive()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *tunConn) stillAlive() {
|
|
||||||
if s.alive != nil {
|
|
||||||
s.alive.Stop()
|
|
||||||
}
|
|
||||||
s.alive = time.AfterFunc(tunConnTimeout, s.close)
|
|
||||||
}
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
type MTU uint16
|
type MTU uint16
|
||||||
|
|
||||||
// TunAdapter represents a running TUN interface and extends the
|
// TunAdapter represents a running TUN interface and extends the
|
||||||
// mesh.Adapter type. In order to use the TUN adapter with Mesh, you
|
// mesh.Adapter type. In order to use the TUN adapter with Yggdrasil, you
|
||||||
// should pass this object to the mesh.SetRouterAdapter() function before
|
// should pass this object to the mesh.SetRouterAdapter() function before
|
||||||
// calling mesh.Start().
|
// calling mesh.Start().
|
||||||
type TunAdapter struct {
|
type TunAdapter struct {
|
||||||
|
@ -37,7 +37,6 @@ type TunAdapter struct {
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
addr address.Address
|
addr address.Address
|
||||||
subnet address.Subnet
|
subnet address.Subnet
|
||||||
ckr cryptokey
|
|
||||||
mtu uint64
|
mtu uint64
|
||||||
iface tun.Device
|
iface tun.Device
|
||||||
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
||||||
|
@ -93,7 +92,7 @@ func MaximumMTU() uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialises the TUN module. You must have acquired a Listener from
|
// Init initialises the TUN module. You must have acquired a Listener from
|
||||||
// the Mesh core before this point and it must not be in use elsewhere.
|
// the Yggdrasil core before this point and it must not be in use elsewhere.
|
||||||
func (tun *TunAdapter) Init(rwc *ipv6rwc.ReadWriteCloser, config *config.NodeConfig, log *log.Logger, options interface{}) error {
|
func (tun *TunAdapter) Init(rwc *ipv6rwc.ReadWriteCloser, config *config.NodeConfig, log *log.Logger, options interface{}) error {
|
||||||
tun.rwc = rwc
|
tun.rwc = rwc
|
||||||
tun.config = config
|
tun.config = config
|
||||||
|
@ -141,7 +140,6 @@ func (tun *TunAdapter) _start() error {
|
||||||
}
|
}
|
||||||
tun.rwc.SetMTU(tun.MTU())
|
tun.rwc.SetMTU(tun.MTU())
|
||||||
tun.isOpen = true
|
tun.isOpen = true
|
||||||
tun.ckr.init(tun)
|
|
||||||
tun.isEnabled = true
|
tun.isEnabled = true
|
||||||
go tun.read()
|
go tun.read()
|
||||||
go tun.write()
|
go tun.write()
|
||||||
|
|
|
@ -8,11 +8,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FlowKeyMessage struct {
|
|
||||||
FlowKey uint64
|
|
||||||
Message []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimerStop stops a timer and makes sure the channel is drained, returns true if the timer was stopped before firing.
|
// TimerStop stops a timer and makes sure the channel is drained, returns true if the timer was stopped before firing.
|
||||||
func TimerStop(t *time.Timer) bool {
|
func TimerStop(t *time.Timer) bool {
|
||||||
stopped := t.Stop()
|
stopped := t.Stop()
|
||||||
|
@ -40,41 +35,3 @@ func FuncTimeout(timeout time.Duration, f func()) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFlowKey takes an IP packet as an argument and returns some information about the traffic flow.
|
|
||||||
// For IPv4 packets, this is derived from the source and destination protocol and port numbers.
|
|
||||||
// For IPv6 packets, this is derived from the FlowLabel field of the packet if this was set, otherwise it's handled like IPv4.
|
|
||||||
// The FlowKey is then used internally by Mesh for congestion control.
|
|
||||||
func GetFlowKey(bs []byte) uint64 {
|
|
||||||
// Work out the flowkey - this is used to determine which switch queue
|
|
||||||
// traffic will be pushed to in the event of congestion
|
|
||||||
var flowkey uint64
|
|
||||||
// Get the IP protocol version from the packet
|
|
||||||
switch bs[0] & 0xf0 {
|
|
||||||
case 0x40: // IPv4 packet
|
|
||||||
ihl := (bs[0] & 0x0f) * 4 // whole IPv4 header length (min 20)
|
|
||||||
// 8 is minimum UDP packet length
|
|
||||||
if ihl >= 20 && len(bs)-int(ihl) >= 8 {
|
|
||||||
switch bs[9] /* protocol */ {
|
|
||||||
case 0x06 /* TCP */, 0x11 /* UDP */, 0x84 /* SCTP */ :
|
|
||||||
flowkey = uint64(bs[9])<<32 /* proto */ |
|
|
||||||
uint64(bs[ihl+0])<<24 | uint64(bs[ihl+1])<<16 /* sport */ |
|
|
||||||
uint64(bs[ihl+2])<<8 | uint64(bs[ihl+3]) /* dport */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 0x60: // IPv6 packet
|
|
||||||
// Check if the flowlabel was specified in the packet header
|
|
||||||
flowkey = uint64(bs[1]&0x0f)<<16 | uint64(bs[2])<<8 | uint64(bs[3])
|
|
||||||
// If the flowlabel isn't present, make protokey from proto | sport | dport
|
|
||||||
// if the packet meets minimum UDP packet length
|
|
||||||
if flowkey == 0 && len(bs) >= 48 {
|
|
||||||
switch bs[9] /* protocol */ {
|
|
||||||
case 0x06 /* TCP */, 0x11 /* UDP */, 0x84 /* SCTP */ :
|
|
||||||
flowkey = uint64(bs[6])<<32 /* proto */ |
|
|
||||||
uint64(bs[40])<<24 | uint64(bs[41])<<16 /* sport */ |
|
|
||||||
uint64(bs[42])<<8 | uint64(bs[43]) /* dport */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flowkey
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue