Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Add multiples routes options #95

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
hyprspace
.DS_Store
.DS_Store
release
92 changes: 79 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<img src="hyprspace.png" width="250">

# Hyprspace

[![Go Report Card](https://goreportcard.com/badge/github.com/hyprspace/hyprspace)](https://goreportcard.com/report/github.com/hyprspace/hyprspace)
[![](https://img.shields.io/matrix/hyprspace:matrix.org)](https://matrix.to/#/%23hyprspace:matrix.org)

A Lightweight VPN Built on top of IPFS & Libp2p for Truly Distributed Networks.

https://user-images.githubusercontent.com/19558067/152407636-a5f4ae1f-9493-4346-bf73-0de109928415.mp4
A Lightweight VPN Built on top of IPFS & Libp2p for Truly Distributed Networks.

<https://user-images.githubusercontent.com/19558067/152407636-a5f4ae1f-9493-4346-bf73-0de109928415.mp4>

## Table of Contents

- [A Bit of Backstory](#a-bit-of-backstory)
- [Use Cases](#use-cases)
- [A Digital Nomad](#a-digital-nomad)
Expand All @@ -21,20 +22,25 @@ https://user-images.githubusercontent.com/19558067/152407636-a5f4ae1f-9493-4346-
- [Tutorial](#tutorial)

## A Bit of Backstory

[Libp2p](https://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 its 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 central 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 lose 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 NATs/firewalls. No manual port forwarding required!
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 NATs/firewalls. No manual port forwarding required!

## Use Cases

## 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 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!
Expand All @@ -51,7 +57,8 @@ If you're running Hyprspace on Windows you'll need to install [tap-windows](http
### Installation

#### Automatic (Linux & MacOS)
```

```shell
curl -L https://hyprspace.io/install.sh | bash
```

Expand All @@ -73,34 +80,37 @@ curl -L https://hyprspace.io/install.sh | bash
| `help` | `?` | Get help with a specific subcommand. |
| `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 |
| `down` | `d` | Bring Down and Delete A Hyprspace Interface. |
| `update` | `upd` | Have Hyprspace update its own binary to the latest release. |
| `add` | `add` | Add Peer Address to the interface's configuration. |

### Global Flags

| Flag | Alias | Description |
| ------------------- | ------- | -------------------------------------------------------------------------- |
| `--config` | `-c` | Specify the path to a hyprspace config for an interface. |


## Tutorial

### Initializing an Interface

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.)

(Note: if you're using Windows you'll have to use the interface name as seen in Control Panel. IP address will be set automatically only if you run Hyprspace as Administrator.)

###### Local Machine

```bash
sudo hyprspace init hs0
```

###### Remote Machine

```bash
sudo hyprspace init hs1
```
Expand All @@ -113,13 +123,15 @@ put the interface configurations in `/etc/hyprspace/interface-name.yaml`.
So for our example we'll run

###### Local Machine

```bash
sudo nano /etc/hyprspace/hs0.yaml
```

and

###### Remote Machine

```bash
sudo nano /etc/hyprspace/hs1.yaml
```
Expand All @@ -133,28 +145,35 @@ Update,
```yaml
peers: {}
```
to

to

```yaml
peers:
10.1.1.2:
id: YOUR-OTHER-PEER-ID
```

Notice here we'll have to pick one of our machines to be `10.1.1.1`
Notice here we'll have to pick one of our machines to be `10.1.1.1`
and the other to be `10.1.1.2`. Make sure to update the interface's IP
address for the machine who needs to change to be `10.1.1.2`.

### Starting Up the Interfaces!
> As well can be done using `add` command

### Starting Up the Interfaces

Now that we've got our configs all sorted we can start up the two interfaces!

###### Local Machine

```bash
sudo hyprspace up hs0
```

and

###### Remote Machine

```bash
sudo hyprspace up hs1
```
Expand All @@ -164,21 +183,25 @@ and find your other machine. We can now test the connection by
pinging back and forth across the network.

###### Local Machine

```bash
ping 10.1.1.2
```

### Stopping the Interface and Cleaning Up

Now to stop the interface and clean up the system you can run,

###### Local Machine

```bash
sudo hyprspace down hs0
```

and,

###### Remote Machine

```bash
sudo hyprspace down hs1
```
Expand All @@ -187,6 +210,49 @@ sudo hyprspace down hs1

WireGuard is a registered trademark of Jason A. Donenfeld.


## Routes

### Prepare each route node:

```
# sysctl -n net.ipv4.ip_forward
0
# sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s <YOUR_TUN_NET>/24 -o eth0 -j MASQUERADE
iptables -A FORWARD 1 -i <HS_TUN> -o <DEV_GATEWAY> -j ACCEPT
iptables -A FORWARD 1 -i <DEV_GATEWAY> -o <HS_TUN> -j ACCEPT

```
Determine gateway router:
```
# curl ifconfg.me
<GATEWAY_ROUTER>
```

### Configure client:
Config hyprspace yaml configuration file:
```
interface:
...
peers:
ID: ...
...
routes:
192.168.3.0/24:
ip: 10.0.0.3
0.0.0.0/0:
ip: 10.0.0.1

```
Prepare routes
```
One for each route:
# ip route add <GATEWAY_ROUTER> via <YOUR_GATEWAY>

And all traffic for hyprspace tun
# ip route add default dev <HS_TUN> metric 1
```
## License

Copyright 2021-2022 Alec Scott <[email protected]>
Expand All @@ -195,7 +261,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
<http://www.apache.org/licenses/LICENSE-2.0>

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
83 changes: 83 additions & 0 deletions cli/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package cli

import (
"fmt"
"net"
"os"

"github.com/DataDrake/cli-ng/v2/cmd"
"github.com/hyprspace/hyprspace/config"
"github.com/libp2p/go-libp2p/core/peer"
"gopkg.in/yaml.v2"
)

var Add = cmd.Sub{
Name: "add",
Alias: "add",
Short: "Add Peer to Hyprspace Interface",
Args: &AddArgs{},
Flags: &AddFlags{},
Run: AddRun,
}

type AddArgs struct {
InterfaceName string
Address string
ID string
}

type AddFlags struct {
Overwrite bool `long:"overwrite" desc:"Overwrite existing Address"`
}

func AddRun(r *cmd.Root, c *cmd.Sub) {
// Parse Command Args
args := c.Args.(*AddArgs)

// Parse Command Flags
flags := c.Flags.(*AddFlags)

if net.ParseIP(args.Address).String() == "<nil>" {
fmt.Printf("%s is not a valid ip address\n", args.Address)
return
}

// Parse Global Config Flag for Custom Config Path
configPath := r.Flags.(*GlobalFlags).Config
if configPath == "" {
configPath = "/etc/hyprspace/" + args.InterfaceName + ".yaml"
}

// Read in configuration from file.
cfg, err := config.Read(configPath)
checkErr(err)

if id, exists := cfg.Peers[args.Address]; exists && !flags.Overwrite {
fmt.Printf("Address %s is already used by Peer(%s).\nUse --overwrite flag if you'd like to do so.\n", args.Address, id.ID)
return
}

_, err = peer.Decode(args.ID)
if err != nil {
fmt.Printf("%s is not a valid Peer ID: %v\n", args.ID, err)
return
}

cfg.Peers[args.Address] = config.Peer{ID: args.ID}
out, err := yaml.Marshal(cfg)
checkErr(err)

// Backup current config
err = os.Rename(configPath, configPath+".backup")
checkErr(err)

f, err := os.Create(configPath)
checkErr(err)

// Write out config to file.
_, err = f.Write(out)
checkErr(err)

fmt.Printf("Successfuly added new Peer to the config at %s\n", configPath)
fmt.Println("To Apply changes restart Hyprspace daemon")
}
51 changes: 51 additions & 0 deletions cli/id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cli

import (
"fmt"
"strings"

"github.com/DataDrake/cli-ng/v2/cmd"
"github.com/hyprspace/hyprspace/config"
)

var Id = cmd.Sub{
Name: "id",
Alias: "this",
Short: "Print this Node's Peer ID for given Interface",
Args: &UpArgs{},
Flags: &IdFlags{},
Run: IdRun,
}

type IdFlags struct {
Yaml bool `long:"yaml" desc:"Print info as an Interface YAML config chunk"`
Cmd bool `long:"cmd" desc:"Print info as add command arguments"`
}

func IdRun(r *cmd.Root, c *cmd.Sub) {
// Parse Command Args
args := c.Args.(*UpArgs)

// Parse Command Flags
flags := c.Flags.(*IdFlags)

// Parse Global Config Flag for Custom Config Path
configPath := r.Flags.(*GlobalFlags).Config
if configPath == "" {
configPath = "/etc/hyprspace/" + args.InterfaceName + ".yaml"
}

// Read in configuration from file.
cfg, err := config.Read(configPath)
checkErr(err)

addr := strings.Split(cfg.Interface.Address, "/")[0]

if flags.Yaml {
fmt.Printf(" %s:\n id: %s\n", addr, cfg.Interface.ID)
} else if flags.Cmd {
fmt.Printf("%s %s %s\n", cfg.Interface.Name, addr, cfg.Interface.ID)
} else {
fmt.Printf("Peer ID: %s\nAddress: %s\n", cfg.Interface.ID, addr)
}
}
2 changes: 1 addition & 1 deletion cli/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/DataDrake/cli-ng/v2/cmd"
"github.com/hyprspace/hyprspace/config"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p/core/crypto"
"gopkg.in/yaml.v2"
)

Expand Down
Loading