Caution
This project is a fork of the original yggdrasil-go project with substantial refactoring and experimental features. Both ygg and yggdrasil-go are EXPERIMENTAL software and should NOT be used for production or security-critical purposes.
This project has two main goals:
- Make Yggdrasil easier to embed and reuse as a Go library.
- Provide a place to experiment with features that are outside the current scope of upstream yggdrasil-go, including ideas often rejected as "not a goal of Yggdrasil".
The repository keeps compatibility with the Yggdrasil network where practical, but it is intentionally more willing to move code around, split runtime pieces into libraries, and carry experimental daemon features.
Reusable code moved into the ygglib submodule and the daemon/CLI moved into
yggd. Tightly coupled areas have been split so embedders can compose core,
transport setup, VTun, admin handlers, multicast, autopeering, and logging
without copying daemon internals.
Transport implementations are registered at runtime through
ygglib/transport. The lightweight library side keeps tcp and tls
transports, while the daemon wires heavier schemes such as quic, ws,
wss dialing, and unix.
Transport setup now runs over the gonnect.Network abstraction instead of
using standard-library network primitives directly. This makes it possible to
wrap carrier traffic, test with in-memory networks, or route selected hosts
through other networks.
Host-scoped network mappings are also supported. For example, .onion
transport hosts can be sent through Tor without encoding the proxy into a
special transport URI:
Transport: {
DefaultNetwork: native
NetworkMappings: {
"*.onion": { Type: socks, ProxyURL: "socks5://127.0.0.1:9050" }
"*.i2p": { Type: socks, ProxyURL: "socks5://127.0.0.1:4447" }
"*.loki": null
}
}
The autopeer module can periodically fetch public peer lists and add matching
peers when configured connectivity thresholds are not met. Sources may be URLs
returning public-peers JSON or the special BUILTIN source embedded in the
binary.
AutoPeer: {
Enabled: true
Sources: [BUILTIN]
FetchInterval: 1h
CheckInterval: 1m
MinimumConnected: 1
MinimumConnectedFromFetch: 1
Countries: ["germany", "france", "netherlands"]
TransportSchemes: ["tls", "tcp"]
}
The web module runs an
Yggdrasil node in the browser,
attaches a userspace
VTun stack, dials public peers through browser WebSocket APIs, and exposes
built-in HTTP and IRC clients over VTun.
You can also run it locally with:
just web-serveThen open http://127.0.0.1:8000/.
In addition to native OS TUN devices, the daemon can use virtual TUN implementations backed by an embedded userspace TCP/IP stack:
nativecreates and configures an OS TUN device.sockstuncreates a VTun netstack and exposes it through a local SOCKS server.outproxycreates a VTun netstack, listens for SOCKS clients inside Yggdrasil, and proxies them to the outer network.nonestarts without attaching a TUN implementation.
The sockstun and outproxy modes can run without native TUN privileges when
no other configured option needs them.
sockstun provides local SOCKS access to Yggdrasil without an OS TUN device.
It supports standard and extended SOCKS features, including bind, UDP, and Tor
extensions through socksgo lib.
Name resolution uses mnlib for mesh names and related Yggdrasil naming schemes. Optional fallback DNS (like alfis) can be configured for other names, for example through a public DNS service inside Yggdrasil.
TunType: sockstun
IfName: auto
TunSocksListen: 127.0.0.1:1080
TunSocksDNSFallback: "[300:6223::53]:53"
TunSocksDefaultProxy: "socks5://[324:71e:281a:9ed3::fa11]:1080"
sockstun also has optional selective TLS MITM support. When configured with a
local CA that the client trusts, matching HTTPS requests can be converted to
plain HTTP inside Yggdrasil. This is useful for browsing HTTP-only Yggdrasil
sites from HTTPS-only browser environments.
TunSocksTLSMITM: {
ca_file: "/etc/yggd/sockstun-mitm-ca.crt"
key_file: "/etc/yggd/sockstun-mitm-ca.key"
hostnames: ["*.ygg", "*.meshname", "*.meship", "*.onion", "*.i2p"]
}
outproxy makes it easier to host Yggdrasil-to-something SOCKS proxies. The
SOCKS listener is reachable on the node's Yggdrasil address, while selected
destinations can be forwarded to local or external proxy services.
TunType: outproxy
TunSocksListen: 127.0.0.1:1080 # Will use node's IPv6 addr instead of 127.0.0.1
TunSocksProxies: [
{ Filter: "*.onion", proxy_url: "socks5://127.0.0.1:9050" }
{ Filter: "*.i2p", proxy_url: "socks5://127.0.0.1:4447" }
]
TunSocksDefaultProxy: ""
The optional jumper module is inspired by
one-d-wide/yggdrasil-jumper.
It watches routed traffic, reads remote NodeInfo, and tries advertised public
peer addresses as direct links.
Unlike the original jumper idea, this implementation publishes addresses in NodeInfo instead of using a locally hosted discovery service. It does not perform NAT traversal yet.
Jumper: {
Enabled: true
Addresses: ["tls://example.net:12345"]
CheckInterval: 10s
LinkTimeout: 30s
}
The daemon restores a built-in TUN firewall feature that was removed from upstream yggdrasil-go. The default behavior is conservative for native TUN usage because many people run Yggdrasil is production despite its experimental status.
When enabled is left unset, the daemon enables the firewall for native TUN
and disables it for VTun-backed modes. ICMPv6 is always allowed. Outgoing TCP
and UDP create temporary return-flow entries. Unsolicited incoming TCP and UDP
are allowed only for configured destination ports.
TunFirewall: {
enabled: true
allowed_tcp_ports: [22, 80, 443]
allowed_udp_ports: [53]
}
yggdcan auto-create a config file when it is missing.- An optional HTTP admin API and minimal web admin panel can be enabled with
AdminWebListen. - Runtime admin handlers cover transport mappings, autopeering, jumper, firewall, and TUN attach/detach/replace operations.
- A full commented example config is available in example.conf.
The test suite includes package tests, upstream compatibility tests, transport manager tests, autopeering tests, jumper tests, sockstun/outproxy tests, TUN firewall tests, and complex multi-node topology tests.
just test-totalNote
The Docker-based integration suites are Linux-focused and use sudo.
See TESTING.md.
For a complete runnable example, see examples and lib-tutorial.md. A minimal core setup looks like this:
package main
import (
"fmt"
"github.com/asciimoth/gonnect/native"
"github.com/asciimoth/ygg/ygglib/config"
"github.com/asciimoth/ygg/ygglib/core"
ygglogger "github.com/asciimoth/ygg/ygglib/logger"
"github.com/asciimoth/ygg/ygglib/transport"
)
func main() {
cfg := config.GenerateConfig()
if err := cfg.GenerateSelfSignedCertificate(); err != nil {
panic(err)
}
network := &native.Network{}
if err := network.Up(); err != nil {
panic(err)
}
defer network.Down()
manager := transport.NewManager(network)
if err := manager.RegisterTransport(transport.NewTCPTransport()); err != nil {
panic(err)
}
tlsConfig, err := core.GenerateTLSConfig(cfg.Certificate)
if err != nil {
panic(err)
}
if err := manager.RegisterTransport(transport.NewTLSTransport(tlsConfig)); err != nil {
panic(err)
}
node, err := core.New(
cfg.Certificate,
ygglogger.Discard(),
core.TransportManager{Manager: manager},
)
if err != nil {
panic(err)
}
defer node.Stop()
fmt.Println(node.Address())
}Build or run directly from the flake:
nix build github:asciimoth/ygg#yggd
nix run github:asciimoth/ygg#yggd
nix run github:asciimoth/ygg#yggctl -- -endpoint tcp://localhost:9001 getSelf
nix profile add github:asciimoth/ygg#yggdNixOS users can import the module:
{
inputs.ygg.url = "github:asciimoth/ygg";
outputs = { self, nixpkgs, ygg, ... }: {
nixosConfigurations.example = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
ygg.nixosModules.yggd
{
services.yggd.enable = true;
services.yggd.settings = {
Peers = [ "tls://example.net:12345" ];
TunType = "native";
};
}
];
};
};
}Packages are published to my deb/rpm repository:
Setup it for your sytstem via script (or manually):
curl https://repo.moth.contact/setup.sh | bashThen install with your system package manager:
sudo apt install yggd
# or
sudo dnf install yggd
# or
sudo yum install yggdRelease archives and package artifacts are published on the
GitHub releases page. Archives
include yggd, yggctl, and genkeys.
AUR is available
Generate a config:
yggd -genconf > ygg.confStart with an explicit config:
sudo yggd -useconffile ygg.conf -logto stdoutThe daemon also supports auto-config mode:
sudo yggd -autoconf -logto stdoutFor a full commented config, see example.conf.
- Add an IRC server to the web demo so two browser users can connect to each other directly
- Add NAT traversal to jumper
- Add a WebRTC transport
- Build a desktop admin panel
- Build an Android app
- Add a built-in pretty-address miner
- Improve test coverage
- Optimize hot paths:
- Use bufpool where it matter
- Reduce lock and synchronization overhead
- Add man pages
- Package for more platforms
This code is released under the terms of the LGPLv3, but with an added exception that was taken from godeb. Under certain circumstances, this exception permits distribution of binaries that are statically or dynamically linked with this code, without requiring the distribution of Minimal Corresponding Source or Minimal Application Code. For more details, see LICENSE.