├── .github
└── workflows
│ ├── ci.yml
│ └── pkg.yml
├── .gitignore
├── .golangci.yml
├── Dockerfile
├── LICENSE
├── README.md
├── build
├── clean
├── cmd
├── genkeys
│ └── main.go
├── yggdrasil
│ └── main.go
└── yggdrasilctl
│ ├── cmd_line_env.go
│ └── main.go
├── contrib
├── ansible
│ └── genkeys.go
├── apparmor
│ └── usr.bin.yggdrasil
├── busybox-init
│ └── S42yggdrasil
├── deb
│ └── generate.sh
├── docker
│ ├── Dockerfile
│ └── entrypoint.sh
├── freebsd
│ └── yggdrasil
├── logo
│ └── ygg-neilalexander.svg
├── macos
│ ├── create-pkg.sh
│ └── yggdrasil.plist
├── mobile
│ ├── build
│ ├── mobile.go
│ ├── mobile_android.go
│ ├── mobile_ios.go
│ ├── mobile_other.go
│ └── mobile_test.go
├── msi
│ ├── build-msi.sh
│ └── msversion.sh
├── openrc
│ └── yggdrasil
├── semver
│ ├── name.sh
│ └── version.sh
├── systemd
│ ├── yggdrasil-default-config.service
│ └── yggdrasil.service
└── yggdrasil-brute-simple
│ ├── LICENSE
│ ├── Makefile
│ ├── README.md
│ ├── util.c
│ ├── yggdrasil-brute-multi-curve25519.c
│ ├── yggdrasil-brute-multi-ed25519.c
│ └── yggdrasil-brute.h
├── go.mod
├── go.sum
├── misc
├── run-schannel-netns
└── run-twolink-test
└── src
├── autopeering
├── main.go
├── module.go
├── peers.go
└── peers.txt
├── meshname
└── module.go
└── popura
├── config.go
├── module.go
└── utils.go
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Yggdrasil
2 |
3 | on:
4 | push:
5 | pull_request:
6 | release:
7 | workflow_dispatch:
8 |
9 | concurrency:
10 | group: ${{ github.workflow }}-${{ github.ref }}
11 | cancel-in-progress: true
12 |
13 | jobs:
14 | lint:
15 | name: Lint
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/setup-go@v3
19 | with:
20 | go-version: 1.19
21 | - uses: actions/checkout@v3
22 | - name: golangci-lint
23 | uses: golangci/golangci-lint-action@v3
24 | with:
25 | args: --issues-exit-code=1
26 |
27 | codeql:
28 | name: Analyse
29 | runs-on: ubuntu-latest
30 | permissions:
31 | actions: read
32 | contents: read
33 | security-events: write
34 |
35 | steps:
36 | - name: Checkout repository
37 | uses: actions/checkout@v3
38 |
39 | - name: Initialize CodeQL
40 | uses: github/codeql-action/init@v2
41 | with:
42 | languages: go
43 |
44 | - name: Autobuild
45 | uses: github/codeql-action/autobuild@v2
46 |
47 | - name: Perform CodeQL Analysis
48 | uses: github/codeql-action/analyze@v2
49 |
50 | build-linux:
51 | strategy:
52 | fail-fast: false
53 | matrix:
54 | goversion: ["1.17", "1.18", "1.19"]
55 |
56 | name: Build & Test (Linux, Go ${{ matrix.goversion }})
57 | needs: [lint]
58 |
59 | runs-on: ubuntu-latest
60 | steps:
61 | - uses: actions/checkout@v3
62 |
63 | - name: Set up Go
64 | uses: actions/setup-go@v3
65 | with:
66 | go-version: ${{ matrix.goversion }}
67 |
68 | - name: Build Yggdrasil
69 | run: go build -v ./...
70 |
71 | - name: Unit tests
72 | run: go test -v ./...
73 |
74 | build-windows:
75 | strategy:
76 | fail-fast: false
77 | matrix:
78 | goversion: ["1.17", "1.18", "1.19"]
79 |
80 | name: Build & Test (Windows, Go ${{ matrix.goversion }})
81 | needs: [lint]
82 |
83 | runs-on: windows-latest
84 | steps:
85 | - uses: actions/checkout@v3
86 |
87 | - name: Set up Go
88 | uses: actions/setup-go@v3
89 | with:
90 | go-version: ${{ matrix.goversion }}
91 |
92 | - name: Build Yggdrasil
93 | run: go build -v ./...
94 |
95 | - name: Unit tests
96 | run: go test -v ./...
97 |
98 | build-macos:
99 | strategy:
100 | fail-fast: false
101 | matrix:
102 | goversion: ["1.17", "1.18", "1.19"]
103 |
104 | name: Build & Test (macOS, Go ${{ matrix.goversion }})
105 | needs: [lint]
106 |
107 | runs-on: macos-latest
108 | steps:
109 | - uses: actions/checkout@v3
110 |
111 | - name: Set up Go
112 | uses: actions/setup-go@v3
113 | with:
114 | go-version: ${{ matrix.goversion }}
115 |
116 | - name: Build Yggdrasil
117 | run: go build -v ./...
118 |
119 | - name: Unit tests
120 | run: go test -v ./...
121 |
122 | tests-ok:
123 | name: All tests passed
124 | needs: [lint, codeql, build-linux, build-windows, build-macos]
125 | runs-on: ubuntu-latest
126 | if: ${{ !cancelled() }}
127 | steps:
128 | - name: Check all tests passed
129 | uses: re-actors/alls-green@release/v1
130 | with:
131 | jobs: ${{ toJSON(needs) }}
--------------------------------------------------------------------------------
/.github/workflows/pkg.yml:
--------------------------------------------------------------------------------
1 | name: Packages
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | concurrency:
7 | group: ${{ github.workflow }}-${{ github.ref }}
8 | cancel-in-progress: true
9 |
10 | jobs:
11 | build-packages-debian:
12 | strategy:
13 | fail-fast: false
14 | matrix:
15 | pkgarch: ["amd64", "i386", "mips", "mipsel", "armhf", "armel", "arm64"]
16 |
17 | name: Package (Debian, ${{ matrix.pkgarch }})
18 |
19 | runs-on: ubuntu-latest
20 | steps:
21 | - uses: actions/checkout@v3
22 | with:
23 | fetch-depth: 0
24 |
25 | - name: Set up Go
26 | uses: actions/setup-go@v3
27 | with:
28 | go-version: 1.19
29 |
30 | - name: Build package
31 | env:
32 | PKGARCH: ${{ matrix.pkgarch }}
33 | run: sh contrib/deb/generate.sh
34 |
35 | - name: Upload artifacts
36 | uses: actions/upload-artifact@v3
37 | with:
38 | name: Debian package (${{ matrix.pkgarch }})
39 | path: "*.deb"
40 | if-no-files-found: error
41 |
42 | build-packages-macos:
43 | strategy:
44 | fail-fast: false
45 | matrix:
46 | pkgarch: ["amd64", "arm64"]
47 |
48 | name: Package (macOS, ${{ matrix.pkgarch }})
49 |
50 | runs-on: macos-latest
51 | steps:
52 | - uses: actions/checkout@v3
53 | with:
54 | fetch-depth: 0
55 |
56 | - name: Set up Go
57 | uses: actions/setup-go@v3
58 | with:
59 | go-version: 1.19
60 |
61 | - name: Build package
62 | env:
63 | PKGARCH: ${{ matrix.pkgarch }}
64 | run: sh contrib/macos/create-pkg.sh
65 |
66 | - name: Upload artifacts
67 | uses: actions/upload-artifact@v3
68 | with:
69 | name: macOS package (${{ matrix.pkgarch }})
70 | path: "*.pkg"
71 | if-no-files-found: error
72 |
73 | build-packages-windows:
74 | strategy:
75 | fail-fast: false
76 | matrix:
77 | pkgarch: ["x64", "x86", "arm", "arm64"]
78 |
79 | name: Package (Windows, ${{ matrix.pkgarch }})
80 |
81 | runs-on: windows-latest
82 | steps:
83 | - uses: actions/checkout@v3
84 | with:
85 | fetch-depth: 0
86 |
87 | - name: Set up Go
88 | uses: actions/setup-go@v3
89 | with:
90 | go-version: 1.19
91 |
92 | - name: Build package
93 | run: sh contrib/msi/build-msi.sh ${{ matrix.pkgarch }}
94 |
95 | - name: Upload artifacts
96 | uses: actions/upload-artifact@v3
97 | with:
98 | name: Windows package (${{ matrix.pkgarch }})
99 | path: "*.msi"
100 | if-no-files-found: error
101 |
102 | build-packages-router:
103 | strategy:
104 | fail-fast: false
105 | matrix:
106 | pkgarch: ["edgerouter-x", "edgerouter-lite", "vyos-amd64", "vyos-i386"]
107 |
108 | name: Package (Router, ${{ matrix.pkgarch }})
109 |
110 | runs-on: ubuntu-latest
111 | steps:
112 | - uses: actions/checkout@v3
113 | with:
114 | fetch-depth: 0
115 | path: yggdrasil
116 |
117 | - uses: actions/checkout@v3
118 | with:
119 | repository: neilalexander/vyatta-yggdrasil
120 | path: vyatta-yggdrasil
121 |
122 | - name: Set up Go
123 | uses: actions/setup-go@v3
124 | with:
125 | go-version: 1.19
126 |
127 | - name: Build package
128 | env:
129 | BUILDDIR_YGG: /home/runner/work/yggdrasil-go/yggdrasil-go/yggdrasil
130 | run: cd /home/runner/work/yggdrasil-go/yggdrasil-go/vyatta-yggdrasil && ./build-${{ matrix.pkgarch }}
131 |
132 | - name: Upload artifacts
133 | uses: actions/upload-artifact@v3
134 | with:
135 | name: Router package (${{ matrix.pkgarch }})
136 | path: "/home/runner/work/yggdrasil-go/yggdrasil-go/vyatta-yggdrasil/*.deb"
137 | if-no-files-found: error
138 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /yggdrasil
2 | /yggdrasil.exe
3 | /yggdrasilctl
4 | /yggdrasilctl.exe
5 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | run:
2 | build-tags:
3 | - lint
4 | issues-exit-code: 0 # TODO: change this to 1 when we want it to fail builds
5 | skip-dirs:
6 | - contrib/
7 | - misc/
8 | linters:
9 | disable:
10 | - gocyclo
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | contrib/docker/Dockerfile
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Popura ポプラ
2 |
3 | Popura, an alternative Yggdrasil network client
4 |
5 | *Yggdrasil Network* is a peer-to-peer IPv6 network with link-local peer discovery,
6 | automatic end-to-end encryption, distributed IP address allocation, and DHT-based routing information exchange.
7 |
8 | Popura uses the same Yggdrasil core API internally, but adds some useful
9 | experimental features which the original client lacks.
10 |
11 | By default, it works just like the original yggdrasil client, all features must be enabled manually.
12 | Popura adds new command line flags and config file sections to control those features.
13 |
14 | ## Features
15 |
16 | - [Autopeering](https://github.com/popura-network/Popura/wiki/Autopeering) over the Internet
17 | - Built-in decentralized DNS system [meshname](https://github.com/popura-network/Popura/wiki/Meshname)
18 |
19 | ## Installing
20 |
21 | - [Arch Linux](https://aur.archlinux.org/packages/popura-git/)
22 | - [Debian](https://github.com/popura-network/popura-debian-repo)
23 | - [Gentoo](https://yggdrasil-network.github.io/installation-linux-gentoo.html)
24 | - Just replace `net-p2p/yggdrasil-go` with `net-p2p/popura`
25 | - [OpenWRT](https://github.com/popura-network/hypermodem-packages)
26 | - [Windows](https://github.com/popura-network/Popura/releases)
27 |
28 | ## Building from source
29 |
30 | 1. Install Go
31 | 2. Clone this repository
32 | 3. Run `./build`
33 |
34 | ## Information
35 |
36 | [Wiki](https://github.com/popura-network/Popura/wiki)
37 |
38 | [Blog](https://popura-network.github.io)
39 |
40 | [Telegram channel](https://t.me/PopuraChan)
41 |
42 | [Yggdrasil documentation](https://yggdrasil-network.github.io/)
43 |
--------------------------------------------------------------------------------
/build:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ef
4 |
5 | PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version}
6 | PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)}
7 | PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
8 |
9 | LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
10 | ARGS="-v"
11 |
12 | while getopts "utc:l:dro:p" option
13 | do
14 | case "$option"
15 | in
16 | u) UPX=true;;
17 | t) TABLES=true;;
18 | c) GCFLAGS="$GCFLAGS $OPTARG";;
19 | l) LDFLAGS="$LDFLAGS $OPTARG";;
20 | d) ARGS="$ARGS -tags debug" DEBUG=true;;
21 | r) ARGS="$ARGS -race";;
22 | o) ARGS="$ARGS -o $OPTARG";;
23 | p) ARGS="$ARGS -buildmode=pie";;
24 | esac
25 | done
26 |
27 | if [ -z $TABLES ] && [ -z $DEBUG ]; then
28 | LDFLAGS="$LDFLAGS -s -w"
29 | fi
30 |
31 | for CMD in yggdrasil yggdrasilctl ; do
32 | echo "Building: $CMD"
33 | go build $ARGS -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" ./cmd/$CMD
34 |
35 | if [ $UPX ]; then
36 | upx --brute $CMD
37 | fi
38 | done
39 |
--------------------------------------------------------------------------------
/clean:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | git clean -dxf
3 |
--------------------------------------------------------------------------------
/cmd/genkeys/main.go:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | This file generates crypto keys.
4 | It prints out a new set of keys each time if finds a "better" one.
5 | By default, "better" means a higher NodeID (-> higher IP address).
6 | This is because the IP address format can compress leading 1s in the address, to increase the number of ID bits in the address.
7 |
8 | If run with the "-sig" flag, it generates signing keys instead.
9 | A "better" signing key means one with a higher TreeID.
10 | This only matters if it's high enough to make you the root of the tree.
11 |
12 | */
13 | package main
14 |
15 | import (
16 | "crypto/ed25519"
17 | "encoding/hex"
18 | "fmt"
19 | "net"
20 | "runtime"
21 |
22 | "github.com/yggdrasil-network/yggdrasil-go/src/address"
23 | )
24 |
25 | type keySet struct {
26 | priv ed25519.PrivateKey
27 | pub ed25519.PublicKey
28 | }
29 |
30 | func main() {
31 | threads := runtime.GOMAXPROCS(0)
32 | var currentBest ed25519.PublicKey
33 | newKeys := make(chan keySet, threads)
34 | for i := 0; i < threads; i++ {
35 | go doKeys(newKeys)
36 | }
37 | for {
38 | newKey := <-newKeys
39 | if isBetter(currentBest, newKey.pub) || len(currentBest) == 0 {
40 | currentBest = newKey.pub
41 | fmt.Println("-----")
42 | fmt.Println("Priv:", hex.EncodeToString(newKey.priv))
43 | fmt.Println("Pub:", hex.EncodeToString(newKey.pub))
44 | addr := address.AddrForKey(newKey.pub)
45 | fmt.Println("IP:", net.IP(addr[:]).String())
46 | }
47 | }
48 | }
49 |
50 | func isBetter(oldPub, newPub ed25519.PublicKey) bool {
51 | for idx := range oldPub {
52 | if newPub[idx] < oldPub[idx] {
53 | return true
54 | }
55 | if newPub[idx] > oldPub[idx] {
56 | break
57 | }
58 | }
59 | return false
60 | }
61 |
62 | func doKeys(out chan<- keySet) {
63 | bestKey := make(ed25519.PublicKey, ed25519.PublicKeySize)
64 | for idx := range bestKey {
65 | bestKey[idx] = 0xff
66 | }
67 | for {
68 | pub, priv, err := ed25519.GenerateKey(nil)
69 | if err != nil {
70 | panic(err)
71 | }
72 | if !isBetter(bestKey, pub) {
73 | continue
74 | }
75 | bestKey = pub
76 | out <- keySet{priv, pub}
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/cmd/yggdrasil/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "context"
6 | "crypto/ed25519"
7 | "encoding/hex"
8 | "encoding/json"
9 | "flag"
10 | "fmt"
11 | "io"
12 | "net"
13 | "os"
14 | "os/signal"
15 | "regexp"
16 | "strings"
17 | "sync"
18 | "syscall"
19 |
20 | "golang.org/x/text/encoding/unicode"
21 |
22 | "github.com/gologme/log"
23 | gsyslog "github.com/hashicorp/go-syslog"
24 | "github.com/hjson/hjson-go"
25 | "github.com/kardianos/minwinsvc"
26 | "github.com/mitchellh/mapstructure"
27 |
28 | "github.com/yggdrasil-network/yggdrasil-go/src/address"
29 | "github.com/yggdrasil-network/yggdrasil-go/src/admin"
30 | "github.com/yggdrasil-network/yggdrasil-go/src/config"
31 | "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
32 | "github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc"
33 |
34 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
35 | "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
36 | "github.com/yggdrasil-network/yggdrasil-go/src/tun"
37 | "github.com/yggdrasil-network/yggdrasil-go/src/version"
38 |
39 | "github.com/popura-network/Popura/src/autopeering"
40 | "github.com/popura-network/Popura/src/meshname"
41 | "github.com/popura-network/Popura/src/popura"
42 | )
43 |
44 | type node struct {
45 | core *core.Core
46 | tun *tun.TunAdapter
47 | multicast *multicast.Multicast
48 | admin *admin.AdminSocket
49 | meshname popura.Module // meshname.MeshnameServer
50 | autopeering popura.Module // autopeering.AutoPeering
51 | }
52 |
53 | func readConfig(log *log.Logger, useconf bool, useconffile string, normaliseconf bool) *config.NodeConfig {
54 | // Use a configuration file. If -useconf, the configuration will be read
55 | // from stdin. If -useconffile, the configuration will be read from the
56 | // filesystem.
57 | var conf []byte
58 | var err error
59 | if useconffile != "" {
60 | // Read the file from the filesystem
61 | conf, err = os.ReadFile(useconffile)
62 | } else {
63 | // Read the file from stdin.
64 | conf, err = io.ReadAll(os.Stdin)
65 | }
66 | if err != nil {
67 | panic(err)
68 | }
69 | // If there's a byte order mark - which Windows 10 is now incredibly fond of
70 | // throwing everywhere when it's converting things into UTF-16 for the hell
71 | // of it - remove it and decode back down into UTF-8. This is necessary
72 | // because hjson doesn't know what to do with UTF-16 and will panic
73 | if bytes.Equal(conf[0:2], []byte{0xFF, 0xFE}) ||
74 | bytes.Equal(conf[0:2], []byte{0xFE, 0xFF}) {
75 | utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
76 | decoder := utf.NewDecoder()
77 | conf, err = decoder.Bytes(conf)
78 | if err != nil {
79 | panic(err)
80 | }
81 | }
82 | // Generate a new configuration - this gives us a set of sane defaults -
83 | // then parse the configuration we loaded above on top of it. The effect
84 | // of this is that any configuration item that is missing from the provided
85 | // configuration will use a sane default.
86 | cfg := defaults.GenerateConfig()
87 | var dat map[string]interface{}
88 | if err := hjson.Unmarshal(conf, &dat); err != nil {
89 | panic(err)
90 | }
91 | // Sanitise the config
92 | confJson, err := json.Marshal(dat)
93 | if err != nil {
94 | panic(err)
95 | }
96 | if err := json.Unmarshal(confJson, &cfg); err != nil {
97 | panic(err)
98 | }
99 | // Overlay our newly mapped configuration onto the autoconf node config that
100 | // we generated above.
101 | if err = mapstructure.Decode(dat, &cfg); err != nil {
102 | panic(err)
103 | }
104 | return cfg
105 | }
106 |
107 | // Generates a new configuration and returns it in HJSON format. This is used
108 | // with -genconf.
109 | func doGenconf(isjson bool) string {
110 | cfg := defaults.GenerateConfig()
111 | var bs []byte
112 | var err error
113 | if isjson {
114 | bs, err = json.MarshalIndent(cfg, "", " ")
115 | } else {
116 | bs, err = hjson.Marshal(cfg)
117 | }
118 | if err != nil {
119 | panic(err)
120 | }
121 | return string(bs)
122 | }
123 |
124 | func setLogLevel(loglevel string, logger *log.Logger) {
125 | levels := [...]string{"error", "warn", "info", "debug", "trace"}
126 | loglevel = strings.ToLower(loglevel)
127 |
128 | contains := func() bool {
129 | for _, l := range levels {
130 | if l == loglevel {
131 | return true
132 | }
133 | }
134 | return false
135 | }
136 |
137 | if !contains() { // set default log level
138 | logger.Infoln("Loglevel parse failed. Set default level(info)")
139 | loglevel = "info"
140 | }
141 |
142 | for _, l := range levels {
143 | logger.EnableLevel(l)
144 | if l == loglevel {
145 | break
146 | }
147 | }
148 | }
149 |
150 | type yggArgs struct {
151 | genconf bool
152 | useconf bool
153 | normaliseconf bool
154 | confjson bool
155 | autoconf bool
156 | ver bool
157 | getaddr bool
158 | getsnet bool
159 | useconffile string
160 | logto string
161 | loglevel string
162 | autopeer bool
163 | meshnameenable bool
164 | meshnamelisten string
165 | }
166 |
167 | func getArgs() yggArgs {
168 | genconf := flag.Bool("genconf", false, "print a new config to stdout")
169 | useconf := flag.Bool("useconf", false, "read HJSON/JSON config from stdin")
170 | useconffile := flag.String("useconffile", "", "read HJSON/JSON config from specified file path")
171 | normaliseconf := flag.Bool("normaliseconf", false, "use in combination with either -useconf or -useconffile, outputs your configuration normalised")
172 | confjson := flag.Bool("json", false, "print configuration from -genconf or -normaliseconf as JSON instead of HJSON")
173 | autoconf := flag.Bool("autoconf", false, "automatic mode (dynamic IP, peer with IPv6 neighbors)")
174 | ver := flag.Bool("version", false, "prints the version of this build")
175 | logto := flag.String("logto", "stdout", "file path to log to, \"syslog\" or \"stdout\"")
176 | getaddr := flag.Bool("address", false, "returns the IPv6 address as derived from the supplied configuration")
177 | getsnet := flag.Bool("subnet", false, "returns the IPv6 subnet as derived from the supplied configuration")
178 | loglevel := flag.String("loglevel", "info", "loglevel to enable")
179 | autopeer := flag.Bool("autopeer", false, "automatic Internet peering (using peers from github.com/yggdrasil-network/public-peers)")
180 | meshnameenable := flag.Bool("meshname", false, "enable meshname resolver")
181 | meshnamelisten := flag.String("meshnamelisten", "[::1]:53535", "meshname resolver listen address")
182 | flag.Parse()
183 | return yggArgs{
184 | genconf: *genconf,
185 | useconf: *useconf,
186 | useconffile: *useconffile,
187 | normaliseconf: *normaliseconf,
188 | confjson: *confjson,
189 | autoconf: *autoconf,
190 | ver: *ver,
191 | logto: *logto,
192 | getaddr: *getaddr,
193 | getsnet: *getsnet,
194 | loglevel: *loglevel,
195 | autopeer: *autopeer,
196 | meshnameenable: *meshnameenable,
197 | meshnamelisten: *meshnamelisten,
198 | }
199 | }
200 |
201 | // The main function is responsible for configuring and starting Yggdrasil.
202 | func run(args yggArgs, ctx context.Context) {
203 | // Create a new logger that logs output to stdout.
204 | var logger *log.Logger
205 | switch args.logto {
206 | case "stdout":
207 | logger = log.New(os.Stdout, "", log.Flags())
208 | case "syslog":
209 | if syslogger, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, "DAEMON", version.BuildName()); err == nil {
210 | logger = log.New(syslogger, "", log.Flags())
211 | }
212 | default:
213 | if logfd, err := os.OpenFile(args.logto, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err == nil {
214 | logger = log.New(logfd, "", log.Flags())
215 | }
216 | }
217 | if logger == nil {
218 | logger = log.New(os.Stdout, "", log.Flags())
219 | logger.Warnln("Logging defaulting to stdout")
220 | }
221 |
222 | if args.normaliseconf {
223 | setLogLevel("error", logger)
224 | } else {
225 | setLogLevel(args.loglevel, logger)
226 | }
227 |
228 | var cfg *config.NodeConfig
229 | popuraConfig := popura.GenerateConfig()
230 | var err error
231 | switch {
232 | case args.ver:
233 | fmt.Println("Build name:", version.BuildName())
234 | fmt.Println("Build version:", version.BuildVersion())
235 | return
236 | case args.autoconf:
237 | // Use an autoconf-generated config, this will give us random keys and
238 | // port numbers, and will use an automatically selected TUN interface.
239 | cfg = defaults.GenerateConfig()
240 | case args.useconffile != "" || args.useconf:
241 | // Read the configuration from either stdin or from the filesystem
242 | cfg = readConfig(logger, args.useconf, args.useconffile, args.normaliseconf)
243 | // If the -normaliseconf option was specified then remarshal the above
244 | // configuration and print it back to stdout. This lets the user update
245 | // their configuration file with newly mapped names (like above) or to
246 | // convert from plain JSON to commented HJSON.
247 | if args.normaliseconf {
248 | var bs []byte
249 | if args.confjson {
250 | bs, err = json.MarshalIndent(cfg, "", " ")
251 | } else {
252 | bs, err = hjson.Marshal(cfg)
253 | }
254 | if err != nil {
255 | panic(err)
256 | }
257 | fmt.Println(string(bs))
258 | return
259 | }
260 | case args.genconf:
261 | // Generate a new configuration and print it to stdout.
262 | fmt.Println(doGenconf(args.confjson))
263 | return
264 | default:
265 | // No flags were provided, therefore print the list of flags to stdout.
266 | flag.PrintDefaults()
267 | }
268 | // Have we got a working configuration? If we don't then it probably means
269 | // that neither -autoconf, -useconf or -useconffile were set above. Stop
270 | // if we don't.
271 | if cfg == nil {
272 | return
273 | }
274 | // Have we been asked for the node address yet? If so, print it and then stop.
275 | getNodeKey := func() ed25519.PublicKey {
276 | if pubkey, err := hex.DecodeString(cfg.PrivateKey); err == nil {
277 | return ed25519.PrivateKey(pubkey).Public().(ed25519.PublicKey)
278 | }
279 | return nil
280 | }
281 | switch {
282 | case args.getaddr:
283 | if key := getNodeKey(); key != nil {
284 | addr := address.AddrForKey(key)
285 | ip := net.IP(addr[:])
286 | fmt.Println(ip.String())
287 | }
288 | return
289 | case args.getsnet:
290 | if key := getNodeKey(); key != nil {
291 | snet := address.SubnetForKey(key)
292 | ipnet := net.IPNet{
293 | IP: append(snet[:], 0, 0, 0, 0, 0, 0, 0, 0),
294 | Mask: net.CIDRMask(len(snet)*8, 128),
295 | }
296 | fmt.Println(ipnet.String())
297 | }
298 | return
299 | }
300 |
301 | n := &node{}
302 |
303 | // Setup the Yggdrasil node itself.
304 | {
305 | sk, err := hex.DecodeString(cfg.PrivateKey)
306 | if err != nil {
307 | panic(err)
308 | }
309 | options := []core.SetupOption{
310 | core.NodeInfo(cfg.NodeInfo),
311 | core.NodeInfoPrivacy(cfg.NodeInfoPrivacy),
312 | }
313 | for _, addr := range cfg.Listen {
314 | options = append(options, core.ListenAddress(addr))
315 | }
316 | for _, peer := range cfg.Peers {
317 | options = append(options, core.Peer{URI: peer})
318 | }
319 | for intf, peers := range cfg.InterfacePeers {
320 | for _, peer := range peers {
321 | options = append(options, core.Peer{URI: peer, SourceInterface: intf})
322 | }
323 | }
324 | for _, allowed := range cfg.AllowedPublicKeys {
325 | k, err := hex.DecodeString(allowed)
326 | if err != nil {
327 | panic(err)
328 | }
329 | options = append(options, core.AllowedPublicKey(k[:]))
330 | }
331 | if n.core, err = core.New(sk[:], logger, options...); err != nil {
332 | panic(err)
333 | }
334 | }
335 |
336 | // Setup the admin socket.
337 | {
338 | options := []admin.SetupOption{
339 | admin.ListenAddress(cfg.AdminListen),
340 | }
341 | if n.admin, err = admin.New(n.core, logger, options...); err != nil {
342 | panic(err)
343 | }
344 | if n.admin != nil {
345 | n.admin.SetupAdminHandlers()
346 | }
347 | }
348 |
349 | // Setup the multicast module.
350 | {
351 | options := []multicast.SetupOption{}
352 | for _, intf := range cfg.MulticastInterfaces {
353 | options = append(options, multicast.MulticastInterface{
354 | Regex: regexp.MustCompile(intf.Regex),
355 | Beacon: intf.Beacon,
356 | Listen: intf.Listen,
357 | Port: intf.Port,
358 | Priority: intf.Priority,
359 | })
360 | }
361 | if n.multicast, err = multicast.New(n.core, logger, options...); err != nil {
362 | panic(err)
363 | }
364 | if n.admin != nil && n.multicast != nil {
365 | n.multicast.SetupAdminHandlers(n.admin)
366 | }
367 | }
368 |
369 | // Setup the TUN module.
370 | {
371 | options := []tun.SetupOption{
372 | tun.InterfaceName(cfg.IfName),
373 | tun.InterfaceMTU(cfg.IfMTU),
374 | }
375 | if n.tun, err = tun.New(ipv6rwc.NewReadWriteCloser(n.core), logger, options...); err != nil {
376 | panic(err)
377 | }
378 | if n.admin != nil && n.tun != nil {
379 | n.tun.SetupAdminHandlers(n.admin)
380 | }
381 | }
382 |
383 | // Setup Popura modules
384 | {
385 | n.meshname = &meshname.MeshnameServer{}
386 | n.autopeering = &autopeering.AutoPeering{}
387 |
388 | popuraConfig.Meshname.Enable = args.meshnameenable
389 | popuraConfig.Meshname.Listen = args.meshnamelisten
390 | _ = n.meshname.Init(n.core, cfg, popuraConfig, logger, nil)
391 | if err = n.meshname.Start(); err != nil {
392 | panic(err)
393 | }
394 |
395 | popuraConfig.Autopeering.Enable = args.autopeer
396 | _ = n.autopeering.Init(n.core, cfg, popuraConfig, logger, nil)
397 | if err = n.autopeering.Start(); err != nil {
398 | panic(err)
399 | }
400 | }
401 |
402 | // Make some nice output that tells us what our IPv6 address and subnet are.
403 | // This is just logged to stdout for the user.
404 | address := n.core.Address()
405 | subnet := n.core.Subnet()
406 | public := n.core.GetSelf().Key
407 | logger.Infof("Your public key is %s", hex.EncodeToString(public[:]))
408 | logger.Infof("Your IPv6 address is %s", address.String())
409 | logger.Infof("Your IPv6 subnet is %s", subnet.String())
410 |
411 | // Block until we are told to shut down.
412 | <-ctx.Done()
413 |
414 | // Shut down the node.
415 | _ = n.admin.Stop()
416 | _ = n.multicast.Stop()
417 | _ = n.tun.Stop()
418 | _ = n.autopeering.Stop()
419 | _ = n.meshname.Stop()
420 | n.core.Stop()
421 | }
422 |
423 | func main() {
424 | args := getArgs()
425 |
426 | // Catch interrupts from the operating system to exit gracefully.
427 | ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
428 |
429 | // Capture the service being stopped on Windows.
430 | minwinsvc.SetOnExit(cancel)
431 |
432 | // Start the node, block and then wait for it to shut down.
433 | var wg sync.WaitGroup
434 | wg.Add(1)
435 | go func() {
436 | defer wg.Done()
437 | run(args, ctx)
438 | }()
439 | wg.Wait()
440 | }
441 |
--------------------------------------------------------------------------------
/cmd/yggdrasilctl/cmd_line_env.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "flag"
6 | "fmt"
7 | "log"
8 | "os"
9 |
10 | "github.com/hjson/hjson-go"
11 | "golang.org/x/text/encoding/unicode"
12 |
13 | "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
14 | )
15 |
16 | type CmdLineEnv struct {
17 | args []string
18 | endpoint, server string
19 | injson, ver bool
20 | }
21 |
22 | func newCmdLineEnv() CmdLineEnv {
23 | var cmdLineEnv CmdLineEnv
24 | cmdLineEnv.endpoint = defaults.GetDefaults().DefaultAdminListen
25 | return cmdLineEnv
26 | }
27 |
28 | func (cmdLineEnv *CmdLineEnv) parseFlagsAndArgs() {
29 | flag.Usage = func() {
30 | fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n\n", os.Args[0])
31 | fmt.Println("Options:")
32 | flag.PrintDefaults()
33 | fmt.Println()
34 | fmt.Println("Please note that options must always specified BEFORE the command\non the command line or they will be ignored.")
35 | fmt.Println()
36 | fmt.Println("Commands:\n - Use \"list\" for a list of available commands")
37 | fmt.Println()
38 | fmt.Println("Examples:")
39 | fmt.Println(" - ", os.Args[0], "list")
40 | fmt.Println(" - ", os.Args[0], "getPeers")
41 | fmt.Println(" - ", os.Args[0], "-v getSelf")
42 | fmt.Println(" - ", os.Args[0], "setTunTap name=auto mtu=1500 tap_mode=false")
43 | fmt.Println(" - ", os.Args[0], "-endpoint=tcp://localhost:9001 getDHT")
44 | fmt.Println(" - ", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getDHT")
45 | }
46 |
47 | server := flag.String("endpoint", cmdLineEnv.endpoint, "Admin socket endpoint")
48 | injson := flag.Bool("json", false, "Output in JSON format (as opposed to pretty-print)")
49 | ver := flag.Bool("version", false, "Prints the version of this build")
50 |
51 | flag.Parse()
52 |
53 | cmdLineEnv.args = flag.Args()
54 | cmdLineEnv.server = *server
55 | cmdLineEnv.injson = *injson
56 | cmdLineEnv.ver = *ver
57 | }
58 |
59 | func (cmdLineEnv *CmdLineEnv) setEndpoint(logger *log.Logger) {
60 | if cmdLineEnv.server == cmdLineEnv.endpoint {
61 | if config, err := os.ReadFile(defaults.GetDefaults().DefaultConfigFile); err == nil {
62 | if bytes.Equal(config[0:2], []byte{0xFF, 0xFE}) ||
63 | bytes.Equal(config[0:2], []byte{0xFE, 0xFF}) {
64 | utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
65 | decoder := utf.NewDecoder()
66 | config, err = decoder.Bytes(config)
67 | if err != nil {
68 | panic(err)
69 | }
70 | }
71 | var dat map[string]interface{}
72 | if err := hjson.Unmarshal(config, &dat); err != nil {
73 | panic(err)
74 | }
75 | if ep, ok := dat["AdminListen"].(string); ok && (ep != "none" && ep != "") {
76 | cmdLineEnv.endpoint = ep
77 | logger.Println("Found platform default config file", defaults.GetDefaults().DefaultConfigFile)
78 | logger.Println("Using endpoint", cmdLineEnv.endpoint, "from AdminListen")
79 | } else {
80 | logger.Println("Configuration file doesn't contain appropriate AdminListen option")
81 | logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
82 | }
83 | } else {
84 | logger.Println("Can't open config file from default location", defaults.GetDefaults().DefaultConfigFile)
85 | logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
86 | }
87 | } else {
88 | cmdLineEnv.endpoint = cmdLineEnv.server
89 | logger.Println("Using endpoint", cmdLineEnv.endpoint, "from command line")
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/cmd/yggdrasilctl/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "errors"
7 | "flag"
8 | "fmt"
9 | "log"
10 | "net"
11 | "net/url"
12 | "os"
13 | "strings"
14 | "time"
15 |
16 | "github.com/olekukonko/tablewriter"
17 | "github.com/yggdrasil-network/yggdrasil-go/src/admin"
18 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
19 | "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
20 | "github.com/yggdrasil-network/yggdrasil-go/src/tun"
21 | "github.com/yggdrasil-network/yggdrasil-go/src/version"
22 | )
23 |
24 | func main() {
25 | // makes sure we can use defer and still return an error code to the OS
26 | os.Exit(run())
27 | }
28 |
29 | func run() int {
30 | logbuffer := &bytes.Buffer{}
31 | logger := log.New(logbuffer, "", log.Flags())
32 |
33 | defer func() int {
34 | if r := recover(); r != nil {
35 | logger.Println("Fatal error:", r)
36 | fmt.Print(logbuffer)
37 | return 1
38 | }
39 | return 0
40 | }()
41 |
42 | cmdLineEnv := newCmdLineEnv()
43 | cmdLineEnv.parseFlagsAndArgs()
44 |
45 | if cmdLineEnv.ver {
46 | fmt.Println("Build name:", version.BuildName())
47 | fmt.Println("Build version:", version.BuildVersion())
48 | fmt.Println("To get the version number of the running Yggdrasil node, run", os.Args[0], "getSelf")
49 | return 0
50 | }
51 |
52 | if len(cmdLineEnv.args) == 0 {
53 | flag.Usage()
54 | return 0
55 | }
56 |
57 | cmdLineEnv.setEndpoint(logger)
58 |
59 | var conn net.Conn
60 | u, err := url.Parse(cmdLineEnv.endpoint)
61 | if err == nil {
62 | switch strings.ToLower(u.Scheme) {
63 | case "unix":
64 | logger.Println("Connecting to UNIX socket", cmdLineEnv.endpoint[7:])
65 | conn, err = net.Dial("unix", cmdLineEnv.endpoint[7:])
66 | case "tcp":
67 | logger.Println("Connecting to TCP socket", u.Host)
68 | conn, err = net.Dial("tcp", u.Host)
69 | default:
70 | logger.Println("Unknown protocol or malformed address - check your endpoint")
71 | err = errors.New("protocol not supported")
72 | }
73 | } else {
74 | logger.Println("Connecting to TCP socket", u.Host)
75 | conn, err = net.Dial("tcp", cmdLineEnv.endpoint)
76 | }
77 | if err != nil {
78 | panic(err)
79 | }
80 |
81 | logger.Println("Connected")
82 | defer conn.Close()
83 |
84 | decoder := json.NewDecoder(conn)
85 | encoder := json.NewEncoder(conn)
86 | send := &admin.AdminSocketRequest{}
87 | recv := &admin.AdminSocketResponse{}
88 | args := map[string]string{}
89 | for c, a := range cmdLineEnv.args {
90 | if c == 0 {
91 | if strings.HasPrefix(a, "-") {
92 | logger.Printf("Ignoring flag %s as it should be specified before other parameters\n", a)
93 | continue
94 | }
95 | logger.Printf("Sending request: %v\n", a)
96 | send.Name = a
97 | continue
98 | }
99 | tokens := strings.SplitN(a, "=", 2)
100 | switch {
101 | case len(tokens) == 1:
102 | logger.Println("Ignoring invalid argument:", a)
103 | default:
104 | args[tokens[0]] = tokens[1]
105 | }
106 | }
107 | if send.Arguments, err = json.Marshal(args); err != nil {
108 | panic(err)
109 | }
110 | if err := encoder.Encode(&send); err != nil {
111 | panic(err)
112 | }
113 | logger.Printf("Request sent")
114 | if err := decoder.Decode(&recv); err != nil {
115 | panic(err)
116 | }
117 | if recv.Status == "error" {
118 | if err := recv.Error; err != "" {
119 | fmt.Println("Admin socket returned an error:", err)
120 | } else {
121 | fmt.Println("Admin socket returned an error but didn't specify any error text")
122 | }
123 | return 1
124 | }
125 | if cmdLineEnv.injson {
126 | if json, err := json.MarshalIndent(recv.Response, "", " "); err == nil {
127 | fmt.Println(string(json))
128 | }
129 | return 0
130 | }
131 |
132 | table := tablewriter.NewWriter(os.Stdout)
133 | table.SetAlignment(tablewriter.ALIGN_LEFT)
134 | table.SetAutoFormatHeaders(false)
135 | table.SetCenterSeparator("")
136 | table.SetColumnSeparator("")
137 | table.SetRowSeparator("")
138 | table.SetHeaderLine(false)
139 | table.SetBorder(false)
140 | table.SetTablePadding("\t") // pad with tabs
141 | table.SetNoWhiteSpace(true)
142 | table.SetAutoWrapText(false)
143 |
144 | switch strings.ToLower(send.Name) {
145 | case "list":
146 | var resp admin.ListResponse
147 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
148 | panic(err)
149 | }
150 | table.SetHeader([]string{"Command", "Arguments", "Description"})
151 | for _, entry := range resp.List {
152 | for i := range entry.Fields {
153 | entry.Fields[i] = entry.Fields[i] + "=..."
154 | }
155 | table.Append([]string{entry.Command, strings.Join(entry.Fields, ", "), entry.Description})
156 | }
157 | table.Render()
158 |
159 | case "getself":
160 | var resp admin.GetSelfResponse
161 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
162 | panic(err)
163 | }
164 | table.Append([]string{"Build name:", resp.BuildName})
165 | table.Append([]string{"Build version:", resp.BuildVersion})
166 | table.Append([]string{"IPv6 address:", resp.IPAddress})
167 | table.Append([]string{"IPv6 subnet:", resp.Subnet})
168 | table.Append([]string{"Coordinates:", fmt.Sprintf("%v", resp.Coords)})
169 | table.Append([]string{"Public key:", resp.PublicKey})
170 | table.Render()
171 |
172 | case "getpeers":
173 | var resp admin.GetPeersResponse
174 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
175 | panic(err)
176 | }
177 | table.SetHeader([]string{"Port", "Public Key", "IP Address", "Uptime", "RX", "TX", "Pr", "URI"})
178 | for _, peer := range resp.Peers {
179 | table.Append([]string{
180 | fmt.Sprintf("%d", peer.Port),
181 | peer.PublicKey,
182 | peer.IPAddress,
183 | (time.Duration(peer.Uptime) * time.Second).String(),
184 | peer.RXBytes.String(),
185 | peer.TXBytes.String(),
186 | fmt.Sprintf("%d", peer.Priority),
187 | peer.Remote,
188 | })
189 | }
190 | table.Render()
191 |
192 | case "getdht":
193 | var resp admin.GetDHTResponse
194 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
195 | panic(err)
196 | }
197 | table.SetHeader([]string{"Public Key", "IP Address", "Port", "Rest"})
198 | for _, dht := range resp.DHT {
199 | table.Append([]string{
200 | dht.PublicKey,
201 | dht.IPAddress,
202 | fmt.Sprintf("%d", dht.Port),
203 | fmt.Sprintf("%d", dht.Rest),
204 | })
205 | }
206 | table.Render()
207 |
208 | case "getpaths":
209 | var resp admin.GetPathsResponse
210 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
211 | panic(err)
212 | }
213 | table.SetHeader([]string{"Public Key", "IP Address", "Path"})
214 | for _, p := range resp.Paths {
215 | table.Append([]string{
216 | p.PublicKey,
217 | p.IPAddress,
218 | fmt.Sprintf("%v", p.Path),
219 | })
220 | }
221 | table.Render()
222 |
223 | case "getsessions":
224 | var resp admin.GetSessionsResponse
225 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
226 | panic(err)
227 | }
228 | table.SetHeader([]string{"Public Key", "IP Address", "Uptime", "RX", "TX"})
229 | for _, p := range resp.Sessions {
230 | table.Append([]string{
231 | p.PublicKey,
232 | p.IPAddress,
233 | (time.Duration(p.Uptime) * time.Second).String(),
234 | p.RXBytes.String(),
235 | p.TXBytes.String(),
236 | })
237 | }
238 | table.Render()
239 |
240 | case "getnodeinfo":
241 | var resp core.GetNodeInfoResponse
242 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
243 | panic(err)
244 | }
245 | for _, v := range resp {
246 | fmt.Println(string(v))
247 | break
248 | }
249 |
250 | case "getmulticastinterfaces":
251 | var resp multicast.GetMulticastInterfacesResponse
252 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
253 | panic(err)
254 | }
255 | table.SetHeader([]string{"Interface"})
256 | for _, p := range resp.Interfaces {
257 | table.Append([]string{p})
258 | }
259 | table.Render()
260 |
261 | case "gettun":
262 | var resp tun.GetTUNResponse
263 | if err := json.Unmarshal(recv.Response, &resp); err != nil {
264 | panic(err)
265 | }
266 | table.Append([]string{"TUN enabled:", fmt.Sprintf("%#v", resp.Enabled)})
267 | if resp.Enabled {
268 | table.Append([]string{"Interface name:", resp.Name})
269 | table.Append([]string{"Interface MTU:", fmt.Sprintf("%d", resp.MTU)})
270 | }
271 | table.Render()
272 |
273 | case "addpeer", "removepeer":
274 |
275 | default:
276 | fmt.Println(string(recv.Response))
277 | }
278 |
279 | return 0
280 | }
281 |
--------------------------------------------------------------------------------
/contrib/ansible/genkeys.go:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | This file generates crypto keys for [ansible-yggdrasil](https://github.com/jcgruenhage/ansible-yggdrasil/)
4 |
5 | */
6 | package main
7 |
8 | import (
9 | "crypto/ed25519"
10 | "encoding/hex"
11 | "flag"
12 | "fmt"
13 | "net"
14 | "os"
15 |
16 | "github.com/cheggaaa/pb/v3"
17 | "github.com/yggdrasil-network/yggdrasil-go/src/address"
18 | )
19 |
20 | var numHosts = flag.Int("hosts", 1, "number of host vars to generate")
21 | var keyTries = flag.Int("tries", 1000, "number of tries before taking the best keys")
22 |
23 | type keySet struct {
24 | priv []byte
25 | pub []byte
26 | ip string
27 | }
28 |
29 | func main() {
30 | flag.Parse()
31 |
32 | bar := pb.StartNew(*keyTries*2 + *numHosts)
33 |
34 | if *numHosts > *keyTries {
35 | println("Can't generate less keys than hosts.")
36 | return
37 | }
38 |
39 | var keys []keySet
40 | for i := 0; i < *numHosts+1; i++ {
41 | keys = append(keys, newKey())
42 | bar.Increment()
43 | }
44 | keys = sortKeySetArray(keys)
45 | for i := 0; i < *keyTries-*numHosts-1; i++ {
46 | keys[0] = newKey()
47 | keys = bubbleUpTo(keys, 0)
48 | bar.Increment()
49 | }
50 |
51 | os.MkdirAll("host_vars", 0755)
52 |
53 | for i := 1; i <= *numHosts; i++ {
54 | os.MkdirAll(fmt.Sprintf("host_vars/%x", i), 0755)
55 | file, err := os.Create(fmt.Sprintf("host_vars/%x/vars", i))
56 | if err != nil {
57 | return
58 | }
59 | defer file.Close()
60 | file.WriteString(fmt.Sprintf("yggdrasil_public_key: %v\n", hex.EncodeToString(keys[i].pub)))
61 | file.WriteString("yggdrasil_private_key: \"{{ vault_yggdrasil_private_key }}\"\n")
62 | file.WriteString(fmt.Sprintf("ansible_host: %v\n", keys[i].ip))
63 |
64 | file, err = os.Create(fmt.Sprintf("host_vars/%x/vault", i))
65 | if err != nil {
66 | return
67 | }
68 | defer file.Close()
69 | file.WriteString(fmt.Sprintf("vault_yggdrasil_private_key: %v\n", hex.EncodeToString(keys[i].priv)))
70 | bar.Increment()
71 | }
72 | bar.Finish()
73 | }
74 |
75 | func newKey() keySet {
76 | pub, priv, err := ed25519.GenerateKey(nil)
77 | if err != nil {
78 | panic(err)
79 | }
80 | ip := net.IP(address.AddrForKey(pub)[:]).String()
81 | return keySet{priv[:], pub[:], ip}
82 | }
83 |
84 | func isBetter(oldID, newID []byte) bool {
85 | for idx := range oldID {
86 | if newID[idx] < oldID[idx] {
87 | return true
88 | }
89 | if newID[idx] > oldID[idx] {
90 | return false
91 | }
92 | }
93 | return false
94 | }
95 |
96 | func sortKeySetArray(sets []keySet) []keySet {
97 | for i := 0; i < len(sets); i++ {
98 | sets = bubbleUpTo(sets, i)
99 | }
100 | return sets
101 | }
102 |
103 | func bubbleUpTo(sets []keySet, num int) []keySet {
104 | for i := 0; i < len(sets)-num-1; i++ {
105 | if isBetter(sets[i+1].pub, sets[i].pub) {
106 | var tmp = sets[i]
107 | sets[i] = sets[i+1]
108 | sets[i+1] = tmp
109 | } else {
110 | break
111 | }
112 | }
113 | return sets
114 | }
115 |
--------------------------------------------------------------------------------
/contrib/apparmor/usr.bin.yggdrasil:
--------------------------------------------------------------------------------
1 | # Last Modified: Fri Oct 30 11:33:31 2020
2 | #include
3 |
4 | /usr/bin/yggdrasil {
5 | #include
6 | #include
7 |
8 | capability net_admin,
9 | capability net_raw,
10 |
11 | /dev/net/tun rw,
12 | /proc/sys/net/core/somaxconn r,
13 | /sys/kernel/mm/transparent_hugepage/hpage_pmd_size r,
14 |
15 | /etc/yggdrasil.conf rw,
16 | /run/yggdrasil.sock rw,
17 | }
18 |
--------------------------------------------------------------------------------
/contrib/busybox-init/S42yggdrasil:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | CONFFILE="/etc/yggdrasil.conf"
4 |
5 | genconf() {
6 | /usr/bin/yggdrasil -genconf > "$1"
7 | return $?
8 | }
9 |
10 | probetun() {
11 | modprobe tun
12 | return $?
13 | }
14 |
15 | start() {
16 | if [ ! -f "$CONFFILE" ]; then
17 | printf 'Generating configuration file: '
18 | if genconf "$CONFFILE"; then
19 | echo "OK"
20 | else
21 | echo "FAIL"
22 | return 1
23 | fi
24 | fi
25 |
26 | if [ ! -e /dev/net/tun ]; then
27 | printf 'Inserting TUN module: '
28 | if probetun; then
29 | echo "OK"
30 | else
31 | echo "FAIL"
32 | return 1
33 | fi
34 | fi
35 |
36 | printf 'Starting yggdrasil: '
37 | if start-stop-daemon -S -q -b -x /usr/bin/yggdrasil \
38 | -- -useconffile "$CONFFILE"; then
39 | echo "OK"
40 | else
41 | echo "FAIL"
42 | fi
43 | }
44 |
45 | stop() {
46 | printf "Stopping yggdrasil: "
47 | if start-stop-daemon -K -q -x /usr/bin/yggdrasil; then
48 | echo "OK"
49 | else
50 | echo "FAIL"
51 | fi
52 | }
53 |
54 | reload() {
55 | printf "Reloading yggdrasil: "
56 | if start-stop-daemon -K -q -s HUP -x /usr/bin/yggdrasil; then
57 | echo "OK"
58 | else
59 | echo "FAIL"
60 | start
61 | fi
62 | }
63 |
64 | restart() {
65 | stop
66 | start
67 | }
68 |
69 | case "$1" in
70 | start|stop|restart|reload)
71 | "$1";;
72 | *)
73 | echo "Usage: $0 {start|stop|restart|reload}"
74 | exit 1
75 | esac
76 |
77 | exit 0
78 |
--------------------------------------------------------------------------------
/contrib/deb/generate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This is a lazy script to create a .deb for Debian/Ubuntu. It installs
4 | # yggdrasil and enables it in systemd. You can give it the PKGARCH= argument
5 | # i.e. PKGARCH=i386 sh contrib/deb/generate.sh
6 |
7 | if [ `pwd` != `git rev-parse --show-toplevel` ]
8 | then
9 | echo "You should run this script from the top-level directory of the git repo"
10 | exit 1
11 | fi
12 |
13 | PKGBRANCH=$(basename `git name-rev --name-only HEAD`)
14 | PKGNAME=$(sh contrib/semver/name.sh)
15 | PKGVERSION=$(sh contrib/semver/version.sh --bare)
16 | PKGARCH=${PKGARCH-amd64}
17 | PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb
18 | PKGREPLACES=yggdrasil
19 |
20 | if [ $PKGBRANCH = "master" ]; then
21 | PKGREPLACES=yggdrasil-develop
22 | fi
23 |
24 | if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build
25 | elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build
26 | elif [ $PKGARCH = "mipsel" ]; then GOARCH=mipsle GOOS=linux ./build
27 | elif [ $PKGARCH = "mips" ]; then GOARCH=mips64 GOOS=linux ./build
28 | elif [ $PKGARCH = "armhf" ]; then GOARCH=arm GOOS=linux GOARM=6 ./build
29 | elif [ $PKGARCH = "arm64" ]; then GOARCH=arm64 GOOS=linux ./build
30 | elif [ $PKGARCH = "armel" ]; then GOARCH=arm GOOS=linux GOARM=5 ./build
31 | else
32 | echo "Specify PKGARCH=amd64,i386,mips,mipsel,armhf,arm64,armel"
33 | exit 1
34 | fi
35 |
36 | echo "Building $PKGFILE"
37 |
38 | mkdir -p /tmp/$PKGNAME/
39 | mkdir -p /tmp/$PKGNAME/debian/
40 | mkdir -p /tmp/$PKGNAME/usr/bin/
41 | mkdir -p /tmp/$PKGNAME/etc/systemd/system/
42 |
43 | cat > /tmp/$PKGNAME/debian/changelog << EOF
44 | Please see https://github.com/yggdrasil-network/yggdrasil-go/
45 | EOF
46 | echo 9 > /tmp/$PKGNAME/debian/compat
47 | cat > /tmp/$PKGNAME/debian/control << EOF
48 | Package: $PKGNAME
49 | Version: $PKGVERSION
50 | Section: contrib/net
51 | Priority: extra
52 | Architecture: $PKGARCH
53 | Replaces: $PKGREPLACES
54 | Conflicts: $PKGREPLACES
55 | Maintainer: Neil Alexander
56 | Description: Yggdrasil Network
57 | Yggdrasil is an early-stage implementation of a fully end-to-end encrypted IPv6
58 | network. It is lightweight, self-arranging, supported on multiple platforms and
59 | allows pretty much any IPv6-capable application to communicate securely with
60 | other Yggdrasil nodes.
61 | EOF
62 | cat > /tmp/$PKGNAME/debian/copyright << EOF
63 | Please see https://github.com/yggdrasil-network/yggdrasil-go/
64 | EOF
65 | cat > /tmp/$PKGNAME/debian/docs << EOF
66 | Please see https://github.com/yggdrasil-network/yggdrasil-go/
67 | EOF
68 | cat > /tmp/$PKGNAME/debian/install << EOF
69 | usr/bin/yggdrasil usr/bin
70 | usr/bin/yggdrasilctl usr/bin
71 | etc/systemd/system/*.service etc/systemd/system
72 | EOF
73 | cat > /tmp/$PKGNAME/debian/postinst << EOF
74 | #!/bin/sh
75 |
76 | if ! getent group yggdrasil 2>&1 > /dev/null; then
77 | groupadd --system --force yggdrasil || echo "Failed to create group 'yggdrasil' - please create it manually and reinstall"
78 | fi
79 |
80 | if [ -f /etc/yggdrasil.conf ];
81 | then
82 | mkdir -p /var/backups
83 | echo "Backing up configuration file to /var/backups/yggdrasil.conf.`date +%Y%m%d`"
84 | cp /etc/yggdrasil.conf /var/backups/yggdrasil.conf.`date +%Y%m%d`
85 | echo "Normalising and updating /etc/yggdrasil.conf"
86 | /usr/bin/yggdrasil -useconf -normaliseconf < /var/backups/yggdrasil.conf.`date +%Y%m%d` > /etc/yggdrasil.conf
87 | chgrp yggdrasil /etc/yggdrasil.conf
88 |
89 | if command -v systemctl >/dev/null; then
90 | systemctl daemon-reload >/dev/null || true
91 | systemctl enable yggdrasil || true
92 | systemctl start yggdrasil || true
93 | fi
94 | else
95 | echo "Generating initial configuration file /etc/yggdrasil.conf"
96 | echo "Please familiarise yourself with this file before starting Yggdrasil"
97 | sh -c 'umask 0027 && /usr/bin/yggdrasil -genconf > /etc/yggdrasil.conf'
98 | chgrp yggdrasil /etc/yggdrasil.conf
99 | fi
100 | EOF
101 | cat > /tmp/$PKGNAME/debian/prerm << EOF
102 | #!/bin/sh
103 | if command -v systemctl >/dev/null; then
104 | if systemctl is-active --quiet yggdrasil; then
105 | systemctl stop yggdrasil || true
106 | fi
107 | systemctl disable yggdrasil || true
108 | fi
109 | EOF
110 |
111 | cp yggdrasil /tmp/$PKGNAME/usr/bin/
112 | cp yggdrasilctl /tmp/$PKGNAME/usr/bin/
113 | cp contrib/systemd/*.service /tmp/$PKGNAME/etc/systemd/system/
114 |
115 | tar -czvf /tmp/$PKGNAME/data.tar.gz -C /tmp/$PKGNAME/ \
116 | usr/bin/yggdrasil usr/bin/yggdrasilctl \
117 | etc/systemd/system/yggdrasil.service \
118 | etc/systemd/system/yggdrasil-default-config.service
119 | tar -czvf /tmp/$PKGNAME/control.tar.gz -C /tmp/$PKGNAME/debian .
120 | echo 2.0 > /tmp/$PKGNAME/debian-binary
121 |
122 | ar -r $PKGFILE \
123 | /tmp/$PKGNAME/debian-binary \
124 | /tmp/$PKGNAME/control.tar.gz \
125 | /tmp/$PKGNAME/data.tar.gz
126 |
127 | rm -rf /tmp/$PKGNAME
128 |
--------------------------------------------------------------------------------
/contrib/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM docker.io/golang:alpine as builder
2 |
3 | COPY . /src
4 | WORKDIR /src
5 |
6 | ENV CGO_ENABLED=0
7 |
8 | RUN apk add git && ./build && go build -o /src/genkeys cmd/genkeys/main.go
9 |
10 | FROM docker.io/alpine
11 |
12 | COPY --from=builder /src/yggdrasil /usr/bin/yggdrasil
13 | COPY --from=builder /src/yggdrasilctl /usr/bin/yggdrasilctl
14 | COPY --from=builder /src/genkeys /usr/bin/genkeys
15 | COPY contrib/docker/entrypoint.sh /usr/bin/entrypoint.sh
16 |
17 | # RUN addgroup -g 1000 -S yggdrasil-network \
18 | # && adduser -u 1000 -S -g 1000 --home /etc/yggdrasil-network yggdrasil-network
19 | #
20 | # USER yggdrasil-network
21 | # TODO: Make running unprivileged work
22 |
23 | VOLUME [ "/etc/yggdrasil-network" ]
24 |
25 | ENTRYPOINT [ "/usr/bin/entrypoint.sh" ]
26 |
--------------------------------------------------------------------------------
/contrib/docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | CONF_DIR="/etc/yggdrasil-network"
6 |
7 | if [ ! -f "$CONF_DIR/config.conf" ]; then
8 | echo "generate $CONF_DIR/config.conf"
9 | yggdrasil --genconf > "$CONF_DIR/config.conf"
10 | fi
11 |
12 | yggdrasil --useconf < "$CONF_DIR/config.conf"
13 | exit $?
14 |
--------------------------------------------------------------------------------
/contrib/freebsd/yggdrasil:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Put the yggdrasil and yggdrasilctl binaries into /usr/local/bin
4 | # Then copy this script into /etc/rc.d/yggdrasil
5 | # Finally, run:
6 | # 1. chmod +x /etc/rc.d/yggdrasil /usr/local/bin/{yggdrasil,yggdrasilctl}
7 | # 2. echo "yggdrasil_enable=yes" >> /etc/rc.d
8 | # 3. service yggdrasil start
9 | #
10 | # PROVIDE: yggdrasil
11 | # REQUIRE: networking
12 | # KEYWORD:
13 |
14 | . /etc/rc.subr
15 |
16 | name="yggdrasil"
17 | rcvar="yggdrasil_enable"
18 |
19 | start_cmd="${name}_start"
20 | stop_cmd="${name}_stop"
21 |
22 | pidfile="/var/run/yggdrasil/${name}.pid"
23 | command="/usr/sbin/daemon"
24 | command_args="-P ${pidfile} -r -f ${yggdrasil_command}"
25 |
26 | yggdrasil_start()
27 | {
28 | test ! -x /usr/local/bin/yggdrasil && (
29 | logger -s -t yggdrasil "Warning: /usr/local/bin/yggdrasil is missing or not executable"
30 | logger -s -t yggdrasil "Copy the yggdrasil binary into /usr/local/bin and then chmod +x /usr/local/bin/yggdrasil"
31 | return 1
32 | )
33 |
34 | test ! -f /etc/yggdrasil.conf && (
35 | logger -s -t yggdrasil "Generating new configuration file into /etc/yggdrasil.conf"
36 | /usr/local/bin/yggdrasil -genconf > /etc/yggdrasil.conf
37 | )
38 |
39 | tap_path="$(cat /etc/yggdrasil.conf | egrep -o '/dev/tap[0-9]{1,2}$')"
40 | tap_name="$(echo -n ${tap_path} | tr -d '/dev/')"
41 |
42 | /sbin/ifconfig ${tap_name} >/dev/null 2>&1 || (
43 | logger -s -t yggdrasil "Creating ${tap_name} adapter"
44 | /sbin/ifconfig ${tap_name} create || logger -s -t yggdrasil "Failed to create ${tap_name} adapter"
45 | )
46 |
47 | test ! -d /var/run/yggdrasil && mkdir -p /var/run/yggdrasil
48 |
49 | logger -s -t yggdrasil "Starting yggdrasil"
50 | ${command} ${command_args} /usr/local/bin/yggdrasil -useconffile /etc/yggdrasil.conf \
51 | 1>/var/log/yggdrasil.stdout.log \
52 | 2>/var/log/yggdrasil.stderr.log &
53 | }
54 |
55 | yggdrasil_stop()
56 | {
57 | logger -s -t yggdrasil "Stopping yggdrasil"
58 | test -f /var/run/yggdrasil/${name}.pid && kill -TERM $(cat /var/run/yggdrasil/${name}.pid)
59 |
60 | tap_path="$(cat /etc/yggdrasil.conf | grep /dev/tap | egrep -o '/dev/.*$')"
61 | tap_name="$(echo -n ${tap_path} | tr -d '/dev/')"
62 |
63 | /sbin/ifconfig ${tap_name} >/dev/null 2>&1 && (
64 | logger -s -t yggdrasil "Destroying ${tap_name} adapter"
65 | /sbin/ifconfig ${tap_name} destroy || logger -s -t yggdrasil "Failed to destroy ${tap_name} adapter"
66 | )
67 | }
68 |
69 | load_rc_config $name
70 | : ${yggdrasil_enable:=no}
71 |
72 | run_rc_command "$1"
73 |
--------------------------------------------------------------------------------
/contrib/logo/ygg-neilalexander.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
158 |
--------------------------------------------------------------------------------
/contrib/macos/create-pkg.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Check if xar and mkbom are available
4 | command -v xar >/dev/null 2>&1 || (
5 | echo "Building xar"
6 | sudo apt-get install libxml2-dev libssl1.0-dev zlib1g-dev -y
7 | mkdir -p /tmp/xar && cd /tmp/xar
8 | git clone https://github.com/mackyle/xar && cd xar/xar
9 | (sh autogen.sh && make && sudo make install) || (echo "Failed to build xar"; exit 1)
10 | )
11 | command -v mkbom >/dev/null 2>&1 || (
12 | echo "Building mkbom"
13 | mkdir -p /tmp/mkbom && cd /tmp/mkbom
14 | git clone https://github.com/hogliux/bomutils && cd bomutils
15 | sudo make install || (echo "Failed to build mkbom"; exit 1)
16 | )
17 |
18 | # Build Yggdrasil
19 | echo "running GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build"
20 | GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build
21 |
22 | # Check if we can find the files we need - they should
23 | # exist if you are running this script from the root of
24 | # the yggdrasil-go repo and you have ran ./build
25 | test -f yggdrasil || (echo "yggdrasil binary not found"; exit 1)
26 | test -f yggdrasilctl || (echo "yggdrasilctl binary not found"; exit 1)
27 | test -f contrib/macos/yggdrasil.plist || (echo "contrib/macos/yggdrasil.plist not found"; exit 1)
28 | test -f contrib/semver/version.sh || (echo "contrib/semver/version.sh not found"; exit 1)
29 |
30 | # Delete the pkgbuild folder if it already exists
31 | test -d pkgbuild && rm -rf pkgbuild
32 |
33 | # Create our folder structure
34 | mkdir -p pkgbuild/scripts
35 | mkdir -p pkgbuild/flat/base.pkg
36 | mkdir -p pkgbuild/flat/Resources/en.lproj
37 | mkdir -p pkgbuild/root/usr/local/bin
38 | mkdir -p pkgbuild/root/Library/LaunchDaemons
39 |
40 | # Copy package contents into the pkgbuild root
41 | cp yggdrasil pkgbuild/root/usr/local/bin
42 | cp yggdrasilctl pkgbuild/root/usr/local/bin
43 | cp contrib/macos/yggdrasil.plist pkgbuild/root/Library/LaunchDaemons
44 |
45 | # Create the postinstall script
46 | cat > pkgbuild/scripts/postinstall << EOF
47 | #!/bin/sh
48 |
49 | # Normalise the config if it exists, generate it if it doesn't
50 | if [ -f /etc/yggdrasil.conf ];
51 | then
52 | mkdir -p /Library/Preferences/Yggdrasil
53 | echo "Backing up configuration file to /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d`"
54 | cp /etc/yggdrasil.conf /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d`
55 | echo "Normalising /etc/yggdrasil.conf"
56 | /usr/local/bin/yggdrasil -useconffile /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d` -normaliseconf > /etc/yggdrasil.conf
57 | else
58 | /usr/local/bin/yggdrasil -genconf > /etc/yggdrasil.conf
59 | fi
60 |
61 | # Unload existing Yggdrasil launchd service, if possible
62 | test -f /Library/LaunchDaemons/yggdrasil.plist && (launchctl unload /Library/LaunchDaemons/yggdrasil.plist || true)
63 |
64 | # Load Yggdrasil launchd service and start Yggdrasil
65 | launchctl load /Library/LaunchDaemons/yggdrasil.plist
66 | EOF
67 |
68 | # Set execution permissions
69 | chmod +x pkgbuild/scripts/postinstall
70 | chmod +x pkgbuild/root/usr/local/bin/yggdrasil
71 | chmod +x pkgbuild/root/usr/local/bin/yggdrasilctl
72 |
73 | # Pack payload and scripts
74 | ( cd pkgbuild/scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > pkgbuild/flat/base.pkg/Scripts
75 | ( cd pkgbuild/root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > pkgbuild/flat/base.pkg/Payload
76 |
77 | # Work out metadata for the package info
78 | PKGNAME=$(sh contrib/semver/name.sh)
79 | PKGVERSION=$(sh contrib/semver/version.sh --bare)
80 | PKGARCH=${PKGARCH-amd64}
81 | PAYLOADSIZE=$(( $(wc -c pkgbuild/flat/base.pkg/Payload | awk '{ print $1 }') / 1024 ))
82 | [ "$PKGARCH" = "amd64" ] && PKGHOSTARCH="x86_64" || PKGHOSTARCH=${PKGARCH}
83 |
84 | # Create the PackageInfo file
85 | cat > pkgbuild/flat/base.pkg/PackageInfo << EOF
86 |
87 |
88 |
89 |
90 |
91 |
92 | EOF
93 |
94 | # Create the BOM
95 | ( cd pkgbuild && mkbom root flat/base.pkg/Bom )
96 |
97 | # Create the Distribution file
98 | cat > pkgbuild/flat/Distribution << EOF
99 |
100 |
101 | Yggdrasil (${PKGNAME}-${PKGVERSION})
102 |
103 |
104 |
105 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | #base.pkg
123 |
124 | EOF
125 |
126 | # Finally pack the .pkg
127 | ( cd pkgbuild/flat && xar --compression none -cf "../../${PKGNAME}-${PKGVERSION}-macos-${PKGARCH}.pkg" * )
128 |
--------------------------------------------------------------------------------
/contrib/macos/yggdrasil.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Label
6 | yggdrasil
7 | ProgramArguments
8 |
9 | sh
10 | -c
11 | /usr/local/bin/yggdrasil -useconffile /etc/yggdrasil.conf
12 |
13 | KeepAlive
14 |
15 | RunAtLoad
16 |
17 | ProcessType
18 | Interactive
19 | StandardOutPath
20 | /tmp/yggdrasil.stdout.log
21 | StandardErrorPath
22 | /tmp/yggdrasil.stderr.log
23 |
24 |
25 |
--------------------------------------------------------------------------------
/contrib/mobile/build:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ef
4 |
5 | [ ! -d contrib/mobile ] && (echo "Must run ./contrib/mobile/build [-i] [-a] from the repository top level folder"; exit 1)
6 |
7 | PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version}
8 | PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)}
9 | PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
10 |
11 | LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
12 | ARGS="-v"
13 |
14 | while getopts "aitc:l:d" option
15 | do
16 | case "$option"
17 | in
18 | i) IOS=true;;
19 | a) ANDROID=true;;
20 | t) TABLES=true;;
21 | c) GCFLAGS="$GCFLAGS $OPTARG";;
22 | l) LDFLAGS="$LDFLAGS $OPTARG";;
23 | d) ARGS="$ARGS -tags debug" DEBUG=true;;
24 | esac
25 | done
26 |
27 | if [ -z $TABLES ] && [ -z $DEBUG ]; then
28 | LDFLAGS="$LDFLAGS -s -w"
29 | fi
30 |
31 | if [ ! $IOS ] && [ ! $ANDROID ]; then
32 | echo "Must specify -a (Android), -i (iOS) or both"
33 | exit 1
34 | fi
35 |
36 | if [ $IOS ]; then
37 | echo "Building framework for iOS"
38 | go get golang.org/x/mobile/bind
39 | gomobile bind \
40 | -target ios -tags mobile -o Yggdrasil.xcframework \
41 | -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
42 | ./contrib/mobile ./src/config;
43 | fi
44 |
45 | if [ $ANDROID ]; then
46 | echo "Building aar for Android"
47 | go get golang.org/x/mobile/bind
48 | gomobile bind \
49 | -target android -tags mobile -o yggdrasil.aar \
50 | -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
51 | ./contrib/mobile ./src/config;
52 | fi
53 |
--------------------------------------------------------------------------------
/contrib/mobile/mobile.go:
--------------------------------------------------------------------------------
1 | package mobile
2 |
3 | import (
4 | "encoding/hex"
5 | "encoding/json"
6 | "fmt"
7 | "net"
8 | "regexp"
9 |
10 | "github.com/gologme/log"
11 |
12 | "github.com/yggdrasil-network/yggdrasil-go/src/address"
13 | "github.com/yggdrasil-network/yggdrasil-go/src/config"
14 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
15 | "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
16 | "github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc"
17 | "github.com/yggdrasil-network/yggdrasil-go/src/multicast"
18 | "github.com/yggdrasil-network/yggdrasil-go/src/version"
19 |
20 | _ "golang.org/x/mobile/bind"
21 | )
22 |
23 | // Yggdrasil mobile package is meant to "plug the gap" for mobile support, as
24 | // Gomobile will not create headers for Swift/Obj-C etc if they have complex
25 | // (non-native) types. Therefore for iOS we will expose some nice simple
26 | // functions. Note that in the case of iOS we handle reading/writing to/from TUN
27 | // in Swift therefore we use the "dummy" TUN interface instead.
28 | type Yggdrasil struct {
29 | core *core.Core
30 | iprwc *ipv6rwc.ReadWriteCloser
31 | config *config.NodeConfig
32 | multicast *multicast.Multicast
33 | log MobileLogger
34 | }
35 |
36 | // StartAutoconfigure starts a node with a randomly generated config
37 | func (m *Yggdrasil) StartAutoconfigure() error {
38 | return m.StartJSON([]byte("{}"))
39 | }
40 |
41 | // StartJSON starts a node with the given JSON config. You can get JSON config
42 | // (rather than HJSON) by using the GenerateConfigJSON() function
43 | func (m *Yggdrasil) StartJSON(configjson []byte) error {
44 | logger := log.New(m.log, "", 0)
45 | logger.EnableLevel("error")
46 | logger.EnableLevel("warn")
47 | logger.EnableLevel("info")
48 | m.config = defaults.GenerateConfig()
49 | if err := json.Unmarshal(configjson, &m.config); err != nil {
50 | return err
51 | }
52 | // Setup the Yggdrasil node itself.
53 | {
54 | sk, err := hex.DecodeString(m.config.PrivateKey)
55 | if err != nil {
56 | panic(err)
57 | }
58 | options := []core.SetupOption{}
59 | for _, peer := range m.config.Peers {
60 | options = append(options, core.Peer{URI: peer})
61 | }
62 | for intf, peers := range m.config.InterfacePeers {
63 | for _, peer := range peers {
64 | options = append(options, core.Peer{URI: peer, SourceInterface: intf})
65 | }
66 | }
67 | for _, allowed := range m.config.AllowedPublicKeys {
68 | k, err := hex.DecodeString(allowed)
69 | if err != nil {
70 | panic(err)
71 | }
72 | options = append(options, core.AllowedPublicKey(k[:]))
73 | }
74 | m.core, err = core.New(sk[:], logger, options...)
75 | if err != nil {
76 | panic(err)
77 | }
78 | }
79 |
80 | // Setup the multicast module.
81 | if len(m.config.MulticastInterfaces) > 0 {
82 | var err error
83 | options := []multicast.SetupOption{}
84 | for _, intf := range m.config.MulticastInterfaces {
85 | options = append(options, multicast.MulticastInterface{
86 | Regex: regexp.MustCompile(intf.Regex),
87 | Beacon: intf.Beacon,
88 | Listen: intf.Listen,
89 | Port: intf.Port,
90 | Priority: intf.Priority,
91 | })
92 | }
93 | m.multicast, err = multicast.New(m.core, logger, options...)
94 | if err != nil {
95 | logger.Errorln("An error occurred starting multicast:", err)
96 | }
97 | }
98 |
99 | mtu := m.config.IfMTU
100 | m.iprwc = ipv6rwc.NewReadWriteCloser(m.core)
101 | if m.iprwc.MaxMTU() < mtu {
102 | mtu = m.iprwc.MaxMTU()
103 | }
104 | m.iprwc.SetMTU(mtu)
105 | return nil
106 | }
107 |
108 | // Send sends a packet to Yggdrasil. It should be a fully formed
109 | // IPv6 packet
110 | func (m *Yggdrasil) Send(p []byte) error {
111 | if m.iprwc == nil {
112 | return nil
113 | }
114 | _, _ = m.iprwc.Write(p)
115 | return nil
116 | }
117 |
118 | // Recv waits for and reads a packet coming from Yggdrasil. It
119 | // will be a fully formed IPv6 packet
120 | func (m *Yggdrasil) Recv() ([]byte, error) {
121 | if m.iprwc == nil {
122 | return nil, nil
123 | }
124 | var buf [65535]byte
125 | n, _ := m.iprwc.Read(buf[:])
126 | return buf[:n], nil
127 | }
128 |
129 | // Stop the mobile Yggdrasil instance
130 | func (m *Yggdrasil) Stop() error {
131 | logger := log.New(m.log, "", 0)
132 | logger.EnableLevel("info")
133 | logger.Infof("Stop the mobile Yggdrasil instance %s", "")
134 | if err := m.multicast.Stop(); err != nil {
135 | return err
136 | }
137 | m.core.Stop()
138 | return nil
139 | }
140 |
141 | // GenerateConfigJSON generates mobile-friendly configuration in JSON format
142 | func GenerateConfigJSON() []byte {
143 | nc := defaults.GenerateConfig()
144 | nc.IfName = "none"
145 | if json, err := json.Marshal(nc); err == nil {
146 | return json
147 | }
148 | return nil
149 | }
150 |
151 | // GetAddressString gets the node's IPv6 address
152 | func (m *Yggdrasil) GetAddressString() string {
153 | ip := m.core.Address()
154 | return ip.String()
155 | }
156 |
157 | // GetSubnetString gets the node's IPv6 subnet in CIDR notation
158 | func (m *Yggdrasil) GetSubnetString() string {
159 | subnet := m.core.Subnet()
160 | return subnet.String()
161 | }
162 |
163 | // GetPublicKeyString gets the node's public key in hex form
164 | func (m *Yggdrasil) GetPublicKeyString() string {
165 | return hex.EncodeToString(m.core.GetSelf().Key)
166 | }
167 |
168 | // GetCoordsString gets the node's coordinates
169 | func (m *Yggdrasil) GetCoordsString() string {
170 | return fmt.Sprintf("%v", m.core.GetSelf().Coords)
171 | }
172 |
173 | func (m *Yggdrasil) GetPeersJSON() (result string) {
174 | peers := []struct {
175 | core.PeerInfo
176 | IP string
177 | }{}
178 | for _, v := range m.core.GetPeers() {
179 | a := address.AddrForKey(v.Key)
180 | ip := net.IP(a[:]).String()
181 | peers = append(peers, struct {
182 | core.PeerInfo
183 | IP string
184 | }{
185 | PeerInfo: v,
186 | IP: ip,
187 | })
188 | }
189 | if res, err := json.Marshal(peers); err == nil {
190 | return string(res)
191 | } else {
192 | return "{}"
193 | }
194 | }
195 |
196 | func (m *Yggdrasil) GetDHTJSON() (result string) {
197 | if res, err := json.Marshal(m.core.GetDHT()); err == nil {
198 | return string(res)
199 | } else {
200 | return "{}"
201 | }
202 | }
203 |
204 | // GetMTU returns the configured node MTU. This must be called AFTER Start.
205 | func (m *Yggdrasil) GetMTU() int {
206 | return int(m.core.MTU())
207 | }
208 |
209 | func GetVersion() string {
210 | return version.BuildVersion()
211 | }
212 |
--------------------------------------------------------------------------------
/contrib/mobile/mobile_android.go:
--------------------------------------------------------------------------------
1 | //go:build android
2 | // +build android
3 |
4 | package mobile
5 |
6 | import "log"
7 |
8 | type MobileLogger struct{}
9 |
10 | func (nsl MobileLogger) Write(p []byte) (n int, err error) {
11 | log.Println(string(p))
12 | return len(p), nil
13 | }
14 |
--------------------------------------------------------------------------------
/contrib/mobile/mobile_ios.go:
--------------------------------------------------------------------------------
1 | //go:build ios
2 | // +build ios
3 |
4 | package mobile
5 |
6 | /*
7 | #cgo CFLAGS: -x objective-c
8 | #cgo LDFLAGS: -framework Foundation
9 | #import
10 | void Log(const char *text) {
11 | NSString *nss = [NSString stringWithUTF8String:text];
12 | NSLog(@"%@", nss);
13 | }
14 | */
15 | import "C"
16 | import (
17 | "unsafe"
18 | )
19 |
20 | type MobileLogger struct {
21 | }
22 |
23 | func (nsl MobileLogger) Write(p []byte) (n int, err error) {
24 | p = append(p, 0)
25 | cstr := (*C.char)(unsafe.Pointer(&p[0]))
26 | C.Log(cstr)
27 | return len(p), nil
28 | }
29 |
--------------------------------------------------------------------------------
/contrib/mobile/mobile_other.go:
--------------------------------------------------------------------------------
1 | //go:build !android && !ios
2 | // +build !android,!ios
3 |
4 | package mobile
5 |
6 | import "fmt"
7 |
8 | type MobileLogger struct {
9 | }
10 |
11 | func (nsl MobileLogger) Write(p []byte) (n int, err error) {
12 | fmt.Print(string(p))
13 | return len(p), nil
14 | }
15 |
--------------------------------------------------------------------------------
/contrib/mobile/mobile_test.go:
--------------------------------------------------------------------------------
1 | package mobile
2 |
3 | import "testing"
4 |
5 | func TestStartYggdrasil(t *testing.T) {
6 | ygg := &Yggdrasil{}
7 | if err := ygg.StartAutoconfigure(); err != nil {
8 | t.Fatalf("Failed to start Yggdrasil: %s", err)
9 | }
10 | t.Log("Address:", ygg.GetAddressString())
11 | t.Log("Subnet:", ygg.GetSubnetString())
12 | t.Log("Coords:", ygg.GetCoordsString())
13 | if err := ygg.Stop(); err != nil {
14 | t.Fatalf("Failed to stop Yggdrasil: %s", err)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/contrib/msi/build-msi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This script generates an MSI file for Yggdrasil for a given architecture. It
4 | # needs to run on Windows within MSYS2 and Go 1.17 or later must be installed on
5 | # the system and within the PATH. This is ran currently by GitHub Actions (see
6 | # the workflows in the repository).
7 | #
8 | # Author: Neil Alexander
9 |
10 | # Get arch from command line if given
11 | PKGARCH=$1
12 | if [ "${PKGARCH}" == "" ];
13 | then
14 | echo "tell me the architecture: x86, x64, arm or arm64"
15 | exit 1
16 | fi
17 |
18 | # Download the wix tools!
19 | if [ ! -d wixbin ];
20 | then
21 | curl -LO https://wixtoolset.org/downloads/v3.14.0.3910/wix314-binaries.zip
22 | if [ `md5sum wix314-binaries.zip | cut -f 1 -d " "` != "34f655cf108086838dd5a76d4318063b" ];
23 | then
24 | echo "wix package didn't match expected checksum"
25 | exit 1
26 | fi
27 | mkdir -p wixbin
28 | unzip -o wix314-binaries.zip -d wixbin || (
29 | echo "failed to unzip WiX"
30 | exit 1
31 | )
32 | fi
33 |
34 | # Build Yggdrasil!
35 | [ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./build
36 | [ "${PKGARCH}" == "x86" ] && GOOS=windows GOARCH=386 CGO_ENABLED=0 ./build
37 | [ "${PKGARCH}" == "arm" ] && GOOS=windows GOARCH=arm CGO_ENABLED=0 ./build
38 | [ "${PKGARCH}" == "arm64" ] && GOOS=windows GOARCH=arm64 CGO_ENABLED=0 ./build
39 |
40 | # Create the postinstall script
41 | cat > updateconfig.bat << EOF
42 | if not exist %ALLUSERSPROFILE%\\Yggdrasil (
43 | mkdir %ALLUSERSPROFILE%\\Yggdrasil
44 | )
45 | if not exist %ALLUSERSPROFILE%\\Yggdrasil\\yggdrasil.conf (
46 | if exist yggdrasil.exe (
47 | yggdrasil.exe -genconf > %ALLUSERSPROFILE%\\Yggdrasil\\yggdrasil.conf
48 | )
49 | )
50 | EOF
51 |
52 | # Work out metadata for the package info
53 | PKGNAME=$(sh contrib/semver/name.sh)
54 | PKGVERSION=$(sh contrib/msi/msversion.sh --bare)
55 | PKGVERSIONMS=$(echo $PKGVERSION | tr - .)
56 | ([ "${PKGARCH}" == "x64" ] || [ "${PKGARCH}" == "arm64" ]) && \
57 | PKGGUID="77757838-1a23-40a5-a720-c3b43e0260cc" PKGINSTFOLDER="ProgramFiles64Folder" || \
58 | PKGGUID="54a3294e-a441-4322-aefb-3bb40dd022bb" PKGINSTFOLDER="ProgramFilesFolder"
59 |
60 | # Download the Wintun driver
61 | if [ ! -d wintun ];
62 | then
63 | curl -o wintun.zip https://www.wintun.net/builds/wintun-0.14.1.zip
64 | unzip wintun.zip
65 | fi
66 | if [ $PKGARCH = "x64" ]; then
67 | PKGWINTUNDLL=wintun/bin/amd64/wintun.dll
68 | elif [ $PKGARCH = "x86" ]; then
69 | PKGWINTUNDLL=wintun/bin/x86/wintun.dll
70 | elif [ $PKGARCH = "arm" ]; then
71 | PKGWINTUNDLL=wintun/bin/arm/wintun.dll
72 | elif [ $PKGARCH = "arm64" ]; then
73 | PKGWINTUNDLL=wintun/bin/arm64/wintun.dll
74 | else
75 | echo "wasn't sure which architecture to get wintun for"
76 | exit 1
77 | fi
78 |
79 | if [ $PKGNAME != "master" ]; then
80 | PKGDISPLAYNAME="Yggdrasil Network (${PKGNAME} branch)"
81 | else
82 | PKGDISPLAYNAME="Yggdrasil Network"
83 | fi
84 |
85 | # Generate the wix.xml file
86 | cat > wix.xml << EOF
87 |
88 |
89 |
97 |
98 |
109 |
110 |
112 |
113 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
130 |
131 |
136 |
137 |
149 |
150 |
156 |
157 |
158 |
159 |
165 |
166 |
167 |
168 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
192 |
193 |
194 |
197 | NOT Installed AND NOT REMOVE
198 |
199 |
200 |
201 |
202 |
203 | EOF
204 |
205 | # Generate the MSI
206 | CANDLEFLAGS="-nologo"
207 | LIGHTFLAGS="-nologo -spdb -sice:ICE71 -sice:ICE61"
208 | wixbin/candle $CANDLEFLAGS -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj -arch ${PKGARCH} wix.xml && \
209 | wixbin/light $LIGHTFLAGS -ext WixUtilExtension.dll -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.msi ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj
210 |
--------------------------------------------------------------------------------
/contrib/msi/msversion.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Get the last tag
4 | TAG=$(git describe --abbrev=0 --tags --match="v[0-9]*\.[0-9]*\.[0-9]*" 2>/dev/null)
5 |
6 | # Did getting the tag succeed?
7 | if [ $? != 0 ] || [ -z "$TAG" ]; then
8 | printf -- "unknown"
9 | exit 0
10 | fi
11 |
12 | # Get the current branch
13 | BRANCH=$(git symbolic-ref -q HEAD --short 2>/dev/null)
14 |
15 | # Did getting the branch succeed?
16 | if [ $? != 0 ] || [ -z "$BRANCH" ]; then
17 | BRANCH="master"
18 | fi
19 |
20 | # Split out into major, minor and patch numbers
21 | MAJOR=$(echo $TAG | cut -c 2- | cut -d "." -f 1)
22 | MINOR=$(echo $TAG | cut -c 2- | cut -d "." -f 2)
23 | PATCH=$(echo $TAG | cut -c 2- | cut -d "." -f 3 | awk -F"rc" '{print $1}')
24 |
25 | # Output in the desired format
26 | if [ $((PATCH)) -eq 0 ]; then
27 | printf '%s%d.%d' "$PREPEND" "$((MAJOR))" "$((MINOR))"
28 | else
29 | printf '%s%d.%d.%d' "$PREPEND" "$((MAJOR))" "$((MINOR))" "$((PATCH))"
30 | fi
31 |
32 | # Add the build tag on non-master branches
33 | if [ "$BRANCH" != "master" ]; then
34 | BUILD=$(git rev-list --count $TAG..HEAD 2>/dev/null)
35 |
36 | # Did getting the count of commits since the tag succeed?
37 | if [ $? != 0 ] || [ -z "$BUILD" ]; then
38 | printf -- "-unknown"
39 | exit 0
40 | fi
41 |
42 | # Is the build greater than zero?
43 | if [ $((BUILD)) -gt 0 ]; then
44 | printf -- "-%04d" "$((BUILD))"
45 | fi
46 | fi
--------------------------------------------------------------------------------
/contrib/openrc/yggdrasil:
--------------------------------------------------------------------------------
1 | #!/sbin/openrc-run
2 |
3 | description="An experiment in scalable routing as an encrypted IPv6 overlay network."
4 |
5 | CONFFILE="/etc/yggdrasil.conf"
6 | pidfile="/run/${RC_SVCNAME}.pid"
7 |
8 | command="/usr/bin/yggdrasil"
9 | extra_started_commands="reload"
10 |
11 | depend() {
12 | use net dns logger
13 | }
14 |
15 | start_pre() {
16 | if [ ! -f "${CONFFILE}" ]; then
17 | ebegin "Generating new configuration file into ${CONFFILE}"
18 | if ! eval ${command} -genconf > ${CONFFILE}; then
19 | eerror "Failed to generate configuration file"
20 | exit 1
21 | fi
22 | fi
23 |
24 | if [ ! -e /dev/net/tun ]; then
25 | ebegin "Inserting TUN module"
26 | if ! modprobe tun; then
27 | eerror "Failed to insert TUN kernel module"
28 | exit 1
29 | fi
30 | fi
31 | }
32 |
33 | start() {
34 | ebegin "Starting ${RC_SVCNAME}"
35 | start-stop-daemon --start --quiet \
36 | --pidfile "${pidfile}" \
37 | --make-pidfile \
38 | --background \
39 | --stdout /var/log/yggdrasil.stdout.log \
40 | --stderr /var/log/yggdrasil.stderr.log \
41 | --exec "${command}" -- -useconffile "${CONFFILE}"
42 | eend $?
43 | }
44 |
45 | reload() {
46 | ebegin "Reloading ${RC_SVCNAME}"
47 | start-stop-daemon --signal HUP --pidfile "${pidfile}"
48 | eend $?
49 | }
50 |
51 | stop() {
52 | ebegin "Stopping ${RC_SVCNAME}"
53 | start-stop-daemon --stop --pidfile "${pidfile}" --exec "${command}"
54 | eend $?
55 | }
56 |
--------------------------------------------------------------------------------
/contrib/semver/name.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Get the current branch name
4 | BRANCH="$GITHUB_REF_NAME"
5 | if [ -z "$BRANCH" ]; then
6 | BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
7 | fi
8 |
9 | if [ $? != 0 ] || [ -z "$BRANCH" ]; then
10 | printf "yggdrasil"
11 | exit 0
12 | fi
13 |
14 | # Remove "/" characters from the branch name if present
15 | BRANCH=$(echo $BRANCH | tr -d "/")
16 |
17 | # Check if the branch name is not master
18 | if [ "$BRANCH" = "master" ]; then
19 | printf "yggdrasil"
20 | exit 0
21 | fi
22 |
23 | # If it is something other than master, append it
24 | printf "yggdrasil-%s" "$BRANCH"
25 |
--------------------------------------------------------------------------------
/contrib/semver/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | case "$*" in
4 | *--bare*)
5 | # Remove the "v" prefix
6 | git describe --tags --match="v[0-9]*\.[0-9]*\.[0-9]*" | cut -c 2-
7 | ;;
8 | *)
9 | git describe --tags --match="v[0-9]*\.[0-9]*\.[0-9]*"
10 | ;;
11 | esac
12 |
--------------------------------------------------------------------------------
/contrib/systemd/yggdrasil-default-config.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=yggdrasil default config generator
3 | ConditionPathExists=|!/etc/yggdrasil.conf
4 | ConditionFileNotEmpty=|!/etc/yggdrasil.conf
5 | Wants=local-fs.target
6 | After=local-fs.target
7 |
8 | [Service]
9 | Type=oneshot
10 | Group=yggdrasil
11 | StandardOutput=file:/etc/yggdrasil.conf
12 | ExecStart=/usr/bin/yggdrasil -genconf
13 | ExecStartPost=/usr/bin/chmod 0640 /etc/yggdrasil.conf
14 |
--------------------------------------------------------------------------------
/contrib/systemd/yggdrasil.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=yggdrasil
3 | Wants=network-online.target
4 | Wants=yggdrasil-default-config.service
5 | After=network-online.target
6 | After=yggdrasil-default-config.service
7 |
8 | [Service]
9 | Group=yggdrasil
10 | ProtectHome=true
11 | ProtectSystem=true
12 | SyslogIdentifier=yggdrasil
13 | CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
14 | ExecStartPre=+-/sbin/modprobe tun
15 | ExecStart=/usr/bin/yggdrasil -useconffile /etc/yggdrasil.conf
16 | ExecReload=/bin/kill -HUP $MAINPID
17 | Restart=always
18 | TimeoutStopSec=5
19 |
20 | [Install]
21 | WantedBy=multi-user.target
22 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/LICENSE:
--------------------------------------------------------------------------------
1 | This software is released into the public domain. As such, it can be
2 | used under the Unlicense or CC0 public domain dedications.
3 |
4 |
5 |
6 | The Unlicense
7 |
8 | This is free and unencumbered software released into the public domain.
9 |
10 | Anyone is free to copy, modify, publish, use, compile, sell, or
11 | distribute this software, either in source code form or as a compiled
12 | binary, for any purpose, commercial or non-commercial, and by any
13 | means.
14 |
15 | In jurisdictions that recognize copyright laws, the author or authors
16 | of this software dedicate any and all copyright interest in the
17 | software to the public domain. We make this dedication for the benefit
18 | of the public at large and to the detriment of our heirs and
19 | successors. We intend this dedication to be an overt act of
20 | relinquishment in perpetuity of all present and future rights to this
21 | software under copyright law.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 | OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | For more information, please refer to
32 |
33 |
34 |
35 | CC0 1.0 Universal
36 |
37 | Statement of Purpose
38 |
39 | The laws of most jurisdictions throughout the world automatically confer
40 | exclusive Copyright and Related Rights (defined below) upon the creator and
41 | subsequent owner(s) (each and all, an "owner") of an original work of
42 | authorship and/or a database (each, a "Work").
43 |
44 | Certain owners wish to permanently relinquish those rights to a Work for the
45 | purpose of contributing to a commons of creative, cultural and scientific
46 | works ("Commons") that the public can reliably and without fear of later
47 | claims of infringement build upon, modify, incorporate in other works, reuse
48 | and redistribute as freely as possible in any form whatsoever and for any
49 | purposes, including without limitation commercial purposes. These owners may
50 | contribute to the Commons to promote the ideal of a free culture and the
51 | further production of creative, cultural and scientific works, or to gain
52 | reputation or greater distribution for their Work in part through the use and
53 | efforts of others.
54 |
55 | For these and/or other purposes and motivations, and without any expectation
56 | of additional consideration or compensation, the person associating CC0 with a
57 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
58 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
59 | and publicly distribute the Work under its terms, with knowledge of his or her
60 | Copyright and Related Rights in the Work and the meaning and intended legal
61 | effect of CC0 on those rights.
62 |
63 | 1. Copyright and Related Rights. A Work made available under CC0 may be
64 | protected by copyright and related or neighboring rights ("Copyright and
65 | Related Rights"). Copyright and Related Rights include, but are not limited
66 | to, the following:
67 |
68 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
69 | and translate a Work;
70 |
71 | ii. moral rights retained by the original author(s) and/or performer(s);
72 |
73 | iii. publicity and privacy rights pertaining to a person's image or likeness
74 | depicted in a Work;
75 |
76 | iv. rights protecting against unfair competition in regards to a Work,
77 | subject to the limitations in paragraph 4(a), below;
78 |
79 | v. rights protecting the extraction, dissemination, use and reuse of data in
80 | a Work;
81 |
82 | vi. database rights (such as those arising under Directive 96/9/EC of the
83 | European Parliament and of the Council of 11 March 1996 on the legal
84 | protection of databases, and under any national implementation thereof,
85 | including any amended or successor version of such directive); and
86 |
87 | vii. other similar, equivalent or corresponding rights throughout the world
88 | based on applicable law or treaty, and any national implementations thereof.
89 |
90 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
91 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
92 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
93 | and Related Rights and associated claims and causes of action, whether now
94 | known or unknown (including existing as well as future claims and causes of
95 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
96 | duration provided by applicable law or treaty (including future time
97 | extensions), (iii) in any current or future medium and for any number of
98 | copies, and (iv) for any purpose whatsoever, including without limitation
99 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
100 | the Waiver for the benefit of each member of the public at large and to the
101 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
102 | shall not be subject to revocation, rescission, cancellation, termination, or
103 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
104 | by the public as contemplated by Affirmer's express Statement of Purpose.
105 |
106 | 3. Public License Fallback. Should any part of the Waiver for any reason be
107 | judged legally invalid or ineffective under applicable law, then the Waiver
108 | shall be preserved to the maximum extent permitted taking into account
109 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
110 | is so judged Affirmer hereby grants to each affected person a royalty-free,
111 | non transferable, non sublicensable, non exclusive, irrevocable and
112 | unconditional license to exercise Affirmer's Copyright and Related Rights in
113 | the Work (i) in all territories worldwide, (ii) for the maximum duration
114 | provided by applicable law or treaty (including future time extensions), (iii)
115 | in any current or future medium and for any number of copies, and (iv) for any
116 | purpose whatsoever, including without limitation commercial, advertising or
117 | promotional purposes (the "License"). The License shall be deemed effective as
118 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
119 | License for any reason be judged legally invalid or ineffective under
120 | applicable law, such partial invalidity or ineffectiveness shall not
121 | invalidate the remainder of the License, and in such case Affirmer hereby
122 | affirms that he or she will not (i) exercise any of his or her remaining
123 | Copyright and Related Rights in the Work or (ii) assert any associated claims
124 | and causes of action with respect to the Work, in either case contrary to
125 | Affirmer's express Statement of Purpose.
126 |
127 | 4. Limitations and Disclaimers.
128 |
129 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
130 | surrendered, licensed or otherwise affected by this document.
131 |
132 | b. Affirmer offers the Work as-is and makes no representations or warranties
133 | of any kind concerning the Work, express, implied, statutory or otherwise,
134 | including without limitation warranties of title, merchantability, fitness
135 | for a particular purpose, non infringement, or the absence of latent or
136 | other defects, accuracy, or the present or absence of errors, whether or not
137 | discoverable, all to the greatest extent permissible under applicable law.
138 |
139 | c. Affirmer disclaims responsibility for clearing rights of other persons
140 | that may apply to the Work or any use thereof, including without limitation
141 | any person's Copyright and Related Rights in the Work. Further, Affirmer
142 | disclaims responsibility for obtaining any necessary consents, permissions
143 | or other rights required for any use of the Work.
144 |
145 | d. Affirmer understands and acknowledges that Creative Commons is not a
146 | party to this document and has no duty or obligation with respect to this
147 | CC0 or use of the Work.
148 |
149 | For more information, please see
150 |
151 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all
2 |
3 | all: util yggdrasil-brute-multi-curve25519 yggdrasil-brute-multi-ed25519
4 |
5 | util: util.c
6 | gcc -Wall -std=c89 -O3 -c -o util.o util.c
7 |
8 | yggdrasil-brute-multi-ed25519: yggdrasil-brute-multi-ed25519.c util.o
9 | gcc -Wall -std=c89 -O3 -o yggdrasil-brute-multi-ed25519 -lsodium yggdrasil-brute-multi-ed25519.c util.o
10 |
11 | yggdrasil-brute-multi-curve25519: yggdrasil-brute-multi-curve25519.c util.o
12 | gcc -Wall -std=c89 -O3 -o yggdrasil-brute-multi-curve25519 -lsodium yggdrasil-brute-multi-curve25519.c util.o
13 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/README.md:
--------------------------------------------------------------------------------
1 | # yggdrasil-brute-simple
2 |
3 | Simple program for finding curve25519 and ed25519 public keys whose sha512 hash has many leading ones.
4 | Because ed25519 private keys consist of a seed that is hashed to find the secret part of the keypair,
5 | this program is near optimal for finding ed25519 keypairs. Curve25519 key generation, on the other hand,
6 | could be further optimized with elliptic curve magic.
7 |
8 | Depends on libsodium.
9 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/util.c:
--------------------------------------------------------------------------------
1 | #include "yggdrasil-brute.h"
2 |
3 | int find_where(unsigned char hash[64], unsigned char besthashlist[NUMKEYS][64]) {
4 | /* Where to insert hash into sorted hashlist */
5 | int j;
6 | int where = -1;
7 | for (j = 0; j < NUMKEYS; ++j) {
8 | if (memcmp(hash, besthashlist[j], 64) > 0) ++where;
9 | else break;
10 | }
11 | return where;
12 | }
13 |
14 | void insert_64(unsigned char itemlist[NUMKEYS][64], unsigned char item[64], int where) {
15 | int j;
16 | for (j = 0; j < where; ++j) {
17 | memcpy(itemlist[j], itemlist[j+1], 64);
18 | }
19 | memcpy(itemlist[where], item, 64);
20 | }
21 |
22 | void insert_32(unsigned char itemlist[NUMKEYS][32], unsigned char item[32], int where) {
23 | int j;
24 | for (j = 0; j < where; ++j) {
25 | memcpy(itemlist[j], itemlist[j+1], 32);
26 | }
27 | memcpy(itemlist[where], item, 32);
28 | }
29 |
30 | void make_addr(unsigned char addr[32], unsigned char hash[64]) {
31 | /* Public key hash to yggdrasil ipv6 address */
32 | int i;
33 | int offset;
34 | unsigned char mask;
35 | unsigned char c;
36 | int ones = 0;
37 | unsigned char br = 0; /* false */
38 | for (i = 0; i < 64 && !br; ++i) {
39 | mask = 128;
40 | c = hash[i];
41 | while (mask) {
42 | if (c & mask) {
43 | ++ones;
44 | } else {
45 | br = 1; /* true */
46 | break;
47 | }
48 | mask >>= 1;
49 | }
50 | }
51 |
52 | addr[0] = 2;
53 | addr[1] = ones;
54 |
55 | offset = ones + 1;
56 | for (i = 0; i < 14; ++i) {
57 | c = hash[offset/8] << (offset%8);
58 | c |= hash[offset/8 + 1] >> (8 - offset%8);
59 | addr[i + 2] = c;
60 | offset += 8;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/yggdrasil-brute-multi-curve25519.c:
--------------------------------------------------------------------------------
1 | /*
2 | sk: 32 random bytes
3 | sk[0] &= 248;
4 | sk[31] &= 127;
5 | sk[31] |= 64;
6 |
7 | increment sk
8 | pk = curve25519_scalarmult_base(mysecret)
9 | hash = sha512(pk)
10 |
11 | if besthash:
12 | bestsk = sk
13 | besthash = hash
14 | */
15 |
16 | #include "yggdrasil-brute.h"
17 |
18 |
19 | void seed(unsigned char sk[32]) {
20 | randombytes_buf(sk, 32);
21 | sk[0] &= 248;
22 | sk[31] &= 127;
23 | sk[31] |= 64;
24 | }
25 |
26 |
27 | int main(int argc, char **argv) {
28 | int i;
29 | int j;
30 | unsigned char addr[16];
31 | time_t starttime;
32 | time_t requestedtime;
33 |
34 | unsigned char bestsklist[NUMKEYS][32];
35 | unsigned char bestpklist[NUMKEYS][32];
36 | unsigned char besthashlist[NUMKEYS][64];
37 |
38 | unsigned char sk[32];
39 | unsigned char pk[32];
40 | unsigned char hash[64];
41 |
42 | unsigned int runs = 0;
43 | int where;
44 |
45 | if (argc != 2) {
46 | fprintf(stderr, "usage: ./yggdrasil-brute-multi-curve25519 \n");
47 | return 1;
48 | }
49 |
50 | if (sodium_init() < 0) {
51 | /* panic! the library couldn't be initialized, it is not safe to use */
52 | printf("sodium init failed!\n");
53 | return 1;
54 | }
55 |
56 | starttime = time(NULL);
57 | requestedtime = atoi(argv[1]);
58 |
59 | if (requestedtime < 0) requestedtime = 0;
60 | fprintf(stderr, "Searching for yggdrasil curve25519 keys (this will take slightly longer than %ld seconds)\n", requestedtime);
61 |
62 | sodium_memzero(bestsklist, NUMKEYS * 32);
63 | sodium_memzero(bestpklist, NUMKEYS * 32);
64 | sodium_memzero(besthashlist, NUMKEYS * 64);
65 | seed(sk);
66 |
67 | do {
68 | /* generate pubkey, hash, compare, increment secret.
69 | * this loop should take 4 seconds on modern hardware */
70 | for (i = 0; i < (1 << 16); ++i) {
71 | ++runs;
72 | if (crypto_scalarmult_curve25519_base(pk, sk) != 0) {
73 | printf("scalarmult to create pub failed!\n");
74 | return 1;
75 | }
76 | crypto_hash_sha512(hash, pk, 32);
77 |
78 | where = find_where(hash, besthashlist);
79 | if (where >= 0) {
80 | insert_32(bestsklist, sk, where);
81 | insert_32(bestpklist, pk, where);
82 | insert_64(besthashlist, hash, where);
83 |
84 | seed(sk);
85 | }
86 | for (j = 1; j < 31; ++j) if (++sk[j]) break;
87 | }
88 | } while (time(NULL) - starttime < requestedtime || runs < NUMKEYS);
89 |
90 | fprintf(stderr, "--------------addr-------------- -----------------------------secret----------------------------- -----------------------------public-----------------------------\n");
91 | for (i = 0; i < NUMKEYS; ++i) {
92 | make_addr(addr, besthashlist[i]);
93 | for (j = 0; j < 16; ++j) printf("%02x", addr[j]);
94 | printf(" ");
95 | for (j = 0; j < 32; ++j) printf("%02x", bestsklist[i][j]);
96 | printf(" ");
97 | for (j = 0; j < 32; ++j) printf("%02x", bestpklist[i][j]);
98 | printf("\n");
99 | }
100 |
101 | sodium_memzero(bestsklist, NUMKEYS * 32);
102 | sodium_memzero(sk, 32);
103 |
104 | return 0;
105 | }
106 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/yggdrasil-brute-multi-ed25519.c:
--------------------------------------------------------------------------------
1 | /*
2 | seed: 32 random bytes
3 | sk: sha512(seed)
4 | sk[0] &= 248
5 | sk[31] &= 127
6 | sk[31] |= 64
7 |
8 | pk: scalarmult_ed25519_base(sk)
9 |
10 |
11 | increment seed
12 | generate sk
13 | generate pk
14 | hash = sha512(mypub)
15 |
16 | if besthash:
17 | bestseed = seed
18 | bestseckey = sk
19 | bestpubkey = pk
20 | besthash = hash
21 | */
22 |
23 | #include "yggdrasil-brute.h"
24 |
25 |
26 | int main(int argc, char **argv) {
27 | int i;
28 | int j;
29 | time_t starttime;
30 | time_t requestedtime;
31 |
32 | unsigned char bestsklist[NUMKEYS][64]; /* sk contains pk */
33 | unsigned char besthashlist[NUMKEYS][64];
34 |
35 | unsigned char seed[32];
36 | unsigned char sk[64];
37 | unsigned char pk[32];
38 | unsigned char hash[64];
39 |
40 | unsigned int runs = 0;
41 | int where;
42 |
43 | if (argc != 2) {
44 | fprintf(stderr, "usage: ./yggdrasil-brute-multi-curve25519 \n");
45 | return 1;
46 | }
47 |
48 | if (sodium_init() < 0) {
49 | /* panic! the library couldn't be initialized, it is not safe to use */
50 | printf("sodium init failed!\n");
51 | return 1;
52 | }
53 |
54 | starttime = time(NULL);
55 | requestedtime = atoi(argv[1]);
56 |
57 | if (requestedtime < 0) requestedtime = 0;
58 | fprintf(stderr, "Searching for yggdrasil ed25519 keys (this will take slightly longer than %ld seconds)\n", requestedtime);
59 |
60 | sodium_memzero(bestsklist, NUMKEYS * 64);
61 | sodium_memzero(besthashlist, NUMKEYS * 64);
62 | randombytes_buf(seed, 32);
63 |
64 | do {
65 | /* generate pubkey, hash, compare, increment secret.
66 | * this loop should take 4 seconds on modern hardware */
67 | for (i = 0; i < (1 << 17); ++i) {
68 | ++runs;
69 | crypto_hash_sha512(sk, seed, 32);
70 |
71 | if (crypto_scalarmult_ed25519_base(pk, sk) != 0) {
72 | printf("scalarmult to create pub failed!\n");
73 | return 1;
74 | }
75 | memcpy(sk + 32, pk, 32);
76 |
77 | crypto_hash_sha512(hash, pk, 32);
78 |
79 | /* insert into local list of good key */
80 | where = find_where(hash, besthashlist);
81 | if (where >= 0) {
82 | insert_64(bestsklist, sk, where);
83 | insert_64(besthashlist, hash, where);
84 | randombytes_buf(seed, 32);
85 | }
86 | for (j = 1; j < 31; ++j) if (++seed[j]) break;
87 | }
88 | } while (time(NULL) - starttime < requestedtime || runs < NUMKEYS);
89 |
90 | fprintf(stderr, "!! Secret key is seed concatenated with public !!\n");
91 | fprintf(stderr, "---hash--- ------------------------------seed------------------------------ -----------------------------public-----------------------------\n");
92 | for (i = 0; i < NUMKEYS; ++i) {
93 | for (j = 0; j < 5; ++j) printf("%02x", besthashlist[i][j]);
94 | printf(" ");
95 | for (j = 0; j < 32; ++j) printf("%02x", bestsklist[i][j]);
96 | printf(" ");
97 | for (j = 32; j < 64; ++j) printf("%02x", bestsklist[i][j]);
98 | printf("\n");
99 | }
100 |
101 | sodium_memzero(bestsklist, NUMKEYS * 64);
102 | sodium_memzero(sk, 64);
103 | sodium_memzero(seed, 32);
104 |
105 | return 0;
106 | }
107 |
--------------------------------------------------------------------------------
/contrib/yggdrasil-brute-simple/yggdrasil-brute.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include /* printf */
3 | #include /* memcpy */
4 | #include /* atoi */
5 | #include /* time */
6 |
7 |
8 | #define NUMKEYS 10
9 | void make_addr(unsigned char addr[32], unsigned char hash[64]);
10 | int find_where(unsigned char hash[64], unsigned char besthashlist[NUMKEYS][64]);
11 | void insert_64(unsigned char itemlist[NUMKEYS][64], unsigned char item[64], int where);
12 | void insert_32(unsigned char itemlist[NUMKEYS][32], unsigned char item[32], int where);
13 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/popura-network/Popura
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/cheggaaa/pb/v3 v3.0.8
7 | github.com/gologme/log v1.2.0
8 | github.com/hashicorp/go-syslog v1.0.0
9 | github.com/hjson/hjson-go v3.1.0+incompatible
10 | github.com/kardianos/minwinsvc v1.0.2
11 | github.com/mitchellh/mapstructure v1.4.1
12 | github.com/olekukonko/tablewriter v0.0.5
13 | github.com/yggdrasil-network/yggdrasil-go v0.4.6
14 | github.com/zhoreeq/meshname v0.2.0
15 | golang.org/x/mobile v0.0.0-20221012134814-c746ac228303
16 | golang.org/x/text v0.3.8
17 | )
18 |
19 | require (
20 | github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2 // indirect
21 | github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979 // indirect
22 | github.com/VividCortex/ewma v1.2.0 // indirect
23 | github.com/fatih/color v1.12.0 // indirect
24 | github.com/mattn/go-colorable v0.1.8 // indirect
25 | github.com/mattn/go-isatty v0.0.13 // indirect
26 | github.com/mattn/go-runewidth v0.0.13 // indirect
27 | github.com/miekg/dns v1.1.41 // indirect
28 | github.com/rivo/uniseg v0.2.0 // indirect
29 | github.com/vishvananda/netlink v1.1.0 // indirect
30 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
31 | golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect
32 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
33 | golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
34 | golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect
35 | golang.org/x/tools v0.1.12 // indirect
36 | golang.zx2c4.com/wireguard v0.0.0-20211017052713-f87e87af0d9a // indirect
37 | golang.zx2c4.com/wireguard/windows v0.4.12 // indirect
38 | )
39 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2 h1:Usab30pNT2i/vZvpXcN9uOr5IO1RZPcUqoGH0DIAPnU=
2 | github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk=
3 | github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979 h1:WndgpSW13S32VLQ3ugUxx2EnnWmgba1kCqPkd4Gk1yQ=
4 | github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI=
5 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
6 | github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
7 | github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
8 | github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
9 | github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA=
10 | github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA=
11 | github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
12 | github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
13 | github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
14 | github.com/gologme/log v1.2.0 h1:Ya5Ip/KD6FX7uH0S31QO87nCCSucKtF44TLbTtO7V4c=
15 | github.com/gologme/log v1.2.0/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U=
16 | github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
17 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
18 | github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw=
19 | github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
20 | github.com/kardianos/minwinsvc v1.0.2 h1:JmZKFJQrmTGa/WiW+vkJXKmfzdjabuEW4Tirj5lLdR0=
21 | github.com/kardianos/minwinsvc v1.0.2/go.mod h1:LUZNYhNmxujx2tR7FbdxqYJ9XDDoCd3MQcl1o//FWl4=
22 | github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
23 | github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
24 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
25 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
26 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
27 | github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
28 | github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
29 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
30 | github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
31 | github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
32 | github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
33 | github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
34 | github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
35 | github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
36 | github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
37 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
38 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
39 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
40 | github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
41 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
42 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
43 | github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
44 | github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
45 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
46 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
47 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
48 | github.com/yggdrasil-network/yggdrasil-go v0.4.6 h1:GALUDV9QPz/5FVkbazpkTc9EABHufA556JwUJZr41j4=
49 | github.com/yggdrasil-network/yggdrasil-go v0.4.6/go.mod h1:PBMoAOvQjA9geNEeGyMXA9QgCS6Bu+9V+1VkWM84wpw=
50 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
51 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
52 | github.com/zhoreeq/meshname v0.2.0 h1:kRAHmemR/MpTmas2ZNoL8VJnYdbesZRwsGR2qEmzyDo=
53 | github.com/zhoreeq/meshname v0.2.0/go.mod h1:3I8MpFZ304bAYiD+e+ovlMDDZat8aKyUlqllUok4qm0=
54 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
55 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
56 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
57 | golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
58 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
59 | golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
60 | golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
61 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
62 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
63 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
64 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
65 | golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
66 | golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
67 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
68 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
69 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
70 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
71 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
72 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
73 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
74 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
75 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
76 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
77 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
78 | golang.org/x/net v0.0.0-20210927181540-4e4d966f7476/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
79 | golang.org/x/net v0.0.0-20211011170408-caeb26a5c8c0/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
80 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
81 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
82 | golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
83 | golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
84 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
85 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
86 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
87 | golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
88 | golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
89 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
90 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
91 | golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
92 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
93 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
94 | golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
95 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
96 | golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
97 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
98 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
99 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
100 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
101 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
102 | golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
103 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
104 | golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
105 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
106 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
107 | golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
108 | golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4=
109 | golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
110 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
111 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
112 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
113 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
114 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
115 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
116 | golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
117 | golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
118 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
119 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
120 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
121 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
122 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
123 | golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
124 | golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
125 | golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
126 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
127 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
128 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
129 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
130 | golang.zx2c4.com/wireguard v0.0.0-20211012062646-82d2aa87aa62/go.mod h1:id8Oh3eCCmpj9uVGWVjsUAl6UPX5ysMLzu6QxJU2UOU=
131 | golang.zx2c4.com/wireguard v0.0.0-20211017052713-f87e87af0d9a h1:tTbyylK9/D3u/wEP26Vx7L700UpY48nhioJWZM1vhZw=
132 | golang.zx2c4.com/wireguard v0.0.0-20211017052713-f87e87af0d9a/go.mod h1:id8Oh3eCCmpj9uVGWVjsUAl6UPX5ysMLzu6QxJU2UOU=
133 | golang.zx2c4.com/wireguard/windows v0.4.12 h1:CUmbdWKVNzTSsVb4yUAiEwL3KsabdJkEPdDjCHxBlhA=
134 | golang.zx2c4.com/wireguard/windows v0.4.12/go.mod h1:PW4y+d9oY83XU9rRwRwrJDwEMuhVjMxu2gfD1cfzS7w=
135 |
--------------------------------------------------------------------------------
/misc/run-schannel-netns:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Connects nodes in a network resembling an s-channel feynmann diagram.
4 |
5 | # 1 5
6 | # \ /
7 | # 3--4
8 | # / \
9 | # 2 6
10 |
11 | # Bandwidth constraints are applied to 4<->5 and 4<->6.
12 | # The idea is to make sure that bottlenecks on one link don't affect the other.
13 |
14 | ip netns add node1
15 | ip netns add node2
16 | ip netns add node3
17 | ip netns add node4
18 | ip netns add node5
19 | ip netns add node6
20 |
21 | ip link add veth13 type veth peer name veth31
22 | ip link set veth13 netns node1 up
23 | ip link set veth31 netns node3 up
24 |
25 | ip link add veth23 type veth peer name veth32
26 | ip link set veth23 netns node2 up
27 | ip link set veth32 netns node3 up
28 |
29 | ip link add veth34 type veth peer name veth43
30 | ip link set veth34 netns node3 up
31 | ip link set veth43 netns node4 up
32 |
33 | ip link add veth45 type veth peer name veth54
34 | ip link set veth45 netns node4 up
35 | ip link set veth54 netns node5 up
36 |
37 | ip link add veth46 type veth peer name veth64
38 | ip link set veth46 netns node4 up
39 | ip link set veth64 netns node6 up
40 |
41 | ip netns exec node4 tc qdisc add dev veth45 root tbf rate 100mbit burst 8192 latency 1ms
42 | ip netns exec node5 tc qdisc add dev veth54 root tbf rate 100mbit burst 8192 latency 1ms
43 |
44 | ip netns exec node4 tc qdisc add dev veth46 root tbf rate 10mbit burst 8192 latency 1ms
45 | ip netns exec node6 tc qdisc add dev veth64 root tbf rate 10mbit burst 8192 latency 1ms
46 |
47 | ip netns exec node1 ip link set lo up
48 | ip netns exec node2 ip link set lo up
49 | ip netns exec node3 ip link set lo up
50 | ip netns exec node4 ip link set lo up
51 | ip netns exec node5 ip link set lo up
52 | ip netns exec node6 ip link set lo up
53 |
54 | echo '{AdminListen: "none"}' | ip netns exec node1 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
55 | echo '{AdminListen: "none"}' | ip netns exec node2 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
56 | echo '{AdminListen: "none"}' | ip netns exec node3 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
57 | echo '{AdminListen: "none"}' | ip netns exec node4 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
58 | echo '{AdminListen: "none"}' | ip netns exec node5 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
59 | echo '{AdminListen: "none"}' | ip netns exec node6 env PPROFLISTEN=localhost:6060 ./yggdrasil --useconf &> /dev/null &
60 |
61 | echo "Started, to continue you should (possibly w/ sudo):"
62 | echo "kill" $(jobs -p)
63 | wait
64 |
65 | ip netns delete node1
66 | ip netns delete node2
67 | ip netns delete node3
68 | ip netns delete node4
69 | ip netns delete node5
70 | ip netns delete node6
71 |
72 | ip link delete veth13
73 | ip link delete veth23
74 | ip link delete veth34
75 | ip link delete veth45
76 | ip link delete veth46
77 |
--------------------------------------------------------------------------------
/misc/run-twolink-test:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Connects nodes in two namespaces by two links with different bandwidth (10mbit and 100mbit)
4 |
5 | ip netns add node1
6 | ip netns add node2
7 |
8 | ip link add veth11 type veth peer name veth21
9 | ip link set veth11 netns node1 up
10 | ip link set veth21 netns node2 up
11 |
12 | ip link add veth12 type veth peer name veth22
13 | ip link set veth12 netns node1 up
14 | ip link set veth22 netns node2 up
15 |
16 | ip netns exec node1 tc qdisc add dev veth11 root tbf rate 10mbit burst 8192 latency 1ms
17 | ip netns exec node2 tc qdisc add dev veth21 root tbf rate 10mbit burst 8192 latency 1ms
18 |
19 | ip netns exec node1 tc qdisc add dev veth12 root tbf rate 100mbit burst 8192 latency 1ms
20 | ip netns exec node2 tc qdisc add dev veth22 root tbf rate 100mbit burst 8192 latency 1ms
21 |
22 | echo '{AdminListen: "unix://node1.sock"}' | ip netns exec node1 env PPROFLISTEN=localhost:6060 ./yggdrasil -logging "info,warn,error,debug" -useconf &> node1.log &
23 | echo '{AdminListen: "unix://node2.sock"}' | ip netns exec node2 env PPROFLISTEN=localhost:6060 ./yggdrasil -logging "info,warn,error,debug" -useconf &> node2.log &
24 |
25 | echo "Started, to continue you should (possibly w/ sudo):"
26 | echo "kill" $(jobs -p)
27 | wait
28 |
29 | ip netns delete node1
30 | ip netns delete node2
31 |
32 | ip link delete veth11
33 | ip link delete veth12
34 |
--------------------------------------------------------------------------------
/src/autopeering/main.go:
--------------------------------------------------------------------------------
1 | package autopeering
2 |
3 | import (
4 | "net"
5 | "net/url"
6 | "time"
7 | )
8 |
9 | const defaultTimeout time.Duration = time.Duration(3) * time.Second
10 |
11 | type Peer struct {
12 | URL url.URL
13 | Online bool
14 | Latency time.Duration
15 | }
16 |
17 | func testPeers(peers []url.URL) []Peer {
18 | var res []Peer
19 | results := make(chan Peer)
20 |
21 | for _, p := range peers {
22 | go testPeer(p, results)
23 | }
24 |
25 | for i := 0; i < len(peers); i++ {
26 | res = append(res, <-results)
27 | }
28 |
29 | return res
30 | }
31 |
32 | func testPeer(peer url.URL, results chan Peer) {
33 | p := Peer{peer, false, 0.0}
34 | p.Online = false
35 | t0 := time.Now()
36 |
37 | var network string
38 | if peer.Scheme == "tcp" || peer.Scheme == "tls" {
39 | network = "tcp"
40 | } else { // skip, not supported yet
41 | results <- p
42 | return
43 | }
44 |
45 | conn, err := net.DialTimeout(network, peer.Host, defaultTimeout)
46 | if err == nil {
47 | t1 := time.Now()
48 | conn.Close()
49 | p.Online = true
50 | p.Latency = t1.Sub(t0)
51 | }
52 | results <- p
53 | }
54 |
--------------------------------------------------------------------------------
/src/autopeering/module.go:
--------------------------------------------------------------------------------
1 | package autopeering
2 |
3 | import (
4 | "net/url"
5 | "strings"
6 | "time"
7 |
8 | "github.com/gologme/log"
9 |
10 | "github.com/yggdrasil-network/yggdrasil-go/src/admin"
11 | "github.com/yggdrasil-network/yggdrasil-go/src/config"
12 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
13 |
14 | "github.com/popura-network/Popura/src/popura"
15 | )
16 |
17 | const (
18 | linkLocalPrefix = "tls://[fe80"
19 | autopeerTimeout = 30 * time.Second
20 | peerCheckTimeout = 10 * time.Second
21 | )
22 |
23 | type AutoPeering struct {
24 | core *core.Core
25 | log *log.Logger
26 | checkPeerTimer *time.Timer
27 | hadPeers time.Time
28 | peers []url.URL
29 | enabled bool
30 | }
31 |
32 | func (ap *AutoPeering) Init(yggcore *core.Core, yggConfig *config.NodeConfig, popConfig *popura.PopuraConfig, log *log.Logger, options interface{}) error {
33 | ap.core = yggcore
34 | ap.log = log
35 | ap.peers = GetPublicPeers()
36 | ap.enabled = popConfig.Autopeering.Enable
37 | return nil
38 | }
39 |
40 | func (ap *AutoPeering) Start() error {
41 | if ap.enabled {
42 | go ap.checkPeerLoop()
43 | }
44 | ap.log.Infoln("autopeering: module started")
45 | return nil
46 | }
47 |
48 | func (ap *AutoPeering) Stop() error {
49 | if ap.checkPeerTimer != nil {
50 | ap.checkPeerTimer.Stop()
51 | }
52 | return nil
53 | }
54 |
55 | func (ap *AutoPeering) checkPeerLoop() {
56 | havePeers := false
57 |
58 | for _, p := range ap.core.GetPeers() {
59 | if !strings.HasPrefix(p.Remote, linkLocalPrefix) {
60 | ap.log.Debugln("autopeering: remote peer is connected ", p.Remote)
61 | havePeers = true
62 | break
63 | }
64 | }
65 |
66 | if havePeers {
67 | ap.hadPeers = time.Now()
68 | } else if time.Since(ap.hadPeers) > autopeerTimeout {
69 | ap.log.Debugln("autopeering: adding a new peer")
70 | ap.hadPeers = time.Now()
71 | peers := RandomPick(GetClosestPeers(ap.peers, 10), 1)
72 | if len(peers) == 1 {
73 | peerUri := peers[0]
74 |
75 | ap.log.Infoln("autopeering: adding new peer", peerUri.String())
76 | go func() {
77 | if err := ap.core.CallPeer(&peerUri, ""); err != nil {
78 | ap.log.Infoln("autopeering: peer connection failed:", err)
79 | }
80 | }()
81 | }
82 | }
83 |
84 | ap.checkPeerTimer = time.AfterFunc(peerCheckTimeout, func() {
85 | ap.checkPeerLoop()
86 | })
87 | }
88 |
89 | func (ap *AutoPeering) UpdateConfig(yggConfig *config.NodeConfig, popConfig *popura.PopuraConfig) {}
90 | func (ap *AutoPeering) SetupAdminHandlers(a *admin.AdminSocket) {}
91 | func (ap *AutoPeering) IsStarted() bool { return false }
92 |
--------------------------------------------------------------------------------
/src/autopeering/peers.go:
--------------------------------------------------------------------------------
1 | package autopeering
2 |
3 | import (
4 | _ "embed"
5 | "math/rand"
6 | "net/url"
7 | "sort"
8 | "strings"
9 | "time"
10 | )
11 |
12 | //go:embed peers.txt
13 | var PublicPeers string
14 |
15 | // Get URLs of embedded public peers
16 | func GetPublicPeers() []url.URL {
17 | var result []url.URL
18 |
19 | for _, p := range strings.Split(PublicPeers, "\n") {
20 | if url, err := url.Parse(p); err == nil {
21 | result = append(result, *url)
22 | } else {
23 | panic(err)
24 | }
25 | }
26 | return result
27 | }
28 |
29 | // Get n online peers with best latency from a peer list
30 | func GetClosestPeers(peerList []url.URL, n int) []url.URL {
31 | var result []url.URL
32 | onlinePeers := testPeers(peerList)
33 |
34 | // Filter online peers
35 | x := 0
36 | for _, p := range onlinePeers {
37 | if p.Online {
38 | onlinePeers[x] = p
39 | x++
40 | }
41 | }
42 | onlinePeers = onlinePeers[:x]
43 |
44 | sort.Slice(onlinePeers, func(i, j int) bool {
45 | return onlinePeers[i].Latency < onlinePeers[j].Latency
46 | })
47 |
48 | for i := 0; i < len(onlinePeers); i++ {
49 | if len(result) == n {
50 | break
51 | }
52 | result = append(result, onlinePeers[i].URL)
53 | }
54 |
55 | return result
56 | }
57 |
58 | // Pick n random peers from a list
59 | func RandomPick(peerList []url.URL, n int) []url.URL {
60 | if len(peerList) <= n {
61 | return peerList
62 | }
63 |
64 | var res []url.URL
65 | r := rand.New(rand.NewSource(time.Now().UnixNano()))
66 | for _, i := range r.Perm(n) {
67 | res = append(res, peerList[i])
68 | }
69 |
70 | return res
71 | }
72 |
--------------------------------------------------------------------------------
/src/autopeering/peers.txt:
--------------------------------------------------------------------------------
1 | tcp://ipv6.campina-grande.paraiba.brazil.yggdrasil.iasylum.net:41000
2 | tcp://ipv4.campina-grande.paraiba.brazil.yggdrasil.iasylum.net:40000
3 | tls://ipv6.campina-grande.paraiba.brazil.yggdrasil.iasylum.net:51000
4 | tls://ipv4.campina-grande.paraiba.brazil.yggdrasil.iasylum.net:50000
5 | tls://192.99.145.61:58226
6 | tls://[2607:5300:201:3100::50a1]:58226
7 | tcp://kusoneko.moe:9002
8 | tls://ca1.servers.devices.cwinfo.net:58226
9 | tcp://[2a05:9403::8b]:7743
10 | tcp://195.123.245.146:7743
11 | tls://95.216.5.243:18836
12 | tls://[2a01:4f9:2a:60c::2]:18836
13 | tls://[2a01:4f9:c010:664d::1]:61995
14 | tls://aurora.devices.waren.io:18836
15 | tls://fi1.servers.devices.cwinfo.net:61995
16 | tls://65.21.57.122:61995
17 | tls://[2001:41d0:2:c44a:51:255:223:60]:54232
18 | tcp://62.210.85.80:39565
19 | tls://51.255.223.60:54232
20 | tcp://51.15.204.214:12345
21 | tls://51.15.204.214:54321
22 | tcp://[2001:470:1f13:e56::64]:39565
23 | tcp://s2.i2pd.xyz:39565
24 | tls://[2001:41d0:304:200::ace3]:23108
25 | tls://62.210.85.80:39575
26 | tls://[2001:470:1f13:e56::64]:39575
27 | tls://152.228.216.112:23108
28 | tls://s2.i2pd.xyz:39575
29 | tls://cloudberry.fr1.servers.devices.cwinfo.net:54232
30 | tls://fr2.servers.devices.cwinfo.net:23108
31 | tls://163.172.31.60:12221?key=060f2d49c6a1a2066357ea06e58f5cff8c76a5c0cc513ceb2dab75c900fe183b&sni=jorropo.net
32 | tls://jorropo.net:12221?key=060f2d49c6a1a2066357ea06e58f5cff8c76a5c0cc513ceb2dab75c900fe183b&sni=jorropo.net
33 | tcp://94.130.203.208:5999
34 | tls://yggdrasil.su:62586
35 | tcp://ygg.mkg20001.io:80
36 | tls://vpn.ltha.de:443?key=0000006149970f245e6cec43664bce203f2514b60a153e194f31e2b229a1339d
37 | tls://de-fsn-1.peer.v4.yggdrasil.chaz6.com:4444
38 | tcp://p2p-node.de:1337?key=000000d80a2d7b3126ea65c8c08fc751088c491a5cdd47eff11c86fa1e4644ae
39 | tcp://phrl42.ydns.eu:8842
40 | tcp://yggdrasil.su:62486
41 | tls://ygg.mkg20001.io:443
42 | tls://p2p-node.de:1338?key=000000d80a2d7b3126ea65c8c08fc751088c491a5cdd47eff11c86fa1e4644ae
43 | tcp://ygg1.mk16.de:1337?key=0000000087ee9949eeab56bd430ee8f324cad55abf3993ed9b9be63ce693e18a
44 | tls://ygg1.mk16.de:1338?key=0000000087ee9949eeab56bd430ee8f324cad55abf3993ed9b9be63ce693e18a
45 | tls://minecast.xyz:3785
46 | tls://45.147.198.155:6010
47 | tcp://ygg-nl.incognet.io:8883
48 | tcp://vpn.itrus.su:7991
49 | tls://ygg-nl.incognet.io:8884
50 | tls://109.107.173.235:9111
51 | tls://94.103.82.150:8080
52 | tls://aaoth.xyz:25565
53 | tcp://aaoth.xyz:7777
54 | tls://[2001:41d0:601:1100::cf2]:11129
55 | tls://54.37.137.221:11129
56 | tls://pl1.servers.devices.cwinfo.net:11129
57 | tcp://185.165.169.234:8880
58 | tls://185.165.169.234:8443
59 | tcp://188.225.9.167:18226
60 | tcp://92.124.136.131:30111
61 | tls://188.225.9.167:18227
62 | tcp://ygg.tomasgl.ru:61933?key=c5e0c28a600c2118e986196a0bbcbda4934d8e9278ceabea48838dc5d8fae576
63 | tls://[2a01:d0:ffff:4353::2]:6010
64 | tls://avevad.com:1337
65 | tcp://itcom.multed.com:7991
66 | tls://ygg.tomasgl.ru:61944?key=c5e0c28a600c2118e986196a0bbcbda4934d8e9278ceabea48838dc5d8fae576
67 | tcp://srv.itrus.su:7991
68 | tcp://box.paulll.cc:13337
69 | tcp://yggno.de:18226
70 | tls://yggno.de:18227
71 | tcp://ekb.itrus.su:7991
72 | tls://box.paulll.cc:13338
73 | tls://yggpvs.duckdns.org:8443
74 | tcp://158.101.229.219:17002
75 | tcp://[2603:c023:8001:1600:35e0:acde:2c6e:b27f]:17002
76 | tls://[2603:c023:8001:1600:35e0:acde:2c6e:b27f]:17001
77 | tls://158.101.229.219:17001
78 | tcp://sin.yuetau.net:6642
79 | tls://sin.yuetau.net:6643
80 | tcp://y.zbin.eu:7743
81 | tcp://[2a04:5b81:2010:5000:27d3:6343:a821:eb1c]:2000
82 | tls://[2a04:5b81:2010:5000:27d3:6343:a821:eb1c]:2001
83 | tls://[2a07:e01:105:444:c634:6bff:feb5:6e28]:7040
84 | tls://185.130.44.194:7040
85 | tls://ygg.ace.ctrl-c.liu.se:9999?key=5636b3af4738c3998284c4805d91209cab38921159c66a6f359f3f692af1c908
86 | tcp://ygg.ace.ctrl-c.liu.se:9998?key=5636b3af4738c3998284c4805d91209cab38921159c66a6f359f3f692af1c908
87 | tcp://212.154.86.134:8800
88 | tls://212.154.86.134:4433
89 | tcp://ip6-antalya.ddns.net:8800
90 | tls://ip6-antalya.ddns.net:4433
91 | tcp://193.111.114.28:8080
92 | tls://193.111.114.28:1443
93 | tls://91.224.254.114:18001
94 | tcp://78.27.153.163:33165
95 | tls://78.27.153.163:3784
96 | tls://78.27.153.163:179
97 | tls://78.27.153.163:3785
98 | tls://78.27.153.163:33166
99 | tls://51.38.64.12:28395
100 | tls://185.175.90.87:43006
101 | tls://[2a10:4740:40:0:2222:3f9c:b7cf:1]:43006
102 | tls://uk1.servers.devices.cwinfo.net:28395
103 | tcp://curiosity.tdjs.tech:30003
104 | tcp://50.236.201.218:56088
105 | tcp://longseason.1200bps.xyz:13121
106 | tcp://149.28.123.138:8008
107 | tcp://lancis.iscute.moe:49273
108 | tcp://zabugor.itrus.su:7991
109 | tcp://supergay.network:9002
110 | tls://108.175.10.127:61216
111 | tls://longseason.1200bps.xyz:13122
112 | tls://167.160.89.98:7040
113 | tls://supergay.network:9001
114 | tls://supergay.network:443
115 | tcp://tasty.chowder.land:9002
116 | tls://44.234.134.124:443
117 | tls://[2605:9f80:2000:64::2]:7040
118 | tls://bazari.sh:3725
119 | tls://tasty.chowder.land:9001
120 | tls://5.161.114.182:443
121 | tls://5.161.139.99:443
122 | tls://lancis.iscute.moe:49274
123 |
--------------------------------------------------------------------------------
/src/meshname/module.go:
--------------------------------------------------------------------------------
1 | package meshname
2 |
3 | import (
4 | "net"
5 |
6 | "github.com/gologme/log"
7 |
8 | "github.com/yggdrasil-network/yggdrasil-go/src/admin"
9 | "github.com/yggdrasil-network/yggdrasil-go/src/config"
10 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
11 |
12 | _meshname "github.com/zhoreeq/meshname/pkg/meshname"
13 |
14 | "github.com/popura-network/Popura/src/popura"
15 | )
16 |
17 | type MeshnameServer struct {
18 | server *_meshname.MeshnameServer
19 | log *log.Logger
20 | enable bool
21 | }
22 |
23 | func (s *MeshnameServer) Init(yggcore *core.Core, yggConfig *config.NodeConfig, popConfig *popura.PopuraConfig, log *log.Logger, options interface{}) error {
24 | s.log = log
25 | s.enable = popConfig.Meshname.Enable
26 | yggIPNet := &net.IPNet{IP: net.ParseIP("200::"), Mask: net.CIDRMask(7, 128)}
27 | s.server = _meshname.New(
28 | log,
29 | popConfig.Meshname.Listen,
30 | map[string]*net.IPNet{"ygg": yggIPNet, "meshname": yggIPNet, "popura": yggIPNet},
31 | false, // enable meship protocol
32 | )
33 |
34 | return nil
35 | }
36 |
37 | func (s *MeshnameServer) Start() error {
38 | if s.enable {
39 | return s.server.Start()
40 | } else {
41 | return nil
42 | }
43 | }
44 |
45 | func (s *MeshnameServer) Stop() error {
46 | s.server.Stop()
47 | return nil
48 | }
49 |
50 | func (s *MeshnameServer) UpdateConfig(yggConfig *config.NodeConfig, popConfig *popura.PopuraConfig) {}
51 |
52 | func (s *MeshnameServer) SetupAdminHandlers(a *admin.AdminSocket) {}
53 |
54 | func (s *MeshnameServer) IsStarted() bool {
55 | return s.server.IsStarted()
56 | }
57 |
--------------------------------------------------------------------------------
/src/popura/config.go:
--------------------------------------------------------------------------------
1 | package popura
2 |
3 | type PopuraConfig struct {
4 | Autopeering AutopeeringConfig `comment:"Autopeering description"`
5 | Meshname MeshnameConfig `comment:"DNS server description"`
6 | }
7 |
8 | type AutopeeringConfig struct {
9 | Enable bool `comment:"Enable autopeering"`
10 | }
11 |
12 | type MeshnameConfig struct {
13 | Enable bool `comment:"Enable or disable the DNS server"`
14 | Listen string `comment:"Listen address for the DNS server"`
15 | }
16 |
17 | func GenerateConfig() *PopuraConfig {
18 | popConfig := PopuraConfig{}
19 |
20 | popConfig.Autopeering.Enable = false
21 |
22 | popConfig.Meshname.Enable = false
23 | popConfig.Meshname.Listen = "[::1]:53535"
24 |
25 | return &popConfig
26 | }
27 |
--------------------------------------------------------------------------------
/src/popura/module.go:
--------------------------------------------------------------------------------
1 | package popura
2 |
3 | import (
4 | "github.com/gologme/log"
5 |
6 | "github.com/yggdrasil-network/yggdrasil-go/src/admin"
7 | "github.com/yggdrasil-network/yggdrasil-go/src/config"
8 | "github.com/yggdrasil-network/yggdrasil-go/src/core"
9 | )
10 |
11 | // Module is an interface that defines which functions must be supported by a
12 | // given Popura module.
13 | type Module interface {
14 | Init(yggcore *core.Core, yggConfig *config.NodeConfig, popuraConf *PopuraConfig, log *log.Logger, options interface{}) error
15 | Start() error
16 | Stop() error
17 | UpdateConfig(yggConf *config.NodeConfig, popuraConf *PopuraConfig)
18 | SetupAdminHandlers(a *admin.AdminSocket)
19 | IsStarted() bool
20 | }
21 |
--------------------------------------------------------------------------------
/src/popura/utils.go:
--------------------------------------------------------------------------------
1 | package popura
2 |
3 | import (
4 | "crypto/ed25519"
5 | "encoding/hex"
6 | "net"
7 |
8 | "github.com/yggdrasil-network/yggdrasil-go/src/address"
9 | )
10 |
11 | func decodeKey(input string) ed25519.PublicKey {
12 | keyData, _ := hex.DecodeString(input)
13 | return ed25519.PrivateKey(keyData).Public().(ed25519.PublicKey)
14 | }
15 |
16 | // Get the subnet information from PublicKey
17 | func SubnetFromKey(inputString string) *net.IPNet {
18 | key := decodeKey(inputString)
19 |
20 | snet := address.SubnetForKey(key)
21 | ipnet := net.IPNet{
22 | IP: append(snet[:], 0, 0, 0, 0, 0, 0, 0, 0),
23 | Mask: net.CIDRMask(len(snet)*8, 128),
24 | }
25 |
26 | return &ipnet
27 | }
28 |
29 | // Get the address information from PublicKey
30 | func AddressFromKey(inputString string) *net.IP {
31 | key := decodeKey(inputString)
32 |
33 | addr := address.AddrForKey(key)
34 | ip := net.IP(addr[:])
35 | return &ip
36 | }
37 |
--------------------------------------------------------------------------------