Skip to content
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
133f87d
Add .gitignore file to exclude yggdrasil related files
andyoknen Jul 29, 2025
de40a2c
Add development environment setup with Docker and VS Code Dev Containers
andyoknen Jul 29, 2025
d741657
Refactor configuration struct comments and update default multicast i…
andyoknen Jul 29, 2025
707e90b
Add VS Code extension for managing TODOs in development container
andyoknen Jul 29, 2025
345d5b9
Add minimal Web UI server
andyoknen Jul 29, 2025
51a1a0a
Refactor web UI server setup in main.go and update default host in co…
andyoknen Jul 29, 2025
13a6398
Update CodeQL actions to version 3 in CI workflow
andyoknen Jul 29, 2025
a718574
Update .gitignore to include additional yggdrasil related files and r…
andyoknen Jul 29, 2025
4acc41c
Update devcontainer configuration and Dockerfile to improve environme…
andyoknen Jul 29, 2025
170e369
Refactor Dockerfile to enhance Oh My Zsh installation and configurati…
andyoknen Jul 30, 2025
51e1ef3
Refactor error handling tests to use structured test cases and add ad…
andyoknen Jul 30, 2025
113dcbb
Add password authentication to WebUI and implement session management
andyoknen Jul 30, 2025
a984fba
Add brute force protection to authentication system
andyoknen Jul 30, 2025
008ac3d
Enhance WebUI with multilingual support
andyoknen Jul 30, 2025
fc35486
Implement theme toggle functionality and enhance UI styles
andyoknen Jul 30, 2025
3187114
Refactor static file serving in WebUI to allow CSS and JS access with…
andyoknen Jul 30, 2025
675e2e7
Implement Admin API integration in WebUI for enhanced node management
andyoknen Jul 30, 2025
2b3b4c3
Expose global state and update peer display logic in WebUI
andyoknen Jul 30, 2025
428d29b
Update authMiddleware to redirect to main page if no password is set …
andyoknen Jul 30, 2025
83bd279
Enhance WebUI footer and mobile controls
andyoknen Jul 30, 2025
791214c
Enhance WebUI with new peer display features and multilingual support
andyoknen Jul 31, 2025
1f75299
Improve error handling and fallback mechanisms in WebUI server
andyoknen Jul 31, 2025
fcb5efd
Add timeout handling and loading state management in API calls
andyoknen Jul 31, 2025
19710fb
Implement modal system for adding peers and logout confirmation in WebUI
andyoknen Jul 31, 2025
ee470d3
Implement configuration management in WebUI with API integration for …
andyoknen Aug 4, 2025
1ca9272
Merge branch 'yggdrasil-network:develop' into develop
andyoknen Aug 15, 2025
8ee5c9f
Enhance peer display by including peer names alongside IP addresses i…
andyoknen Aug 15, 2025
c0a9bc8
Refactor peer display in CLI by removing name formatting and directly…
andyoknen Aug 15, 2025
1f8f368
Add NodeInfo field to PeerEntry and PeerInfo structures, and update r…
andyoknen Aug 15, 2025
795cc50
Update peer handling to extract and display NodeInfo names in CLI and…
andyoknen Aug 15, 2025
e473c62
Add methods to extract NodeInfo names and improve peer display in Web…
andyoknen Aug 15, 2025
4935fcf
Remove debug logging related to NodeInfo processing in various compon…
andyoknen Aug 15, 2025
0d0f524
Implement JSON configuration editor in WebUI with save and restart fu…
andyoknen Aug 15, 2025
87251c5
Update fallback return value in YggdrasilUtils to use 'Anonymous' ins…
andyoknen Aug 15, 2025
9e11f76
Update fallback return value in YggdrasilUtils to return 'N/A' when p…
andyoknen Aug 15, 2025
1c61269
Refactor configuration editor to always display line numbers and upda…
andyoknen Aug 15, 2025
9931a87
Added information about PR to CHANGELOG
andyoknen Aug 15, 2025
03c0887
Update CHANGELOG to include development environment improvements, hig…
andyoknen Aug 15, 2025
8d0cbfd
Implement cross-platform restart handling in WebUIServer. Add sendRes…
andyoknen Aug 15, 2025
82b6813
Remove sendRestartSignal function from WebUIServer as it is no longer…
andyoknen Aug 15, 2025
eeae6ee
Refactor node version display logic to ensure proper formatting only …
andyoknen Aug 15, 2025
102e8e2
Add path validation for configuration files to prevent path traversal…
andyoknen Aug 15, 2025
443f9d0
Add safe file operation wrappers and enhance path validation in confi…
andyoknen Aug 15, 2025
2180e12
Remove safe file operation wrappers from configuration handling to st…
andyoknen Aug 15, 2025
09f600c
Remove checks for absolute paths in validateConfigPath function to si…
andyoknen Aug 15, 2025
8e44b57
Remove backup creation logic from SaveConfig function and update rela…
andyoknen Aug 15, 2025
a094c42
Refactor configuration handling by removing writable flag from Config…
andyoknen Aug 15, 2025
ce2b55c
Merge branch 'develop' into develop
andyoknen Aug 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "Yggdrasil Go Development",
"dockerFile": "../contrib/docker/devcontainer/Dockerfile",
"context": "..",
// Set up port forwarding for development
"forwardPorts": [
9000,
9001,
9002,
9003
],
// Configure Docker run options for TUN device access
"runArgs": [
"--privileged",
"--cap-add=NET_ADMIN",
"--device=/dev/net/tun"
],
// Configure VS Code settings and extensions
"customizations": {
"vscode": {
"settings": {
"go.toolsManagement.checkForUpdates": "local",
"go.useLanguageServer": true,
"go.gopath": "/go",
"go.goroot": "/usr/local/go",
"go.lintTool": "golangci-lint",
"go.lintFlags": [
"--fast"
],
"terminal.integrated.defaultProfile.linux": "zsh",
"editor.formatOnSave": true,
"go.formatTool": "goimports",
"go.buildOnSave": "package"
},
"extensions": [
"golang.Go",
"fabiospampinato.vscode-todo-plus"
]
}
},
// Environment variables for Go module caching
"containerEnv": {
"GOCACHE": "/home/vscode/.cache/go-build",
"GOMODCACHE": "/home/vscode/.cache/go-mod"
},
// Post create command to set up the environment
"postCreateCommand": "mkdir -p /home/vscode/.cache/go-build /home/vscode/.cache/go-mod && cd /workspaces/yggdrasil-go && go mod download && go mod tidy",
// Keep the container running
"overrideCommand": false,
// Use non-root user
"remoteUser": "vscode",
// Configure container user
"containerUser": "vscode",
"updateRemoteUserUID": true,
// Features to install
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
}
}
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ jobs:
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: go

- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3

build-linux:
strategy:
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
**/TODO
/yggdrasil
/yggdrasilctl
/yggdrasil.*
/run
/test
38 changes: 38 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug Yggdrasil with Config (Root)",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/yggdrasil",
"cwd": "${workspaceFolder}",
"env": {},
"args": [
"-useconffile",
"yggdrasil.json"
],
"showLog": true,
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"asRoot": true
},
{
"name": "Debug Yggdrasilctl",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/yggdrasilctl",
"cwd": "${workspaceFolder}",
"env": {},
"args": [],
"showLog": true,
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- in case of vulnerabilities.
-->

## [0.5.13] - ...

### Added

* Web UI interface for managing Yggdrasil nodes through a browser
* Built-in configuration editor with JSON support
* Peer management and monitoring
* Multilingual support (English and Russian)
* Authentication system with brute force protection
* Theme toggle functionality
* Mobile-responsive design
* NodeInfo exchange during peer handshakes for better peer identification
* Peer names are now displayed in CLI and admin responses
* NodeInfo data is exchanged and stored during connection establishment
* Enhanced peer display with names alongside IP addresses

## [0.5.12] - 2024-12-18

* Go 1.22 is now required to build Yggdrasil
Expand Down
39 changes: 39 additions & 0 deletions cmd/yggdrasil/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc"
"github.com/yggdrasil-network/yggdrasil-go/src/webui"

"github.com/yggdrasil-network/yggdrasil-go/src/core"
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
Expand All @@ -37,6 +38,7 @@ type node struct {
tun *tun.TunAdapter
multicast *multicast.Multicast
admin *admin.AdminSocket
webui *webui.WebUIServer
}

// The main function is responsible for configuring and starting Yggdrasil.
Expand All @@ -55,6 +57,7 @@ func main() {
getpkey := flag.Bool("publickey", false, "use in combination with either -useconf or -useconffile, outputs your public key")
loglevel := flag.String("loglevel", "info", "loglevel to enable")
chuserto := flag.String("user", "", "user (and, optionally, group) to set UID/GID to")

flag.Parse()

done := make(chan struct{})
Expand Down Expand Up @@ -90,6 +93,7 @@ func main() {
}

cfg := config.GenerateConfig()
var configPath string
var err error
switch {
case *ver:
Expand All @@ -107,6 +111,7 @@ func main() {
}

case *useconffile != "":
configPath = *useconffile
f, err := os.Open(*useconffile)
if err != nil {
panic(err)
Expand Down Expand Up @@ -189,6 +194,9 @@ func main() {
return
}

// Set current config for web UI
config.SetCurrentConfig(configPath, cfg)

n := &node{}

// Set up the Yggdrasil node itself.
Expand Down Expand Up @@ -282,6 +290,34 @@ func main() {
}
}

// Set up the web UI server if enabled in config.
if cfg.WebUI.Enable {
var listenAddr string
if cfg.WebUI.Host == "" {
listenAddr = fmt.Sprintf(":%d", cfg.WebUI.Port)
} else {
listenAddr = fmt.Sprintf("%s:%d", cfg.WebUI.Host, cfg.WebUI.Port)
}

n.webui = webui.Server(listenAddr, cfg.WebUI.Password, logger)

// Connect WebUI with AdminSocket for direct API access
if n.admin != nil {
n.webui.SetAdmin(n.admin)
}

if cfg.WebUI.Password != "" {
logger.Infof("WebUI password authentication enabled")
} else {
logger.Warnf("WebUI running without password protection")
}
go func() {
if err := n.webui.Start(); err != nil {
logger.Errorf("WebUI server error: %v", err)
}
}()
}

//Windows service shutdown
minwinsvc.SetOnExit(func() {
logger.Infof("Shutting down service ...")
Expand Down Expand Up @@ -320,6 +356,9 @@ func main() {
_ = n.admin.Stop()
_ = n.multicast.Stop()
_ = n.tun.Stop()
if n.webui != nil {
_ = n.webui.Stop()
}
n.core.Stop()
}

Expand Down
19 changes: 17 additions & 2 deletions cmd/yggdrasilctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ func run() int {
if err := json.Unmarshal(recv.Response, &resp); err != nil {
panic(err)
}
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Down", "Up", "Pr", "Cost", "Last Error"})
table.SetHeader([]string{"URI", "State", "Dir", "Name", "IP Address", "Uptime", "RTT", "RX", "TX", "Down", "Up", "Pr", "Cost", "Last Error"})
for _, peer := range resp.Peers {
state, lasterr, dir, rtt, rxr, txr := "Up", "-", "Out", "-", "-", "-"
state, lasterr, dir, rtt, rxr, txr, name := "Up", "-", "Out", "-", "-", "-", "-"
if !peer.Up {
state, lasterr = "Down", fmt.Sprintf("%s ago: %s", peer.LastErrorTime.Round(time.Second), peer.LastError)
} else if rttms := float64(peer.Latency.Microseconds()) / 1000; rttms > 0 {
Expand All @@ -197,6 +197,19 @@ func run() int {
if peer.Inbound {
dir = "In"
}

// Extract name from NodeInfo if available
if peer.NodeInfo != "" {
var nodeInfo map[string]interface{}
if err := json.Unmarshal([]byte(peer.NodeInfo), &nodeInfo); err == nil {
if nameValue, ok := nodeInfo["name"]; ok {
if nameStr, ok := nameValue.(string); ok && nameStr != "" {
name = nameStr
}
}
}
}

uristring := peer.URI
if uri, err := url.Parse(peer.URI); err == nil {
uri.RawQuery = ""
Expand All @@ -208,10 +221,12 @@ func run() int {
if peer.TXRate > 0 {
txr = peer.TXRate.String() + "/s"
}

table.Append([]string{
uristring,
state,
dir,
name,
peer.IPAddress,
(time.Duration(peer.Uptime) * time.Second).String(),
rtt,
Expand Down
70 changes: 70 additions & 0 deletions contrib/docker/devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Development Dockerfile for VS Code Dev Containers
FROM golang:1.24-bullseye

# Install only essential system packages
RUN apt-get update && apt-get install -y \
git \
ca-certificates \
sudo \
zsh \
locales \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Install essential Go development tools only
RUN go install golang.org/x/tools/gopls@latest \
&& go install github.com/go-delve/delve/cmd/dlv@latest \
&& go install golang.org/x/tools/cmd/goimports@latest \
&& go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

# Create a non-root user for development
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Create user and group with proper permissions
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/zsh \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME

# Fix Go module cache permissions
RUN chown -R $USERNAME:$USERNAME /go/pkg/mod || true \
&& chmod -R 755 /go/pkg/mod || true

# Create default yggdrasil conf directory
RUN mkdir -p /etc/yggdrasil \
&& chown -R $USERNAME:$USERNAME /etc/yggdrasil

# Set up the workspace with proper ownership
WORKDIR /workspace
RUN chown $USERNAME:$USERNAME /workspace

# Copy go module files to enable dependency caching
COPY go.mod go.sum ./
RUN go mod download && chown -R $USERNAME:$USERNAME /workspace

# Install Oh My Zsh for better terminal experience
RUN sh -c "ZSH=/usr/local/share/zsh/oh-my-zsh $(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" --unattended \
&& ZSH_CUSTOM=/usr/local/share/zsh/oh-my-zsh/custom \
&& git clone https://github.com/chrissicool/zsh-256color $ZSH_CUSTOM/plugins/zsh-256color \
&& git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions \
&& git clone https://github.com/popstas/zsh-command-time.git $ZSH_CUSTOM/plugins/command-time

# Setup zshrc
COPY contrib/docker/devcontainer/zshrc /usr/local/share/zsh/.zshrc
RUN rm -f /root/.zshrc \
&& ln -s /usr/local/share/zsh/.zshrc /root/.zshrc \
&& ln -s /usr/local/share/zsh/.zshrc /home/vscode/.zshrc

# Set up shell environment for vscode user
USER $USERNAME

# Set up shell environment for vscode user
ENV SHELL=/bin/zsh

# Expose common ports that might be used by Yggdrasil
EXPOSE 9001 9002 9003

# Keep container running for dev containers
CMD ["sleep", "infinity"]
Loading
Loading