Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f4a7b5abbe | ||
![]() |
53768270bd | ||
![]() |
0c59a57fc0 | ||
![]() |
d3fb8478b9 | ||
![]() |
e8b9a09992 | ||
![]() |
85a67189ff | ||
![]() |
91a21970ce | ||
![]() |
5b24c1d1bf | ||
![]() |
b5fe9d691d | ||
![]() |
76d27fbcfa | ||
![]() |
6eb4b47e37 | ||
![]() |
82ba8d357f | ||
![]() |
7601d9522a | ||
![]() |
bb76c3dd8e | ||
![]() |
0fb0eb6c62 | ||
![]() |
e4a73a7154 | ||
![]() |
021b1f861c | ||
![]() |
2dd65d83f3 | ||
![]() |
3a0d377a87 | ||
![]() |
8cc12939f8 | ||
![]() |
f10ca89b3b | ||
![]() |
91d1a9c23c | ||
![]() |
8a10ea99f6 | ||
![]() |
bb92e3e940 | ||
![]() |
ad2f73d48b |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
hyprspace
|
||||
hyprspace
|
||||
.DS_Store
|
70
README.md
70
README.md
@@ -1,28 +1,62 @@
|
||||
# Hyprspace
|
||||
<img src="hyprspace.png" width="300" height="300">
|
||||
Hyprspace is a Wireguard-like VPN built on top of Libp2p.
|
||||
|
||||
## What is Libp2p and Why Use it?
|
||||
[Libp2p](libp2p.io) is a networking library created by [Protocol Labs](https://protocol.ai) that allows nodes to discover eachother using a Distributed Hash Table. Paired with [NAT hole punching](https://en.wikipedia.org/wiki/Hole_punching_(networking)) this allows Hyprspace to create a direct encrypted tunnel between two nodes even if they're both behind firewalls.
|
||||
# Hyprspace
|
||||
[](https://goreportcard.com/report/github.com/hyprspace/hyprspace)
|
||||
|
||||
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)
|
||||
- [A Digital Nomad](#a-digital-nomad)
|
||||
- [A Privacy Advocate](#a-privacy-advocate)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [Commands](#commands)
|
||||
- [Tutorial](#tutorial)
|
||||
|
||||
## A Bit of Backstory
|
||||
[Libp2p](libp2p.io) is a networking library created by [Protocol Labs](https://protocol.ai) that allows nodes to discover each other using a Distributed Hash Table. Paired with [NAT hole punching](https://en.wikipedia.org/wiki/Hole_punching_(networking)) this allows Hyprspace to create a direct encrypted tunnel between two nodes even if they're both behind firewalls.
|
||||
|
||||
**Moreover! Each node doesn't even need to know the other's ip address prior to starting up the connection.** This makes Hyprspace perfect for devices that frequently migrate between locations but still require a constant virtual ip address.
|
||||
|
||||
### So How Does Hyprspace Compare to Something Like Wireguard?
|
||||
[Wireguard](https://wireguard.com) is an amazing VPN written by Jason A. Donenfeld. If you haven't already, definitely go check it out! Wireguard actually inspired me to write Hyprspace. That said, although Wireguard is in a class of it's own as a great VPN, it requires at least one of your nodes to have a public IP address. In this mode, as long as one of your nodes is publicly accessible, it can be used as a cental relay to reach the other nodes in the network. However, this means that all of the traffic for your entire system is going through that one system which can slow down your network and make it fragile in the case that node goes down and you loose the whole network. So instead say that you want each node to be able to directly connect to each other as they do in Hyprspace. Unfortunately through Wireguard this would require every node to be publicly addressable which means manual port forwarding and no travelling nodes.
|
||||
|
||||
By contrast Hyprspace allows all of your nodes to connect directly to each other creating a strong reliable network even if they're all behind their own firewalls. No manual port forwarding required!
|
||||
|
||||
## Use Cases:
|
||||
##### A Digital Nomad
|
||||
I use this system when travelling, if I'm staying in a rental or hotel and want to try something out on a Raspberry Pi I can plug the Pi into the location's router or ethernet port and then just ssh into the system using the same-old internal Hyprspace ip address without having to worry about their NAT or local firewall. Furthermore, if I'm connected to the Virtual Hyprspace Network I can ssh into my machines at home without requiring me to set up any sort of port forwarding.
|
||||
|
||||
##### A Privacy Advocate
|
||||
Honestly, I even use this system when I'm at home and could connect directly to my local infastructure. Using Hyprspace however, I don't have to trust the security of my local network and hyprspace will intelligently connect to my machines using their local ip addresses for maximum speed.
|
||||
Honestly, I even use this system when I'm at home and could connect directly to my local infrastructure. Using Hyprspace however, I don't have to trust the security of my local network and Hyprspace will intelligently connect to my machines using their local ip addresses for maximum speed.
|
||||
|
||||
If anyone else has some use cases please add them! Pull requests welcome!
|
||||
|
||||
## Installation
|
||||
| :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. |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
1. Go to Hyprspace Releases (other there -->)
|
||||
## 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,
|
||||
```bash
|
||||
brew install iproute2mac
|
||||
```
|
||||
|
||||
### Installation
|
||||
|
||||
1. Go to Hyprspace Releases (over there -->)
|
||||
2. Copy the link for your corresponding OS and Architecture.
|
||||
3. Run `sudo curl -L "PATH-TO-RELEASE" -o /usr/local/bin/hyprspace`
|
||||
4. Run `sudo chmod a+x /usr/local/bin/hyprspace`
|
||||
5. (Optional) Run `sudo ln -s /usr/local/bin/hyprspace /usr/bin/hyprspace`
|
||||
3. Run `sudo mkdir -p /usr/local/bin/`
|
||||
4. Run `sudo curl -L "PATH-TO-RELEASE" -o /usr/local/bin/hyprspace`
|
||||
5. Run `sudo chmod a+x /usr/local/bin/hyprspace`
|
||||
6. (Optional) Run `sudo ln -s /usr/local/bin/hyprspace /usr/bin/hyprspace`
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -34,7 +68,7 @@ If anyone else has some use cases please add them! Pull requests welcome!
|
||||
| `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
|
||||
|
||||
@@ -43,22 +77,24 @@ If anyone else has some use cases please add them! Pull requests welcome!
|
||||
The first thing we'll want to do once we've got Hyprspace installed is
|
||||
initialize the configuration for an interface. In this case we'll call the
|
||||
interface on our local machine `hs0` (for hypr-space 0) and `hs1` on our remote server
|
||||
but yours could be anything you'd like.
|
||||
but yours could be anything you'd like.
|
||||
|
||||
(Note: if you're using a Mac you'll have to use the interface name `utun[0-9]`. Check which interfaces are already in use by running `ip a` once you've got `iproute2mac` installed.)
|
||||
|
||||
###### Local Machine
|
||||
```bash
|
||||
hyprspace init hs0
|
||||
sudo hyprspace init hs0
|
||||
```
|
||||
|
||||
###### Remote Machine
|
||||
```bash
|
||||
hyprspace init hs1
|
||||
sudo hyprspace init hs1
|
||||
```
|
||||
|
||||
### Add Each Machine As A Peer Of The Other
|
||||
|
||||
Now that we've got a set of configurations we'll want to
|
||||
tell the machines about eachother. By default Hyprspace will
|
||||
tell the machines about each other. By default Hyprspace will
|
||||
put the interface configurations in `/etc/hyprspace/interface-name.yaml`.
|
||||
So for our example we'll run
|
||||
|
||||
@@ -99,7 +135,7 @@ address for the machine who needs to change to be `10.1.1.2`.
|
||||
Looking in the interface's configuration you'll also notice a field called
|
||||
`discover_key` (right above the interface's private key). It doesn't matter
|
||||
which discovery key you pick but it much be the same for all of the nodes in your little cluster
|
||||
so that they can find eachother.
|
||||
so that they can find each other.
|
||||
|
||||
(*Note you can use different `discover_key`s with different interfaces on the same
|
||||
host to create different isolated networks.)
|
||||
@@ -132,7 +168,7 @@ pinging back and forth across the network.
|
||||
ping 10.1.1.2
|
||||
```
|
||||
|
||||
### Stoping the Interface and Cleaning Up
|
||||
### Stopping the Interface and Cleaning Up
|
||||
Now to stop the interface and clean up the system you can run,
|
||||
|
||||
###### Local Machine
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/hyprspace/hyprspace/tun"
|
||||
)
|
||||
|
||||
// Pull downloads files from the Arken cluster.
|
||||
// Down brings down a Hyprspace interface and removes it from the system.
|
||||
var Down = cmd.Sub{
|
||||
Name: "down",
|
||||
Alias: "d",
|
||||
@@ -16,11 +16,12 @@ var Down = cmd.Sub{
|
||||
Run: DownRun,
|
||||
}
|
||||
|
||||
// UpArgs handles the specific arguments for the up command.
|
||||
// DownArgs handles the specific arguments for the down command.
|
||||
type DownArgs struct {
|
||||
InterfaceName string
|
||||
}
|
||||
|
||||
// DownRun handles the execution of the down command.
|
||||
func DownRun(r *cmd.Root, c *cmd.Sub) {
|
||||
// Parse Command Args
|
||||
args := c.Args.(*DownArgs)
|
||||
|
@@ -14,7 +14,7 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Pull downloads files from the Arken cluster.
|
||||
// Init creates a configuration for a Hyprspace Interface.
|
||||
var Init = cmd.Sub{
|
||||
Name: "init",
|
||||
Alias: "i",
|
||||
@@ -28,6 +28,7 @@ type InitArgs struct {
|
||||
InterfaceName string
|
||||
}
|
||||
|
||||
// InitRun handles the execution of the init command.
|
||||
func InitRun(r *cmd.Root, c *cmd.Sub) {
|
||||
// Parse Command Arguments
|
||||
args := c.Args.(*InitArgs)
|
||||
@@ -54,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: "hypr",
|
||||
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) {
|
||||
|
102
cli/up.go
102
cli/up.go
@@ -3,11 +3,14 @@ package cli
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -24,12 +27,18 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
Global config.Config
|
||||
iface *water.Interface
|
||||
// Global is the global interface configuration for the
|
||||
// application instance.
|
||||
Global config.Config
|
||||
// iface is the tun device used to pass packets between
|
||||
// Hyprspace and the user's machine.
|
||||
iface *water.Interface
|
||||
// RevLookup allow quick lookups of an incoming stream
|
||||
// for security before accepting or responding to any data.
|
||||
RevLookup map[string]bool
|
||||
)
|
||||
|
||||
// Pull downloads files from the Arken cluster.
|
||||
// Up creates and brings up a Hyprspace Interface.
|
||||
var Up = cmd.Sub{
|
||||
Name: "up",
|
||||
Alias: "up",
|
||||
@@ -44,10 +53,12 @@ type UpArgs struct {
|
||||
InterfaceName string
|
||||
}
|
||||
|
||||
// UpFlags handles the specific flags for the up command.
|
||||
type UpFlags struct {
|
||||
Forground bool `short:"f" long:"forground" desc:"Don't Create Background Daemon."`
|
||||
Foreground bool `short:"f" long:"foreground" desc:"Don't Create Background Daemon."`
|
||||
}
|
||||
|
||||
// UpRun handles the execution of the up command.
|
||||
func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
// Parse Command Args
|
||||
args := c.Args.(*UpArgs)
|
||||
@@ -65,17 +76,20 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
Global, err := config.Read(configPath)
|
||||
checkErr(err)
|
||||
|
||||
if !flags.Forground {
|
||||
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("[+] Sucessfully Created Hyprspace Daemon")
|
||||
if err != nil {
|
||||
fmt.Println("[+] Failed to Create Hyprspace Daemon")
|
||||
} else {
|
||||
fmt.Println("[+] Successfully Created Hyprspace Daemon")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -88,9 +102,11 @@ 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, 1500)
|
||||
tun.SetMTU(Global.Interface.Name, 1420)
|
||||
// Add Address to Interface
|
||||
tun.SetAddress(Global.Interface.Name, Global.Interface.Address)
|
||||
|
||||
@@ -98,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
|
||||
@@ -133,28 +176,28 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||
|
||||
fmt.Println("[+] Network Setup Complete...Waiting on Node Discovery")
|
||||
// Listen For New Packets on TUN Interface
|
||||
packet := make([]byte, 1500)
|
||||
packet := make([]byte, 1420)
|
||||
var stream network.Stream
|
||||
var header *ipv4.Header
|
||||
var plen int
|
||||
for {
|
||||
plen, err := iface.Read(packet)
|
||||
plen, err = iface.Read(packet)
|
||||
checkErr(err)
|
||||
header, _ := ipv4.ParseHeader(packet[:plen])
|
||||
header, _ = ipv4.ParseHeader(packet)
|
||||
_, ok := Global.Peers[header.Dst.String()]
|
||||
if ok {
|
||||
stream, err := host.NewStream(context.Background(), peerTable[header.Dst.String()], p2p.Protocol)
|
||||
stream, err = host.NewStream(ctx, peerTable[header.Dst.String()], p2p.Protocol)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
stream.Write(packet[:plen])
|
||||
stream.Close()
|
||||
}()
|
||||
stream.Write(packet[:plen])
|
||||
stream.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createDaemon(out chan<- bool) {
|
||||
func createDaemon(out chan<- error) {
|
||||
path, err := os.Executable()
|
||||
checkErr(err)
|
||||
// Create Pipe to monitor for daemon output.
|
||||
@@ -163,9 +206,9 @@ func createDaemon(out chan<- bool) {
|
||||
// Create Sub Process
|
||||
process, err := os.StartProcess(
|
||||
path,
|
||||
append(os.Args, "--forground"),
|
||||
append(os.Args, "--foreground"),
|
||||
&os.ProcAttr{
|
||||
Files: []*os.File{nil, w, nil},
|
||||
Files: []*os.File{nil, w, w},
|
||||
},
|
||||
)
|
||||
checkErr(err)
|
||||
@@ -178,13 +221,16 @@ 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) {
|
||||
// If the remote node ID isn't in the list of known nodes don't respond.
|
||||
if _, ok := RevLookup[stream.Conn().RemotePeer().Pretty()]; !ok {
|
||||
stream.Close()
|
||||
stream.Reset()
|
||||
}
|
||||
io.Copy(iface.ReadWriteCloser, stream)
|
||||
stream.Close()
|
||||
@@ -195,7 +241,7 @@ func prettyDiscovery(ctx context.Context, node host.Host, peerTable map[string]p
|
||||
for ip, id := range peerTable {
|
||||
tempTable[ip] = id
|
||||
}
|
||||
for len(peerTable) > 0 {
|
||||
for len(tempTable) > 0 {
|
||||
for ip, id := range tempTable {
|
||||
stream, err := node.NewStream(ctx, id, p2p.Protocol)
|
||||
if err != nil && (strings.HasPrefix(err.Error(), "failed to dial") ||
|
||||
@@ -204,7 +250,7 @@ func prettyDiscovery(ctx context.Context, node host.Host, peerTable map[string]p
|
||||
continue
|
||||
}
|
||||
if err == nil {
|
||||
fmt.Printf("[+] Connection to %s Sucessful. Network Ready.\n", ip)
|
||||
fmt.Printf("[+] Connection to %s Successful. Network Ready.\n", ip)
|
||||
stream.Close()
|
||||
}
|
||||
delete(tempTable, ip)
|
||||
|
@@ -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{
|
||||
|
@@ -6,29 +6,43 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Config is the main Configuration Struct for Hyprspace.
|
||||
type Config struct {
|
||||
Interface Interface `yaml:"interface"`
|
||||
Peers map[string]Peer `yaml:"peers"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// Peer defines a peer in the configuration. We might add more to this later.
|
||||
type Peer struct {
|
||||
ID string `yaml:"id"`
|
||||
}
|
||||
|
||||
// Read initalizes a config from a file.
|
||||
// Read initializes a config from a file.
|
||||
func Read(path string) (result Config, err error) {
|
||||
in, err := os.ReadFile(path)
|
||||
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
|
@@ -13,11 +13,12 @@ import (
|
||||
dht "github.com/libp2p/go-libp2p-kad-dht"
|
||||
)
|
||||
|
||||
// Discover starts up a DHT based discovery system finding and adding nodes with the same rendezvous string.
|
||||
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, rendezvous string, peerTable map[string]peer.ID) {
|
||||
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 {
|
||||
|
@@ -14,10 +14,12 @@ import (
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Protocol is a descriptor for the Hyprspace P2P Protocol.
|
||||
const Protocol = "/hyprspace/0.0.1"
|
||||
|
||||
func CreateNode(ctx context.Context, inputKey string, handler network.StreamHandler) (node host.Host, dhtOut *dht.IpfsDHT, err error) {
|
||||
// Unmarshall Private Key
|
||||
// CreateNode creates an internal Libp2p nodes and returns it and it's DHT Discovery service.
|
||||
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 {
|
||||
return
|
||||
@@ -25,7 +27,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 {
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
|
||||
// New creates and returns a new TUN interface for the application.
|
||||
func New(name string) (result *water.Interface, err error) {
|
||||
// Setup TUN Config
|
||||
cfg := water.Config{
|
||||
@@ -18,22 +19,28 @@ func New(name string) (result *water.Interface, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||
// Packet on the interface.
|
||||
func SetMTU(name string, mtu int) (err error) {
|
||||
return ip("link", "set", "dev", name, "mtu", fmt.Sprintf("%d", mtu))
|
||||
}
|
||||
|
||||
// SetAddress sets the interface's known address and subnet.
|
||||
func SetAddress(name string, address string) (err error) {
|
||||
return ip("addr", "add", address, "dev", name)
|
||||
}
|
||||
|
||||
// Up brings up an interface to allow it to start accepting connections.
|
||||
func Up(name string) (err error) {
|
||||
return ip("link", "set", "dev", name, "up")
|
||||
}
|
||||
|
||||
// Down brings down an interface stopping active connections.
|
||||
func Down(name string) (err error) {
|
||||
return ip("link", "set", "dev", name, "down")
|
||||
}
|
||||
|
||||
// Delete removes a TUN device from the host.
|
||||
func Delete(name string) (err error) {
|
||||
return ip("link", "delete", "dev", name)
|
||||
}
|
||||
|
Reference in New Issue
Block a user