Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
05cc6b08ce | ||
![]() |
1e23bdb2e0 | ||
![]() |
f4a7b5abbe | ||
![]() |
53768270bd | ||
![]() |
0c59a57fc0 | ||
![]() |
d3fb8478b9 | ||
![]() |
e8b9a09992 | ||
![]() |
85a67189ff | ||
![]() |
91a21970ce | ||
![]() |
5b24c1d1bf | ||
![]() |
b5fe9d691d | ||
![]() |
76d27fbcfa |
2
.github/workflows/build.sh
vendored
2
.github/workflows/build.sh
vendored
@@ -7,6 +7,6 @@ do
|
||||
platform_split=(${platform//\// })
|
||||
GOOS=${platform_split[0]}
|
||||
GOARCH=${platform_split[1]}
|
||||
env GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-X github.com/hyprspace/hyprspace/cli.appVersion=$1" -o hyprspace-$1-${GOOS}-${GOARCH} .
|
||||
env GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/hyprspace/hyprspace/cli.appVersion=$1" -o hyprspace-$1-${GOOS}-${GOARCH} .
|
||||
|
||||
done
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
hyprspace
|
||||
hyprspace
|
||||
.DS_Store
|
11
README.md
11
README.md
@@ -5,6 +5,10 @@
|
||||
|
||||
A Lightweight VPN Built on top of Libp2p for Truly Distributed Networks.
|
||||
|
||||
https://user-images.githubusercontent.com/19558067/121469777-f42cdb80-c971-11eb-84de-9dd4f6d6cd1f.mp4
|
||||
|
||||
|
||||
|
||||
## Table of Contents
|
||||
- [A Bit of Backstory](#a-bit-of-backstory)
|
||||
- [Use Cases](#use-cases)
|
||||
@@ -35,6 +39,9 @@ Honestly, I even use this system when I'm at home and could connect directly to
|
||||
|
||||
If anyone else has some use cases please add them! Pull requests welcome!
|
||||
|
||||
| :exclamation: | Hyprspace is still a very new project. Although we've tested the code locally for security, it hasn't been audited by a third party yet. We probably wouldn't trust it yet in high security environments. |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
## Getting Started
|
||||
### Prerequisites
|
||||
If you're running Hyprspace on a Mac you'll need to install `iproute2mac`. If you're using the `brew` package manager that's as simple as,
|
||||
@@ -44,7 +51,7 @@ brew install iproute2mac
|
||||
|
||||
### Installation
|
||||
|
||||
1. Go to Hyprspace Releases (other there -->)
|
||||
1. Go to Hyprspace Releases (over there -->)
|
||||
2. Copy the link for your corresponding OS and Architecture.
|
||||
3. Run `sudo mkdir -p /usr/local/bin/`
|
||||
4. Run `sudo curl -L "PATH-TO-RELEASE" -o /usr/local/bin/hyprspace`
|
||||
@@ -61,7 +68,7 @@ brew install iproute2mac
|
||||
| `init` | `i` | Initialize an interface's configuration. |
|
||||
| `up` | `up` | Create and Bring Up a Hyprspace Interface |
|
||||
| `down ` | `d` | Bring Down and Delete A Hyprspace Interface |
|
||||
| `update` | `upd` | Have Hyprspace update its own binary. |
|
||||
| `update` | `upd` | Have Hyprspace update its own binary to the latest release. |
|
||||
|
||||
## Tutorial
|
||||
|
||||
|
@@ -55,6 +55,7 @@ func InitRun(r *cmd.Root, c *cmd.Sub) {
|
||||
new := config.Config{
|
||||
Interface: config.Interface{
|
||||
Name: args.InterfaceName,
|
||||
ListenPort: 8001,
|
||||
Address: "10.1.1.1/24",
|
||||
ID: host.ID().Pretty(),
|
||||
PrivateKey: string(keyBytes),
|
||||
|
11
cli/root.go
11
cli/root.go
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/DataDrake/cli-ng/v2/cmd"
|
||||
)
|
||||
|
||||
var appVersion string = "develop"
|
||||
|
||||
//GlobalFlags contains the flags for commands.
|
||||
type GlobalFlags struct {
|
||||
Config string `short:"c" long:"config" desc:"Specify a custom config path."`
|
||||
@@ -19,15 +21,18 @@ var Root *cmd.Root
|
||||
|
||||
func init() {
|
||||
Root = &cmd.Root{
|
||||
Name: "hyprspace",
|
||||
Short: "Hyprspace Distributed Network",
|
||||
Flags: &GlobalFlags{},
|
||||
Name: "hyprspace",
|
||||
Short: "Hyprspace Distributed Network",
|
||||
Version: appVersion,
|
||||
Flags: &GlobalFlags{},
|
||||
}
|
||||
|
||||
cmd.Register(&cmd.Help)
|
||||
cmd.Register(&Init)
|
||||
cmd.Register(&Up)
|
||||
cmd.Register(&Down)
|
||||
cmd.Register(&Update)
|
||||
cmd.Register(&cmd.Version)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
|
56
cli/up.go
56
cli/up.go
@@ -3,11 +3,14 @@ package cli
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -75,15 +78,18 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
|
||||
if !flags.Foreground {
|
||||
// Make results chan
|
||||
out := make(chan bool)
|
||||
out := make(chan error)
|
||||
go createDaemon(out)
|
||||
|
||||
select {
|
||||
case <-out:
|
||||
case err = <-out:
|
||||
case <-time.After(30 * time.Second):
|
||||
}
|
||||
checkErr(err)
|
||||
fmt.Println("[+] Successfully Created Hyprspace Daemon")
|
||||
if err != nil {
|
||||
fmt.Println("[+] Failed to Create Hyprspace Daemon")
|
||||
} else {
|
||||
fmt.Println("[+] Successfully Created Hyprspace Daemon")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -96,7 +102,9 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
fmt.Println("[+] Creating TUN Device")
|
||||
// Create new TUN device
|
||||
iface, err = tun.New(Global.Interface.Name)
|
||||
checkErr(err)
|
||||
if err != nil {
|
||||
checkErr(errors.New("interface already in use"))
|
||||
}
|
||||
// Set TUN MTU
|
||||
tun.SetMTU(Global.Interface.Name, 1420)
|
||||
// Add Address to Interface
|
||||
@@ -106,8 +114,35 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
ctx := context.Background()
|
||||
|
||||
fmt.Println("[+] Creating LibP2P Node")
|
||||
|
||||
// Check that the listener port is available.
|
||||
var ln net.Listener
|
||||
port := Global.Interface.ListenPort
|
||||
if port != 8001 {
|
||||
ln, err = net.Listen("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
checkErr(errors.New("could not create node, listen port already in use by something else"))
|
||||
}
|
||||
} else {
|
||||
for {
|
||||
ln, err = net.Listen("tcp", ":"+strconv.Itoa(port))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if port >= 65535 {
|
||||
checkErr(errors.New("failed to find open port"))
|
||||
}
|
||||
port++
|
||||
}
|
||||
}
|
||||
if ln != nil {
|
||||
ln.Close()
|
||||
}
|
||||
// Create P2P Node
|
||||
host, dht, err := p2p.CreateNode(ctx, Global.Interface.PrivateKey, streamHandler)
|
||||
host, dht, err := p2p.CreateNode(ctx,
|
||||
Global.Interface.PrivateKey,
|
||||
port,
|
||||
streamHandler)
|
||||
checkErr(err)
|
||||
|
||||
// Setup Peer Table for Quick Packet --> Dest ID lookup
|
||||
@@ -162,7 +197,7 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
}
|
||||
}
|
||||
|
||||
func createDaemon(out chan<- bool) {
|
||||
func createDaemon(out chan<- error) {
|
||||
path, err := os.Executable()
|
||||
checkErr(err)
|
||||
// Create Pipe to monitor for daemon output.
|
||||
@@ -173,7 +208,7 @@ func createDaemon(out chan<- bool) {
|
||||
path,
|
||||
append(os.Args, "--foreground"),
|
||||
&os.ProcAttr{
|
||||
Files: []*os.File{nil, w, nil},
|
||||
Files: []*os.File{nil, w, w},
|
||||
},
|
||||
)
|
||||
checkErr(err)
|
||||
@@ -186,7 +221,10 @@ func createDaemon(out chan<- bool) {
|
||||
fmt.Println(scanner.Text())
|
||||
err = process.Release()
|
||||
checkErr(err)
|
||||
out <- true
|
||||
if count < 4 {
|
||||
out <- errors.New("failed to create daemon")
|
||||
}
|
||||
out <- nil
|
||||
}
|
||||
|
||||
func streamHandler(stream network.Stream) {
|
||||
|
@@ -14,8 +14,6 @@ import (
|
||||
"github.com/tcnksm/go-latest"
|
||||
)
|
||||
|
||||
var appVersion string
|
||||
|
||||
// Update checks for a new version of the Hyprspace program and updates itself
|
||||
// if a newer version is found and the user agrees to update.
|
||||
var Update = cmd.Sub{
|
||||
|
@@ -15,8 +15,9 @@ type Config struct {
|
||||
// Interface defines all of the fields that a local node needs to know about itself!
|
||||
type Interface struct {
|
||||
Name string `yaml:"name"`
|
||||
Address string `yaml:"address"`
|
||||
ID string `yaml:"id"`
|
||||
ListenPort int `yaml:"listen_port"`
|
||||
Address string `yaml:"address"`
|
||||
DiscoverKey string `yaml:"discover_key"`
|
||||
PrivateKey string `yaml:"private_key"`
|
||||
}
|
||||
@@ -32,6 +33,16 @@ func Read(path string) (result Config, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
result = Config{
|
||||
Interface: Interface{
|
||||
Name: "hs0",
|
||||
ListenPort: 8001,
|
||||
Address: "10.1.1.1",
|
||||
ID: "",
|
||||
DiscoverKey: "",
|
||||
PrivateKey: "",
|
||||
},
|
||||
}
|
||||
err = yaml.Unmarshal(in, &result)
|
||||
return
|
||||
}
|
||||
|
12
examples/systemd/hyprspace@.service
Normal file
12
examples/systemd/hyprspace@.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=hyprspace daemon for %i
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/hyprspace up %i --foreground
|
||||
ExecStop=/usr/local/bin/hyprspace down %i
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
1
go.mod
1
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
github.com/DataDrake/cli-ng/v2 v2.0.2
|
||||
github.com/hashicorp/go-version v1.2.1 // indirect
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf
|
||||
github.com/ipfs/go-datastore v0.4.5
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/libp2p/go-libp2p v0.14.1
|
||||
github.com/libp2p/go-libp2p-core v0.8.5
|
||||
|
@@ -18,7 +18,7 @@ func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, rendezvous str
|
||||
var routingDiscovery = discovery.NewRoutingDiscovery(dht)
|
||||
discovery.Advertise(ctx, routingDiscovery, rendezvous)
|
||||
|
||||
ticker := time.NewTicker(time.Second * 1)
|
||||
ticker := time.NewTicker(time.Second * 5)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
|
10
p2p/node.go
10
p2p/node.go
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
@@ -18,7 +19,7 @@ import (
|
||||
const Protocol = "/hyprspace/0.0.1"
|
||||
|
||||
// CreateNode creates an internal Libp2p nodes and returns it and it's DHT Discovery service.
|
||||
func CreateNode(ctx context.Context, inputKey string, handler network.StreamHandler) (node host.Host, dhtOut *dht.IpfsDHT, err error) {
|
||||
func CreateNode(ctx context.Context, inputKey string, port int, handler network.StreamHandler) (node host.Host, dhtOut *dht.IpfsDHT, err error) {
|
||||
// Unmarshal Private Key
|
||||
privateKey, err := crypto.UnmarshalPrivateKey([]byte(inputKey))
|
||||
if err != nil {
|
||||
@@ -27,7 +28,7 @@ func CreateNode(ctx context.Context, inputKey string, handler network.StreamHand
|
||||
|
||||
// Create libp2p node
|
||||
node, err = libp2p.New(ctx,
|
||||
libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", 8001)),
|
||||
libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", port)),
|
||||
libp2p.Identity(privateKey),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -38,10 +39,7 @@ func CreateNode(ctx context.Context, inputKey string, handler network.StreamHand
|
||||
node.SetStreamHandler(Protocol, handler)
|
||||
|
||||
// Create DHT Subsystem
|
||||
dhtOut, err = dht.New(ctx, node)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dhtOut = dht.NewDHTClient(ctx, node, datastore.NewMapDatastore())
|
||||
|
||||
// Define Bootstrap Nodes.
|
||||
peers := []string{
|
||||
|
Reference in New Issue
Block a user