Compare commits

...

36 Commits

Author SHA1 Message Date
Mikhail Bragin
0b2c26847b fix: return ctx error when UP command exists (#140) 2021-10-26 21:49:05 +02:00
braginini
595ea0d4f8 chore: decrease log verbosity 2021-10-26 10:08:28 +02:00
Maycon Santos
f714868fdd remove arch if and replacement for debian packages (#138) 2021-10-23 10:29:49 +02:00
Mikhail Bragin
81821a1f39 docs: update diagram and Wireguard title (#137)
* docs: update diagram and Wireguard title
2021-10-21 10:06:29 +02:00
mlsmaycon
842b143a48 sync go.sum 2021-10-20 21:57:16 +02:00
Maycon Santos
1323a74db0 fix: avoid failing and extra error messages (#136)
* avoid failing and extra error messages

* avoid extra error messages when executed after pre_remove.sh

* remove extra output and avoid failure on minor errors

* ensure the steps will run only on remove
2021-10-20 11:51:32 +02:00
Mikhail Bragin
74485d3b13 fix: service hanging when error on startup has been encountered (#135) 2021-10-18 13:29:26 +02:00
Mikhail Bragin
bef3b3392b fix: graceful shutdown (#134)
* fix: graceful shutdown

* fix: windows graceful shutdown
2021-10-17 22:15:38 +02:00
Maycon Santos
fcea3c99d4 Enhance up command (#133)
* move setup-key to root command

* up will check login and start service

* update tests to reflect new UP capabilities

* display client IP

* removed unused argument

* install service if not installed

* update post-install and add pre remove script

* improve log messages

* handle service status failures and install service when needed

* removing unused files

* update documentation and description

* add version command

* update service lib version

* using lib constant for not installed services

* match version from goreleaser

* fix: graceful shutdown

* stop only if service is running

* add logs initialization to service controller commands

Co-authored-by: braginini <bangvalo@gmail.com>
2021-10-17 21:34:07 +02:00
Mikhail Bragin
96799a25b5 docs: fix gif size 2021-10-16 16:54:37 +02:00
Mikhail Bragin
07291cdb93 docs: update readme (#132)
* update readme
2021-10-16 16:53:39 +02:00
Mikhail Bragin
21139938c1 docs: highlight Slack channel 2021-10-12 14:37:49 +02:00
Maycon Santos
5cf2d0a6a9 add slack invitation link (#129) 2021-10-12 12:16:09 +02:00
Maycon Santos
8551afe04e enhancement: Support new architectures and auto upload packages to repo (#128)
* adding uploads

* adding uploads

* adding uploads

* adding uploads

* adding uploads

* adding uploads

* use https://pkgs.wiretrustee.com/

* use https://pkgs.wiretrustee.com/

* use https://pkgs.wiretrustee.com/

* set yum id

* secrets for goreleaser uploads

* ensure Github release is enabled
2021-10-12 12:15:45 +02:00
braginini
1685817171 docs: correct installation steps 2021-10-03 18:55:47 +02:00
Mikhail Bragin
e17f662683 docs: update intro (#125)
* docs: update intro
2021-10-03 18:21:41 +02:00
Mikhail Bragin
a764fb870c docs: move intro link up in readme 2021-09-27 09:23:19 +02:00
Mikhail Bragin
cabff941ac docs: add self-hosting video 2021-09-26 16:49:59 +02:00
Mikhail Bragin
b5f35dfb5e docs: replace beta with app.wiretrustee.com (#123)
* docs: replace beta with app.wiretrustee.com

* docs: add Signal port to the list of the open ports

* docs: minor corrections
2021-09-26 11:44:34 +02:00
braginini
1d426b7f81 docs: fix docker-compose management image 2021-09-25 20:17:01 +02:00
Maycon Santos
e4f9406d44 Removed installer and add workflow dispatch (#120) 2021-09-25 19:30:12 +02:00
braginini
7c79ff62ee fix: coturn port 2021-09-25 19:29:43 +02:00
Mikhail Bragin
32c369257b management/support cert from file (#122)
* feature: support cert file in management service

* docs: add new management commands
2021-09-25 19:22:49 +02:00
Mikhail Bragin
08dd719aa1 self-hosting guide (#121)
* docs: first steps of the self-hosting guide

* feature: add setup configurator for the self-hosted guide

* docs: add setup.env comments

* docs: simplify installation steps - support ./configure.sh

* docs: fix file references

* docs: fix minor docs issues

* docs: remove unused title
2021-09-25 19:12:05 +02:00
Mikhail Bragin
84c714dd93 Update quickstart.md 2021-09-23 14:39:55 +02:00
Mikhail Bragin
996c8d7c62 docs: referer to the new video 2021-09-23 14:38:51 +02:00
Mikhail Bragin
25e68ce493 docs: fix broken intro link 2021-09-22 14:18:48 +02:00
Mikhail Bragin
4881dcbd51 docs: add Getting Started hosted version guide (#119)
* docs: add Getting Started hosted version guide

* docs: fix screenshot sizes

* docs: self-hosting section

* docs: increase screenshots width

* docs: reference getting started from main readme

* docs: add refs to sections

* docs: move docs to a separate folder

* docs: add intro

* docs: correct intro docs

* docs: correct image location

* docs: correct language
2021-09-22 14:16:46 +02:00
Mikhail Bragin
d505f70972 Update README.md 2021-09-13 08:50:15 +02:00
Mikhail Bragin
6a80684378 docs: add slack 2021-09-13 08:18:18 +02:00
Mikhail Bragin
2624a7c4e6 docs: update Auth0 notes 2021-09-13 08:06:28 +02:00
Mikhail Bragin
9a412e7bf1 Update README.md 2021-09-13 07:58:52 +02:00
Mikhail Bragin
b5d1690129 Update README.md 2021-09-12 20:38:26 +02:00
Mikhail Bragin
d4bec15ca3 Update README.md 2021-09-12 20:37:55 +02:00
Mikhail Bragin
3212aca7c7 docs: add reference to auth0 react guide 2021-09-12 09:39:03 +03:00
Mikhail Bragin
b97a2251d3 fix docker compose signal volume 2021-09-12 09:08:55 +03:00
47 changed files with 952 additions and 451 deletions

View File

@@ -51,28 +51,15 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
UPLOAD_DEBIAN_SECRET: ${{ secrets.PKG_UPLOAD_SECRET }}
UPLOAD_YUM_SECRET: ${{ secrets.PKG_UPLOAD_SECRET }}
- -
id: get_version name: Trigger Windows binaries sign pipeline
uses: battila7/get-version-action@v2 uses: benc-uk/workflow-dispatch@v1
-
name: Install makensis
run: sudo apt update && sudo apt install -y nsis nsis-pluginapi
-
name: Download EnvVar Plugin
run: curl -L -o EnVar_plugin.zip https://nsis.sourceforge.io/mediawiki/images/7/7f/EnVar_plugin.zip
-
name: Extract EnVar plugin
run: sudo 7z x -o"/usr/share/nsis/" EnVar_plugin.zip
-
name: Generate Windows installer
run: makensis -V4 client/installer.nsis
env:
APPVER: ${{ steps.get_version.outputs.major }}.${{ steps.get_version.outputs.minor }}.${{ steps.get_version.outputs.patch }}.${{ github.run_id }}
-
name: Upload windows installer to release page
uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} workflow: Sign windows bin and installer
file: wiretrustee-installer.exe repo: wiretrustee/windows-sign-pipeline
asset_name: wiretrustee_installer_${{ steps.get_version.outputs.version-without-v }}_windows_amd64.exe ref: v0.0.1
tag: ${{ github.ref }} token: ${{ secrets.SIGN_GITHUB_TOKEN }}
inputs: '{ "tag": "${{ github.ref }}" }'

4
.gitignore vendored
View File

@@ -3,4 +3,6 @@
dist/ dist/
.env .env
conf.json conf.json
http-cmds.sh http-cmds.sh
infrastructure_files/management.json
infrastructure_files/docker-compose.yml

View File

@@ -13,13 +13,18 @@ builds:
- arm - arm
- amd64 - amd64
- arm64 - arm64
- mips
gomips:
- hardfloat
- softfloat
ignore: ignore:
- goos: darwin
goarch: arm64
- goos: windows - goos: windows
goarch: arm64 goarch: arm64
- goos: windows - goos: windows
goarch: arm goarch: arm
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser
mod_timestamp: '{{ .CommitTimestamp }}'
tags: tags:
- load_wintun_from_rsrc - load_wintun_from_rsrc
@@ -32,6 +37,9 @@ builds:
goarch: goarch:
- amd64 - amd64
- arm64 - arm64
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser
mod_timestamp: '{{ .CommitTimestamp }}'
- id: wiretrustee-signal - id: wiretrustee-signal
dir: signal dir: signal
@@ -42,28 +50,38 @@ builds:
goarch: goarch:
- amd64 - amd64
- arm64 - arm64
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser
mod_timestamp: '{{ .CommitTimestamp }}'
archives: archives:
- builds: - builds:
- wiretrustee - wiretrustee
nfpms: nfpms:
- maintainer: Wiretrustee <wiretrustee@wiretrustee.com> - maintainer: Wiretrustee <dev@wiretrustee.com>
description: Wiretrustee project. description: Wiretrustee client.
homepage: https://wiretrustee.com/ homepage: https://wiretrustee.com/
id: deb
builds: builds:
- wiretrustee - wiretrustee
formats: formats:
- deb - deb
- rpm
contents:
- src: release_files/wiretrustee.service
dst: /lib/systemd/system/wiretrustee.service
- src: release_files/wiretrustee.json
dst: /etc/wiretrustee/wiretrustee.json
type: "config|noreplace"
scripts: scripts:
postinstall: "release_files/post_install.sh" postinstall: "release_files/post_install.sh"
preremove: "release_files/pre_remove.sh"
- maintainer: Wiretrustee <dev@wiretrustee.com>
description: Wiretrustee client.
homepage: https://wiretrustee.com/
id: rpm
builds:
- wiretrustee
formats:
- rpm
scripts:
postinstall: "release_files/post_install.sh"
preremove: "release_files/pre_remove.sh"
dockers: dockers:
- image_templates: - image_templates:
- wiretrustee/signal:{{ .Version }}-amd64 - wiretrustee/signal:{{ .Version }}-amd64
@@ -196,4 +214,20 @@ brews:
homepage: https://wiretrustee.com/ homepage: https://wiretrustee.com/
license: "BSD3" license: "BSD3"
test: | test: |
system "#{bin}/{{ .ProjectName }} -h" system "#{bin}/{{ .ProjectName }} -h"
uploads:
- name: debian
ids:
- deb
mode: archive
target: https://pkgs.wiretrustee.com/debian/pool/{{ .ArtifactName }};deb.distribution=stable;deb.component=main;deb.architecture={{ .Arch }}
username: dev@wiretrustee.com
method: PUT
- name: yum
ids:
- rpm
mode: archive
target: https://pkgs.wiretrustee.com/yum/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}
username: dev@wiretrustee.com
method: PUT

204
README.md
View File

@@ -1,15 +1,50 @@
# Wiretrustee <div align="center">
A WireGuard®-based mesh network that connects your devices into a single private network. <p align="center">
<img width="250" src="docs/media/logo-full.png"/>
</p>
<p>
<img src="https://img.shields.io/badge/license-BSD--3-blue" />
<img src="https://img.shields.io/docker/pulls/wiretrustee/management" />
<img src="https://badgen.net/badge/Open%20Source%3F/Yes%21/blue?icon=github" />
</p>
</div>
<p align="center">
<strong>
Start using Wiretrustee at <a href="https://app.wiretrustee.com/">app.wiretrustee.com</a>
<br/>
See <a href="docs/README.md">Documentation</a>
<br/>
Join our <a href="https://join.slack.com/t/wiretrustee/shared_invite/zt-vrahf41g-ik1v7fV8du6t0RwxSrJ96A">Slack channel</a>
<br/>
</strong>
</p>
<br>
**Wiretrustee is an open-source VPN platform built on top of WireGuard® making it easy to create secure private networks for your organization or home.**
It requires zero configuration effort leaving behind the hassle of opening ports, complex firewall rules, vpn gateways, and so forth.
There is no centralized VPN server with Wiretrustee - your computers, devices, machines, and servers connect to each other directly over a fast encrypted tunnel.
### Secure peer-to-peer VPN in minutes
<p float="left" align="middle">
<img src="docs/media/peerA.gif" width="400"/>
<img src="docs/media/peerB.gif" width="400"/>
</p>
**Note**: The `main` branch may be in an *unstable or even broken state* during development. For stable versions, see [releases](https://github.com/wiretrustee/wiretrustee/releases). **Note**: The `main` branch may be in an *unstable or even broken state* during development. For stable versions, see [releases](https://github.com/wiretrustee/wiretrustee/releases).
**Hosted demo version:** [https://beta.wiretrustee.com/](https://beta.wiretrustee.com/peers) Hosted demo version:
[https://app.wiretrustee.com/](https://app.wiretrustee.com/peers).
Please don't use the hosted demonstration version for production purposes.
[UI Dashboard Repo](https://github.com/wiretrustee/wiretrustee-dashboard) [UI Dashboard Repo](https://github.com/wiretrustee/wiretrustee-dashboard)
### Why using Wiretrustee? ### Why using Wiretrustee?
* Connect multiple devices to each other via a secure peer-to-peer Wireguard VPN tunnel. At home, the office, or anywhere else. * Connect multiple devices to each other via a secure peer-to-peer Wireguard VPN tunnel. At home, the office, or anywhere else.
@@ -25,8 +60,6 @@ Please don't use the hosted demonstration version for production purposes.
* Works on ARM devices (e.g. Raspberry Pi). * Works on ARM devices (e.g. Raspberry Pi).
* Open-source (including Management Service) * Open-source (including Management Service)
### Secure peer-to-peer VPN in minutes
![animation](media/peers.gif)
### A bit on Wiretrustee internals ### A bit on Wiretrustee internals
* Wiretrustee features a Management Service that offers peer IP management and network updates distribution (e.g. when new peer joins the network). * Wiretrustee features a Management Service that offers peer IP management and network updates distribution (e.g. when new peer joins the network).
@@ -44,116 +77,119 @@ Please don't use the hosted demonstration version for production purposes.
### Client Installation ### Client Installation
#### Linux #### Linux
1. Checkout Wiretrustee [releases](https://github.com/wiretrustee/wiretrustee/releases)
2. Download the latest release (**Switch VERSION to the latest**):
**Debian packages** **APT/Debian**
```shell 1. Add the repository:
wget https://github.com/wiretrustee/wiretrustee/releases/download/v<VERSION>/wiretrustee_<VERSION>_linux_amd64.deb ```shell
``` sudo apt-get update
3. Install the package sudo apt-get install ca-certificates curl gnupg -y
```shell curl -L https://pkgs.wiretrustee.com/debian/public.key | sudo apt-key add -
sudo dpkg -i wiretrustee_<VERSION>_linux_amd64.deb echo 'deb https://pkgs.wiretrustee.com/debian stable main' | sudo tee /etc/apt/sources.list.d/wiretrustee.list
``` ```
**Fedora/Centos packages** 2. Install the package
```shell ```shell
wget https://github.com/wiretrustee/wiretrustee/releases/download/v<VERSION>/wiretrustee_<VERSION>_linux_amd64.rpm sudo apt-get update
``` sudo apt-get install wiretrustee
3. Install the package ```
```shell **RPM/Red hat**
sudo rpm -i wiretrustee_<VERSION>_linux_amd64.rpm 1. Add the repository:
``` ```shell
cat <<EOF | sudo tee /etc/yum.repos.d/wiretrustee.repo
[Wiretrustee]
name=Wiretrustee
baseurl=https://pkgs.wiretrustee.com/yum/
enabled=1
gpgcheck=0
gpgkey=https://pkgs.wiretrustee.com/yum/repodata/repomd.xml.key
repo_gpgcheck=1
EOF
```
2. Install the package
```shell
sudo yum install wiretrustee
```
#### MACOS #### MACOS
**Brew install** **Brew install**
1. Download and install Brew at https://brew.sh/ 1. Download and install Brew at https://brew.sh/
2. Install the client 2. Install the client
```shell ```shell
brew install wiretrustee/client/wiretrustee brew install wiretrustee/client/wiretrustee
``` ```
**Installation from binary** **Installation from binary**
1. Checkout Wiretrustee [releases](https://github.com/wiretrustee/wiretrustee/releases/latest) 1. Checkout Wiretrustee [releases](https://github.com/wiretrustee/wiretrustee/releases/latest)
2. Download the latest release (**Switch VERSION to the latest**): 2. Download the latest release (**Switch VERSION to the latest**):
```shell ```shell
curl -o ./wiretrustee_<VERSION>_darwin_amd64.tar.gz https://github.com/wiretrustee/wiretrustee/releases/download/v<VERSION>/wiretrustee_<VERSION>_darwin_amd64.tar.gz curl -o ./wiretrustee_<VERSION>_darwin_amd64.tar.gz https://github.com/wiretrustee/wiretrustee/releases/download/v<VERSION>/wiretrustee_<VERSION>_darwin_amd64.tar.gz
``` ```
3. Decompress 3. Decompress
```shell ```shell
tar xcf ./wiretrustee_<VERSION>_darwin_amd64.tar.gz tar xcf ./wiretrustee_<VERSION>_darwin_amd64.tar.gz
sudo mv wiretrusee /usr/local/bin/wiretrustee sudo mv wiretrusee /usr/local/bin/wiretrustee
chmod +x /usr/local/bin/wiretrustee chmod +x /usr/local/bin/wiretrustee
``` ```
After that you may need to add /usr/local/bin in your MAC's PATH environment variable: After that you may need to add /usr/local/bin in your MAC's PATH environment variable:
````shell ````shell
export PATH=$PATH:/usr/local/bin export PATH=$PATH:/usr/local/bin
```` ````
#### Windows #### Windows
1. Checkout Wiretrustee [releases](https://github.com/wiretrustee/wiretrustee/releases/latest) 1. Checkout Wiretrustee [releases](https://github.com/wiretrustee/wiretrustee/releases/latest)
2. Download the latest Windows release installer ```wiretrustee_installer_<VERSION>_windows_amd64.exe``` (**Switch VERSION to the latest**): 2. Download the latest Windows release installer ```wiretrustee_installer_<VERSION>_windows_amd64.exe``` (**Switch VERSION to the latest**):
3. Proceed with installation steps 3. Proceed with installation steps
4. This will install the client in the C:\\Program Files\\Wiretrustee and add the client service 4. This will install the client in the C:\\Program Files\\Wiretrustee and add the client service
5. After installing you can follow the [Client Configuration](#Client-Configuration) steps. 5. After installing, you can follow the [Client Configuration](#Client-Configuration) steps.
> To uninstall the client and service, you can use Add/Remove programs > To uninstall the client and service, you can use Add/Remove programs
### Client Configuration ### Client Configuration
1. Login to the Management Service. You need to have a `setup key` in hand (see ). 1. Login to the Management Service. You need to have a `setup key` in hand (see ).
For **Unix** systems: For **Unix** systems:
```shell ```shell
sudo wiretrustee login --setup-key <SETUP KEY> sudo wiretrustee up --setup-key <SETUP KEY>
``` ```
For **Windows** systems: For **Windows** systems, start powershell as administrator and:
```shell ```shell
.\wiretrustee.exe login --setup-key <SETUP KEY> wiretrustee up --setup-key <SETUP KEY>
``` ```
Alternatively, if you are hosting your own Management Service provide `--management-url` property pointing to your Management Service: Alternatively, if you are hosting your own Management Service provide `--management-url` property pointing to your Management Service:
```shell ```shell
sudo wiretrustee login --setup-key <SETUP KEY> --management-url https://localhost:33073 sudo wiretrustee up --setup-key <SETUP KEY> --management-url https://localhost:33073
``` ```
You could also omit `--setup-key` property. In this case the tool will prompt it the key. > You could also omit `--setup-key` property. In this case the tool will prompt it the key.
2. Start Wiretrustee:
For **MACOS** you will just start the service: 2. Check your IP:
````shell For **MACOS** you will just start the service:
sudo wiretrustee up ````shell
# or sudo ipconfig getifaddr utun100
sudo wiretrustee up & # to run it in background ````
````
For **Linux** systems: For **Linux** systems:
```shell ```shell
sudo systemctl restart wiretrustee.service ip addr show wt0
sudo systemctl status wiretrustee.service ```
```
For **Windows** systems: For **Windows** systems:
```shell ```shell
.\wiretrustee.exe service start netsh interface ip show config name="wt0"
``` ```
> You may need to run Powershell as Administrator
3. Check your IP: 3. Repeat on other machines.
For **MACOS** you will just start the service:
````shell
sudo ipconfig getifaddr utun100
````
For **Linux** systems:
```shell
ip addr show wt0
```
For **Windows** systems:
```shell
netsh interface ip show config name="wt0"
```
4. Repeat on other machines. ### Running Dashboard, Management, Signal and Coturn
### Running Management, Signal and Coturn
Wiretrustee uses [Auth0](https://auth0.com) for user authentication and authorization, therefore you will need to create a free account Wiretrustee uses [Auth0](https://auth0.com) for user authentication and authorization, therefore you will need to create a free account
and configure AUTH0 variables in the compose file (dashboard and management). and configure Auth0 variables in the compose file (dashboard) and in the management config file.
We chose Auth0 to "outsource" the user management part of our platform because we believe that implementing a proper user auth is not a trivial task and requires significant amount of time to make it right. We focused on connectivity instead.
It is worth mentioning that dependency to Auth0 is the only one that cannot be self-hosted.
Under infrastructure_files we have a docker-compose example to run both, Wiretrustee Management and Signal services, plus an instance of [Coturn](https://github.com/coturn/coturn), it also provides a turnserver.conf file as a simple example of Coturn configuration. Configuring Wiretrustee Auth0 integration:
- check [How to run](https://github.com/wiretrustee/wiretrustee-dashboard#how-to-run) to obtain Auth0 environment variables for UI Dashboard
- set these variables in the [environment section of the docker-compose file](https://github.com/wiretrustee/wiretrustee/blob/main/infrastructure_files/docker-compose.yml)
- check [Auth0 Golang API Guide](https://auth0.com/docs/quickstart/backend/golang) to obtain ```AuthIssuer```, ```AuthAudience```, and ```AuthKeysLocation```
- set these properties in the [management config files](https://github.com/wiretrustee/wiretrustee/blob/main/infrastructure_files/management.json#L33)
Under infrastructure_files we have a docker-compose example to run Dashboard, Wiretrustee Management and Signal services, plus an instance of [Coturn](https://github.com/coturn/coturn), it also provides a turnserver.conf file as a simple example of Coturn configuration.
You can edit the turnserver.conf file and change its Realm setting (defaults to wiretrustee.com) to your own domain and user setting (defaults to username1:password1) to **proper credentials**. You can edit the turnserver.conf file and change its Realm setting (defaults to wiretrustee.com) to your own domain and user setting (defaults to username1:password1) to **proper credentials**.
The example is set to use the official images from Wiretrustee and Coturn, you can find our documentation to run the signal server in docker in [Running the Signal service](#running-the-signal-service), the management in [Management](./management/README.md), and the Coturn official documentation [here](https://hub.docker.com/r/coturn/coturn). The example is set to use the official images from Wiretrustee and Coturn, you can find our documentation to run the signal server in docker in [Running the Signal service](#running-the-signal-service), the management in [Management](./management/README.md), and the Coturn official documentation [here](https://hub.docker.com/r/coturn/coturn).

View File

@@ -152,6 +152,5 @@ func promptPeerSetupKey() (string, error) {
return "", s.Err() return "", s.Err()
} }
func init() { //func init() {
loginCmd.PersistentFlags().StringVar(&setupKey, "setup-key", "", "Setup key obtained from the Management Service Dashboard (used to register peer)") //}
}

View File

@@ -2,11 +2,13 @@ package cmd
import ( import (
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/wiretrustee/wiretrustee/client/internal" "github.com/wiretrustee/wiretrustee/client/internal"
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"
"syscall"
) )
const ( const (
@@ -22,15 +24,15 @@ var (
defaultLogFile string defaultLogFile string
logFile string logFile string
managementURL string managementURL string
rootCmd = &cobra.Command{
rootCmd = &cobra.Command{
Use: "wiretrustee", Use: "wiretrustee",
Short: "", Short: "",
Long: "", Long: "",
} }
// Execution control channel for stopCh signal // Execution control channel for stopCh signal
stopCh chan int stopCh chan int
cleanupCh chan struct{}
) )
// Execute executes the root command. // Execute executes the root command.
@@ -40,6 +42,7 @@ func Execute() error {
func init() { func init() {
stopCh = make(chan int) stopCh = make(chan int)
cleanupCh = make(chan struct{})
defaultConfigPath = "/etc/wiretrustee/config.json" defaultConfigPath = "/etc/wiretrustee/config.json"
defaultLogFile = "/var/log/wiretrustee/client.log" defaultLogFile = "/var/log/wiretrustee/client.log"
@@ -52,9 +55,11 @@ func init() {
rootCmd.PersistentFlags().StringVar(&configPath, "config", defaultConfigPath, "Wiretrustee config file location") rootCmd.PersistentFlags().StringVar(&configPath, "config", defaultConfigPath, "Wiretrustee config file location")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level") rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level")
rootCmd.PersistentFlags().StringVar(&logFile, "log-file", defaultLogFile, "sets Wiretrustee log path. If console is specified the the log will be output to stdout") rootCmd.PersistentFlags().StringVar(&logFile, "log-file", defaultLogFile, "sets Wiretrustee log path. If console is specified the the log will be output to stdout")
rootCmd.PersistentFlags().StringVar(&setupKey, "setup-key", "", "Setup key obtained from the Management Service Dashboard (used to register peer)")
rootCmd.AddCommand(serviceCmd) rootCmd.AddCommand(serviceCmd)
rootCmd.AddCommand(upCmd) rootCmd.AddCommand(upCmd)
rootCmd.AddCommand(loginCmd) rootCmd.AddCommand(loginCmd)
rootCmd.AddCommand(versionCmd)
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
serviceCmd.AddCommand(installCmd, uninstallCmd) // service installer commands are subcommands of service serviceCmd.AddCommand(installCmd, uninstallCmd) // service installer commands are subcommands of service
} }
@@ -62,10 +67,10 @@ func init() {
// SetupCloseHandler handles SIGTERM signal and exits with success // SetupCloseHandler handles SIGTERM signal and exits with success
func SetupCloseHandler() { func SetupCloseHandler() {
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() { go func() {
for range c { for range c {
fmt.Println("\r- Ctrl+C pressed in Terminal") log.Info("shutdown signal received")
stopCh <- 0 stopCh <- 0
} }
}() }()

View File

@@ -1,26 +1,58 @@
package cmd package cmd
import ( import (
"github.com/cenkalti/backoff/v4"
"github.com/kardianos/service" "github.com/kardianos/service"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/wiretrustee/wiretrustee/util"
"time"
) )
func (p *program) Start(s service.Service) error { func (p *program) Start(s service.Service) error {
var backOff = &backoff.ExponentialBackOff{
InitialInterval: time.Second,
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: 30 * time.Second,
MaxElapsedTime: 24 * 3 * time.Hour, //stop after 3 days trying
Stop: backoff.Stop,
Clock: backoff.SystemClock,
}
// Start should not block. Do the actual work async. // Start should not block. Do the actual work async.
log.Info("starting service") //nolint log.Info("starting service") //nolint
go func() { go func() {
err := upCmd.RunE(p.cmd, p.args) operation := func() error {
if err != nil { err := runClient()
return if err != nil {
log.Warnf("retrying Wiretrustee client app due to error: %v", err)
return err
}
return nil
} }
err := backoff.Retry(operation, backOff)
if err != nil {
log.Errorf("exiting client retry loop due to unrecoverable error: %s", err)
return
}
}() }()
return nil return nil
} }
func (p *program) Stop(s service.Service) error { func (p *program) Stop(s service.Service) error {
stopCh <- 1 go func() {
stopCh <- 1
}()
select {
case <-cleanupCh:
case <-time.After(time.Second * 10):
log.Warnf("failed waiting for service cleanup, terminating")
}
log.Info("stopped Wiretrustee service") //nolint
return nil return nil
} }
@@ -30,6 +62,14 @@ var (
Short: "runs wiretrustee as service", Short: "runs wiretrustee as service",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := util.InitLog(logLevel, logFile)
if err != nil {
log.Errorf("failed initializing log %v", err)
return
}
SetupCloseHandler()
prg := &program{ prg := &program{
cmd: cmd, cmd: cmd,
args: args, args: args,
@@ -54,19 +94,24 @@ var (
startCmd = &cobra.Command{ startCmd = &cobra.Command{
Use: "start", Use: "start",
Short: "starts wiretrustee service", Short: "starts wiretrustee service",
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
err := util.InitLog(logLevel, logFile)
if err != nil {
log.Errorf("failed initializing log %v", err)
return err
}
s, err := newSVC(&program{}, newSVCConfig()) s, err := newSVC(&program{}, newSVCConfig())
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return err
} }
err = s.Start() err = s.Start()
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return err
} }
cmd.Printf("Wiretrustee service has been started") cmd.Println("Wiretrustee service has been started")
return nil
}, },
} }
) )
@@ -76,7 +121,10 @@ var (
Use: "stop", Use: "stop",
Short: "stops wiretrustee service", Short: "stops wiretrustee service",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := util.InitLog(logLevel, logFile)
if err != nil {
log.Errorf("failed initializing log %v", err)
}
s, err := newSVC(&program{}, newSVCConfig()) s, err := newSVC(&program{}, newSVCConfig())
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
@@ -87,7 +135,7 @@ var (
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return
} }
cmd.Printf("Wiretrustee service has been stopped") cmd.Println("Wiretrustee service has been stopped")
}, },
} }
) )
@@ -97,7 +145,10 @@ var (
Use: "restart", Use: "restart",
Short: "restarts wiretrustee service", Short: "restarts wiretrustee service",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := util.InitLog(logLevel, logFile)
if err != nil {
log.Errorf("failed initializing log %v", err)
}
s, err := newSVC(&program{}, newSVCConfig()) s, err := newSVC(&program{}, newSVCConfig())
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
@@ -108,7 +159,7 @@ var (
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return
} }
cmd.Printf("Wiretrustee service has been restarted") cmd.Println("Wiretrustee service has been restarted")
}, },
} }
) )

View File

@@ -9,7 +9,7 @@ var (
installCmd = &cobra.Command{ installCmd = &cobra.Command{
Use: "install", Use: "install",
Short: "installs wiretrustee service", Short: "installs wiretrustee service",
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
svcConfig := newSVCConfig() svcConfig := newSVCConfig()
@@ -30,15 +30,16 @@ var (
s, err := newSVC(&program{}, svcConfig) s, err := newSVC(&program{}, svcConfig)
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return err
} }
err = s.Install() err = s.Install()
if err != nil { if err != nil {
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return err
} }
cmd.Printf("Wiretrustee service has been installed") cmd.Println("Wiretrustee service has been installed")
return nil
}, },
} }
) )
@@ -60,7 +61,7 @@ var (
cmd.PrintErrln(err) cmd.PrintErrln(err)
return return
} }
cmd.Printf("Wiretrustee has been uninstalled") cmd.Println("Wiretrustee has been uninstalled")
}, },
} }
) )

View File

@@ -2,13 +2,13 @@ package cmd
import ( import (
"context" "context"
"github.com/kardianos/service"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/wiretrustee/wiretrustee/client/internal" "github.com/wiretrustee/wiretrustee/client/internal"
mgm "github.com/wiretrustee/wiretrustee/management/client" mgm "github.com/wiretrustee/wiretrustee/management/client"
mgmProto "github.com/wiretrustee/wiretrustee/management/proto" mgmProto "github.com/wiretrustee/wiretrustee/management/proto"
signal "github.com/wiretrustee/wiretrustee/signal/client" signal "github.com/wiretrustee/wiretrustee/signal/client"
"github.com/wiretrustee/wiretrustee/util"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@@ -17,97 +17,45 @@ import (
var ( var (
upCmd = &cobra.Command{ upCmd = &cobra.Command{
Use: "up", Use: "up",
Short: "start wiretrustee", Short: "install, login and start wiretrustee client",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
err := util.InitLog(logLevel, logFile)
err := loginCmd.RunE(cmd, args)
if err != nil { if err != nil {
log.Errorf("failed initializing log %v", err) return err
}
if logFile == "console" {
return runClient()
}
s, err := newSVC(&program{}, newSVCConfig())
if err != nil {
cmd.PrintErrln(err)
return err return err
} }
config, err := internal.ReadConfig(managementURL, configPath) srvStatus, err := s.Status()
if err != nil { if err != nil {
log.Errorf("failed reading config %s %v", configPath, err) if err == service.ErrNotInstalled {
return err log.Infof("%s. Installing it now", err.Error())
e := installCmd.RunE(cmd, args)
if e != nil {
return e
}
} else {
log.Warnf("failed retrieving service status: %v", err)
}
} }
if srvStatus == service.StatusRunning {
//validate our peer's Wireguard PRIVATE key stopCmd.Run(cmd, args)
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
if err != nil {
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
return err
} }
ctx, cancel := context.WithCancel(context.Background()) return startCmd.RunE(cmd, args)
defer cancel()
mgmTlsEnabled := false
if config.ManagementURL.Scheme == "https" {
mgmTlsEnabled = true
}
// connect (just a connection, no stream yet) and login to Management Service to get an initial global Wiretrustee config
mgmClient, loginResp, err := connectToManagement(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
if err != nil {
log.Warn(err)
return err
}
// with the global Wiretrustee config in hand connect (just a connection, no stream yet) Signal
signalClient, err := connectToSignal(ctx, loginResp.GetWiretrusteeConfig(), myPrivateKey)
if err != nil {
log.Error(err)
return err
}
engineConfig, err := createEngineConfig(myPrivateKey, config, loginResp.GetWiretrusteeConfig(), loginResp.GetPeerConfig())
if err != nil {
log.Error(err)
return err
}
// create start the Wiretrustee Engine that will connect to the Signal and Management streams and manage connections to remote peers.
engine := internal.NewEngine(signalClient, mgmClient, engineConfig, cancel)
err = engine.Start()
if err != nil {
log.Errorf("error while starting Wiretrustee Connection Engine: %s", err)
return err
}
SetupCloseHandler()
select {
case <-stopCh:
case <-ctx.Done():
}
log.Infof("receive signal to stop running")
err = mgmClient.Close()
if err != nil {
log.Errorf("failed closing Management Service client %v", err)
return err
}
err = signalClient.Close()
if err != nil {
log.Errorf("failed closing Signal Service client %v", err)
return err
}
err = engine.Stop()
if err != nil {
log.Errorf("failed stopping engine %v", err)
return err
}
return nil
}, },
} }
) )
func init() {
}
// createEngineConfig converts configuration received from Management Service to EngineConfig // createEngineConfig converts configuration received from Management Service to EngineConfig
func createEngineConfig(key wgtypes.Key, config *internal.Config, wtConfig *mgmProto.WiretrusteeConfig, peerConfig *mgmProto.PeerConfig) (*internal.EngineConfig, error) { func createEngineConfig(key wgtypes.Key, config *internal.Config, peerConfig *mgmProto.PeerConfig) (*internal.EngineConfig, error) {
iFaceBlackList := make(map[string]struct{}) iFaceBlackList := make(map[string]struct{})
for i := 0; i < len(config.IFaceBlackList); i += 2 { for i := 0; i < len(config.IFaceBlackList); i += 2 {
iFaceBlackList[config.IFaceBlackList[i]] = struct{}{} iFaceBlackList[config.IFaceBlackList[i]] = struct{}{}
@@ -163,7 +111,92 @@ func connectToManagement(ctx context.Context, managementAddr string, ourPrivateK
} }
} }
log.Infof("peer logged in to Management Service %s", managementAddr) log.Debugf("peer logged in to Management Service %s", managementAddr)
return client, loginResp, nil return client, loginResp, nil
} }
func runClient() error {
config, err := internal.ReadConfig(managementURL, configPath)
if err != nil {
log.Errorf("failed reading config %s %v", configPath, err)
return err
}
//validate our peer's Wireguard PRIVATE key
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
if err != nil {
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
return err
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mgmTlsEnabled := false
if config.ManagementURL.Scheme == "https" {
mgmTlsEnabled = true
}
// connect (just a connection, no stream yet) and login to Management Service to get an initial global Wiretrustee config
mgmClient, loginResp, err := connectToManagement(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
if err != nil {
log.Warn(err)
return err
}
// with the global Wiretrustee config in hand connect (just a connection, no stream yet) Signal
signalClient, err := connectToSignal(ctx, loginResp.GetWiretrusteeConfig(), myPrivateKey)
if err != nil {
log.Error(err)
return err
}
peerConfig := loginResp.GetPeerConfig()
engineConfig, err := createEngineConfig(myPrivateKey, config, peerConfig)
if err != nil {
log.Error(err)
return err
}
// create start the Wiretrustee Engine that will connect to the Signal and Management streams and manage connections to remote peers.
engine := internal.NewEngine(signalClient, mgmClient, engineConfig, cancel, ctx)
err = engine.Start()
if err != nil {
log.Errorf("error while starting Wiretrustee Connection Engine: %s", err)
return err
}
log.Print("Wiretrustee engine started, my IP is: ", peerConfig.Address)
select {
case <-stopCh:
case <-ctx.Done():
}
err = mgmClient.Close()
if err != nil {
log.Errorf("failed closing Management Service client %v", err)
return err
}
err = signalClient.Close()
if err != nil {
log.Errorf("failed closing Signal Service client %v", err)
return err
}
err = engine.Stop()
if err != nil {
log.Errorf("failed stopping engine %v", err)
return err
}
go func() {
cleanupCh <- struct{}{}
}()
log.Info("stopped Wiretrustee client")
return ctx.Err()
}

View File

@@ -1,13 +1,10 @@
package cmd package cmd
import ( import (
"errors"
"fmt"
"github.com/wiretrustee/wiretrustee/iface" "github.com/wiretrustee/wiretrustee/iface"
mgmt "github.com/wiretrustee/wiretrustee/management/server" mgmt "github.com/wiretrustee/wiretrustee/management/server"
"github.com/wiretrustee/wiretrustee/util" "github.com/wiretrustee/wiretrustee/util"
"net/url" "net/url"
"os"
"path/filepath" "path/filepath"
"testing" "testing"
"time" "time"
@@ -37,24 +34,6 @@ func TestUp_Start(t *testing.T) {
} }
func TestUp_ShouldFail_On_NoConfig(t *testing.T) {
tempDir := t.TempDir()
confPath := tempDir + "/config.json"
mgmtURL := fmt.Sprintf("http://%s", mgmAddr)
rootCmd.SetArgs([]string{
"up",
"--config",
confPath,
"--management-url",
mgmtURL,
})
err := rootCmd.Execute()
if err == nil || !errors.Is(err, os.ErrNotExist) {
t.Errorf("expecting login command to fail on absence of config")
}
}
func TestUp(t *testing.T) { func TestUp(t *testing.T) {
defer iface.Close() defer iface.Close()
@@ -65,24 +44,17 @@ func TestUp(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
rootCmd.SetArgs([]string{ rootCmd.SetArgs([]string{
"login", "up",
"--config", "--config",
confPath, confPath,
"--setup-key", "--setup-key",
"A2C8E62B-38F5-4553-B31E-DD66C696CEBB", "A2C8E62B-38F5-4553-B31E-DD66C696CEBB",
"--management-url", "--management-url",
mgmtURL.String(), mgmtURL.String(),
}) "--log-file",
err = rootCmd.Execute() "console",
if err != nil {
t.Fatal(err)
}
rootCmd.SetArgs([]string{
"up",
"--config",
confPath,
}) })
go func() { go func() {
err = rootCmd.Execute() err = rootCmd.Execute()

14
client/cmd/version.go Normal file
View File

@@ -0,0 +1,14 @@
package cmd
import "github.com/spf13/cobra"
var (
Version string
versionCmd = &cobra.Command{
Use: "version",
Short: "prints wiretrustee version",
Run: func(cmd *cobra.Command, args []string) {
cmd.Println(Version)
},
}
)

View File

@@ -128,6 +128,8 @@ func (conn *Connection) Open(timeout time.Duration) error {
a, err := ice.NewAgent(&ice.AgentConfig{ a, err := ice.NewAgent(&ice.AgentConfig{
// MulticastDNSMode: ice.MulticastDNSModeQueryAndGather, // MulticastDNSMode: ice.MulticastDNSModeQueryAndGather,
NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4}, NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4},
PortMin: 57830,
PortMax: 57830,
Urls: conn.Config.StunTurnURLS, Urls: conn.Config.StunTurnURLS,
CandidateTypes: []ice.CandidateType{ice.CandidateTypeHost, ice.CandidateTypeServerReflexive, ice.CandidateTypeRelay}, CandidateTypes: []ice.CandidateType{ice.CandidateTypeHost, ice.CandidateTypeServerReflexive, ice.CandidateTypeRelay},
InterfaceFilter: func(s string) bool { InterfaceFilter: func(s string) bool {
@@ -160,13 +162,13 @@ func (conn *Connection) Open(timeout time.Duration) error {
} }
conn.Status = StatusConnecting conn.Status = StatusConnecting
log.Infof("trying to connect to peer %s", conn.Config.RemoteWgKey.String()) log.Debugf("trying to connect to peer %s", conn.Config.RemoteWgKey.String())
// wait until credentials have been sent from the remote peer (will arrive via a signal server) // wait until credentials have been sent from the remote peer (will arrive via a signal server)
select { select {
case remoteAuth := <-conn.remoteAuthChannel: case remoteAuth := <-conn.remoteAuthChannel:
log.Infof("got a connection confirmation from peer %s", conn.Config.RemoteWgKey.String()) log.Debugf("got a connection confirmation from peer %s", conn.Config.RemoteWgKey.String())
err = conn.agent.GatherCandidates() err = conn.agent.GatherCandidates()
if err != nil { if err != nil {
@@ -186,8 +188,11 @@ func (conn *Connection) Open(timeout time.Duration) error {
if err != nil { if err != nil {
return err return err
} }
useProxy := useProxy(pair)
// in case the remote peer is in the local network or one of the peers has public static IP -> no need for a Wireguard proxy, direct communication is possible. // in case the remote peer is in the local network or one of the peers has public static IP -> no need for a Wireguard proxy, direct communication is possible.
if !useProxy(pair) { if !useProxy {
log.Debugf("it is possible to establish a direct connection (without proxy) to peer %s - my addr: %s, remote addr: %s", conn.Config.RemoteWgKey.String(), pair.Local, pair.Remote) log.Debugf("it is possible to establish a direct connection (without proxy) to peer %s - my addr: %s, remote addr: %s", conn.Config.RemoteWgKey.String(), pair.Local, pair.Remote)
err = conn.wgProxy.StartLocal(fmt.Sprintf("%s:%d", pair.Remote.Address(), iface.WgPort)) err = conn.wgProxy.StartLocal(fmt.Sprintf("%s:%d", pair.Remote.Address(), iface.WgPort))
if err != nil { if err != nil {
@@ -195,19 +200,17 @@ func (conn *Connection) Open(timeout time.Duration) error {
} }
} else { } else {
log.Infof("establishing secure tunnel to peer %s via selected candidate pair %s", conn.Config.RemoteWgKey.String(), pair) log.Debugf("establishing secure tunnel to peer %s via selected candidate pair %s", conn.Config.RemoteWgKey.String(), pair)
err = conn.wgProxy.Start(remoteConn) err = conn.wgProxy.Start(remoteConn)
if err != nil { if err != nil {
return err return err
} }
} }
if pair.Remote.Type() == ice.CandidateTypeRelay || pair.Local.Type() == ice.CandidateTypeRelay { relayed := pair.Remote.Type() == ice.CandidateTypeRelay || pair.Local.Type() == ice.CandidateTypeRelay
log.Infof("using relay with peer %s", conn.Config.RemoteWgKey)
}
conn.Status = StatusConnected conn.Status = StatusConnected
log.Infof("opened connection to peer %s", conn.Config.RemoteWgKey.String()) log.Infof("opened connection to peer %s [localProxy=%v, relayed=%v]", conn.Config.RemoteWgKey.String(), useProxy, relayed)
case <-conn.closeCond.C: case <-conn.closeCond.C:
conn.Status = StatusDisconnected conn.Status = StatusDisconnected
return fmt.Errorf("connection to peer %s has been closed", conn.Config.RemoteWgKey.String()) return fmt.Errorf("connection to peer %s has been closed", conn.Config.RemoteWgKey.String())
@@ -271,7 +274,7 @@ func (conn *Connection) Close() error {
var err error var err error
conn.closeCond.Do(func() { conn.closeCond.Do(func() {
log.Warnf("closing connection to peer %s", conn.Config.RemoteWgKey.String()) log.Debugf("closing connection to peer %s", conn.Config.RemoteWgKey.String())
if a := conn.agent; a != nil { if a := conn.agent; a != nil {
e := a.Close() e := a.Close()

View File

@@ -57,6 +57,8 @@ type Engine struct {
TURNs []*ice.URL TURNs []*ice.URL
cancel context.CancelFunc cancel context.CancelFunc
ctx context.Context
} }
// Peer is an instance of the Connection Peer // Peer is an instance of the Connection Peer
@@ -66,7 +68,7 @@ type Peer struct {
} }
// NewEngine creates a new Connection Engine // NewEngine creates a new Connection Engine
func NewEngine(signalClient *signal.Client, mgmClient *mgm.Client, config *EngineConfig, cancel context.CancelFunc) *Engine { func NewEngine(signalClient *signal.Client, mgmClient *mgm.Client, config *EngineConfig, cancel context.CancelFunc, ctx context.Context) *Engine {
return &Engine{ return &Engine{
signal: signalClient, signal: signalClient,
mgmClient: mgmClient, mgmClient: mgmClient,
@@ -77,17 +79,25 @@ func NewEngine(signalClient *signal.Client, mgmClient *mgm.Client, config *Engin
STUNs: []*ice.URL{}, STUNs: []*ice.URL{},
TURNs: []*ice.URL{}, TURNs: []*ice.URL{},
cancel: cancel, cancel: cancel,
ctx: ctx,
} }
} }
func (e *Engine) Stop() error { func (e *Engine) Stop() error {
err := e.removeAllPeerConnections()
if err != nil {
return err
}
log.Debugf("removing Wiretrustee interface %s", e.config.WgIface) log.Debugf("removing Wiretrustee interface %s", e.config.WgIface)
err := iface.Close() err = iface.Close()
if err != nil { if err != nil {
log.Errorf("failed closing Wiretrustee interface %s %v", e.config.WgIface, err) log.Errorf("failed closing Wiretrustee interface %s %v", e.config.WgIface, err)
return err return err
} }
log.Infof("stopped Wiretrustee Engine")
return nil return nil
} }
@@ -127,7 +137,7 @@ func (e *Engine) Start() error {
// initializePeer peer agent attempt to open connection // initializePeer peer agent attempt to open connection
func (e *Engine) initializePeer(peer Peer) { func (e *Engine) initializePeer(peer Peer) {
var backOff = &backoff.ExponentialBackOff{ var backOff = backoff.WithContext(&backoff.ExponentialBackOff{
InitialInterval: backoff.DefaultInitialInterval, InitialInterval: backoff.DefaultInitialInterval,
RandomizationFactor: backoff.DefaultRandomizationFactor, RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier, Multiplier: backoff.DefaultMultiplier,
@@ -135,19 +145,20 @@ func (e *Engine) initializePeer(peer Peer) {
MaxElapsedTime: time.Duration(0), //never stop MaxElapsedTime: time.Duration(0), //never stop
Stop: backoff.Stop, Stop: backoff.Stop,
Clock: backoff.SystemClock, Clock: backoff.SystemClock,
} }, e.ctx)
operation := func() error { operation := func() error {
_, err := e.openPeerConnection(e.wgPort, e.config.WgPrivateKey, peer) _, err := e.openPeerConnection(e.wgPort, e.config.WgPrivateKey, peer)
e.peerMux.Lock() e.peerMux.Lock()
defer e.peerMux.Unlock() defer e.peerMux.Unlock()
if _, ok := e.conns[peer.WgPubKey]; !ok { if _, ok := e.conns[peer.WgPubKey]; !ok {
log.Infof("removing connection attempt with Peer: %v, not retrying", peer.WgPubKey) log.Debugf("removed connection attempt to peer: %v, not retrying", peer.WgPubKey)
return nil return nil
} }
if err != nil { if err != nil {
log.Warnln(err) log.Warnln(err)
log.Warnln("retrying connection because of error: ", err.Error()) log.Debugf("retrying connection because of error: %s", err.Error())
return err return err
} }
return nil return nil
@@ -172,6 +183,19 @@ func (e *Engine) removePeerConnections(peers []string) error {
return nil return nil
} }
func (e *Engine) removeAllPeerConnections() error {
log.Debugf("removing all peer connections")
e.peerMux.Lock()
defer e.peerMux.Unlock()
for peer := range e.conns {
err := e.removePeerConnection(peer)
if err != nil {
return err
}
}
return nil
}
// removePeerConnection closes existing peer connection and removes peer // removePeerConnection closes existing peer connection and removes peer
func (e *Engine) removePeerConnection(peerKey string) error { func (e *Engine) removePeerConnection(peerKey string) error {
conn, exists := e.conns[peerKey] conn, exists := e.conns[peerKey]
@@ -179,6 +203,7 @@ func (e *Engine) removePeerConnection(peerKey string) error {
delete(e.conns, peerKey) delete(e.conns, peerKey)
return conn.Close() return conn.Close()
} }
log.Infof("removed connection to peer %s", peerKey)
return nil return nil
} }
@@ -310,7 +335,7 @@ func (e *Engine) receiveManagementEvents() {
e.cancel() e.cancel()
return return
} }
log.Infof("connected to Management Service updates stream") log.Debugf("stopped receiving updates from Management Service")
}() }()
log.Debugf("connecting to Management Service updates stream") log.Debugf("connecting to Management Service updates stream")
} }

View File

@@ -87,7 +87,7 @@ func (p *WgProxy) proxyToRemotePeer(remoteConn *ice.Conn) {
for { for {
select { select {
case <-p.close: case <-p.close:
log.Infof("stopped proxying from remote peer %s due to closed connection", p.remoteKey) log.Debugf("stopped proxying from remote peer %s due to closed connection", p.remoteKey)
return return
default: default:
n, err := p.wgConn.Read(buf) n, err := p.wgConn.Read(buf)
@@ -113,7 +113,7 @@ func (p *WgProxy) proxyToLocalWireguard(remoteConn *ice.Conn) {
for { for {
select { select {
case <-p.close: case <-p.close:
log.Infof("stopped proxying from remote peer %s due to closed connection", p.remoteKey) log.Debugf("stopped proxying from remote peer %s due to closed connection", p.remoteKey)
return return
default: default:
n, err := remoteConn.Read(buf) n, err := remoteConn.Read(buf)

View File

@@ -5,7 +5,11 @@ import (
"os" "os"
) )
var version = "development"
func main() { func main() {
cmd.Version = version
if err := cmd.Execute(); err != nil { if err := cmd.Execute(); err != nil {
os.Exit(1) os.Exit(1)
} }

104
docs/README.md Normal file
View File

@@ -0,0 +1,104 @@
### Table of contents
* [About Wiretrustee](#about-wiretrustee)
* [Why Wireguard with Wiretrustee?](#why-wireguard-with-wiretrustee)
* [Wiretrustee vs. Traditional VPN](#wiretrustee-vs-traditional-vpn)
* [High-level technology overview](#high-level-technology-overview)
* [Getting started](#getting-started)
### About Wiretrustee
Wiretrustee is an open-source VPN platform built on top of [WireGuard®](https://www.wireguard.com/) making it easy to create secure private networks for your organization or home.
It requires zero configuration effort leaving behind the hassle of opening ports, complex firewall rules, vpn gateways, and so forth.
There is no centralized VPN server with Wiretrustee - your computers, devices, machines, and servers connect to each other directly over a fast encrypted tunnel.
It literally takes less than 5 minutes to provision a secure peer-to-peer VPN with Wiretrustee. Check our [Quickstart Guide Video](https://www.youtube.com/watch?v=cWTsGUJAUaU) to see the setup in action.
### Why Wireguard with Wiretrustee?
WireGuard is a modern and extremely fast VPN tunnel utilizing state-of-the-art [cryptography](https://www.wireguard.com/protocol/)
and Wiretrustee uses Wireguard to establish a secure tunnel between machines.
Built with simplicity in mind, Wireguard ensures that traffic between two machines is encrypted and flowing, however, it requires a few things to be done beforehand.
First, in order to connect, the machines have to be configured.
On each machine, you need to generate private and public keys and prepare a WireGuard configuration file.
The configuration also includes a private IP address that should be unique per machine.
Secondly, to accept the incoming traffic, the machines have to trust each other.
The generated public keys have to be pre-shared on the machines.
This works similarly to SSH with its authorised_keys file.
Lastly, the connectivity between the machines has to be ensured.
To make machines reach one another, you are required to set a WireGuard endpoint property which indicates the IP address and port of the remote machine to connect to.
On many occasions, machines are hidden behind firewalls and NAT devices,
meaning that you may need to configure a port forwarding or open holes in your firewall to ensure the machines are reachable.
The undertakings mentioned above might not be complicated if you have just a few machines, but the complexity grows as the number of machines increases.
Wiretrustee simplifies the setup by automatically generating private and public keys, assigning unique private IP addresses, and takes care of sharing public keys between the machines.
It is worth mentioning that the private key never leaves the machine.
So only the machine that owns the key can decrypt traffic addressed to it.
The same applies also to the relayed traffic mentioned below.
Furthermore, Wiretrustee ensures connectivity by leveraging advanced [NAT traversal techniques](https://en.wikipedia.org/wiki/NAT_traversal)
and removing the necessity of port forwarding, opening holes in the firewall, and having a public static IP address.
In cases when a direct peer-to-peer connection isn't possible, all traffic is relayed securely between peers.
Wiretrustee also monitors the connection health and restarts broken connections.
There are a few more things that we are working on to make secure private networks simple. A few examples are ACLs, MFA and activity monitoring.
Check out the WireGuard [Quick Start](https://www.wireguard.com/quickstart/) guide to learn more about configuring "plain" WireGuard without Wiretrustee.
### Wiretrustee vs. Traditional VPN
In the traditional VPN model, everything converges on a centralized, protected network where all the clients are connecting to a central VPN server.
An increasing amount of connections can easily overload the VPN server.
Even a short downtime of a server can cause expensive system disruptions, and a remote team's inability to work.
Centralized VPNs imply all the traffic going through the central server causing network delays and increased traffic usage.
Such systems require an experienced team to set up and maintain.
Configuring firewalls, setting up NATs, SSO integration, and managing access control lists can be a nightmare.
Traditional centralized VPNs are often compared to a [castle-and-moat](https://en.wikipedia.org/wiki/Moat) model
in which once accessed, user is trusted and can access critical infrastructure and resources without any restrictions.
Wiretrustee decentralizes networks using direct point-to-point connections, as opposed to traditional models.
Consequently, network performance is increased since traffic flows directly between the machines bypassing VPN servers or gateways.
To achieve this, Wiretrustee client applications employ signalling servers to find other machines and negotiate connections.
These are similar to the signaling servers used in [WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling#the_signaling_server)
Thanks to [NAT traversal techniques](https://en.wikipedia.org/wiki/NAT_traversal),
outlined in the [Why not just Wireguard?](#why-wireguard-with-wiretrustee) section above,
Wiretrustee installation doesn't require complex network and firewall configuration.
It just works, minimising the maintenance effort.
Finally, each machine or device in the Wiretrustee network verifies incoming connections accepting only the trusted ones.
This is ensured by Wireguard's [Crypto Routing concept](https://www.wireguard.com/#cryptokey-routing).
### High-level technology overview
In essence, Wiretrustee is an open source platform consisting of a collection of systems, responsible for handling peer-to-peer connections, tunneling and network management (IP, keys, ACLs, etc).
<p align="center">
<img src="media/high-level-dia.png" alt="high-level-dia" width="781"/>
</p>
Wiretrustee uses open-source technologies like [WireGuard®](https://www.wireguard.com/), [Pion ICE (WebRTC)](https://github.com/pion/ice), [Coturn](https://github.com/coturn/coturn),
and [software](https://github.com/wiretrustee/wiretrustee) developed by Wiretrustee authors to make it all work together.
To learn more about Wiretrustee architecture, please refer to the [architecture section](../docs/architecture.md).
### Getting Started
There are 2 ways of getting started with Wiretrustee:
- use Cloud Managed version
- self-hosting
We recommend starting with the cloud managed version hosted at [app.wiretrustee.com](https://app.wiretrustee.com) - the quickest way to get familiar with the system.
See [Quickstart Guide](../docs/quickstart.md) for instructions.
If you don't want to use the managed version, check out our [Self-hosting Guide](../docs/self-hosting.md).

2
docs/architecture.md Normal file
View File

@@ -0,0 +1,2 @@
### Architecture
TODO

BIN
docs/media/add-peer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
docs/media/auth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
docs/media/empty-peers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/media/logo-full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/media/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/media/peerA.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
docs/media/peerB.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 5.9 MiB

BIN
docs/media/peers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

41
docs/quickstart.md Normal file
View File

@@ -0,0 +1,41 @@
## Quickstart guide (Cloud Managed version)
Step-by-step video guide on YouTube:
[![IMAGE ALT TEXT](https://img.youtube.com/vi/cWTsGUJAUaU/0.jpg)](https://youtu.be/cWTsGUJAUaU "Wiretrustee - secure private network in less than 5 minutes")
This guide describes how to create secure VPN and connect 2 machines peer-to-peer.
One machine is a Raspberry Pi Compute Module 4 hosted at home (Peer A), and the other one is a regular Ubuntu server running in the Data Center (Peer B).
Both machines are running Linux (Raspbian and Ubuntu respectively), but you could also use Mac or Windows operating systems.
1. Sign-up at [https://app.wiretrustee.com/](https://app.wiretrustee.com/peers)
You can use your email and password to sign-up or any available social login option (e.g., GitHub account)
<img src="media/auth.png" alt="auth" width="350"/>
2. After a successful login you will be redirected to the ```Peers``` screen which is empty because you don't have any peers yet.
Click ```Add peer``` to add a new machine.
<img src="media/empty-peers.png" alt="empty-peers" width="700"/>
3. Choose a setup key which will be used to associate your new machine with your account (in our case it is ```Default key```).
Choose your machine operating system (in our case it is ```Linux```) and proceed with the installation steps on the machine.
<img src="media/add-peer.png" alt="add-peer" width="700"/>
4. Repeat #3 for the 2nd machine.
5. Return to ```Peers``` and you should notice 2 new machines with status ```Connected```
<img src="media/peers.png" alt="peers" width="700"/>
6. To test the connection you could try pinging devices:
On Peer A:
```ping 100.64.0.2```
On Peer B:
```ping 100.64.0.1```
7. Done! You now have a secure peer-to-peer VPN configured.

96
docs/self-hosting.md Normal file
View File

@@ -0,0 +1,96 @@
### Self-hosting
Wiretrustee is an open-source platform that can be self-hosted on your servers.
It relies on components developed by Wiretrustee Authors [Management Service](https://github.com/wiretrustee/wiretrustee/tree/main/management), [Management UI Dashboard](https://github.com/wiretrustee/wiretrustee-dashboard), [Signal Service](https://github.com/wiretrustee/wiretrustee/tree/main/signal),
a 3rd party open-source STUN/TURN service [Coturn](https://github.com/coturn/coturn) and a 3rd party service [Auth0](https://auth0.com/).
All the components can be self-hosted except for the Auth0 service.
We chose Auth0 to "outsource" the user management part of the platform because we believe that implementing a proper user auth requires significant amount of time to make it right.
We focused on connectivity instead.
If you would like to learn more about the architecture please refer to the [Wiretrustee Architecture section](architecture.md).
### Step-by-step video guide on YouTube:
[![IMAGE ALT TEXT](https://img.youtube.com/vi/Ofpgx5WhT0k/0.jpg)](https://youtu.be/Ofpgx5WhT0k "Wiretrustee Self-Hosting Guide")
### Requirements
- Virtual machine offered by any cloud provider (e.g., AWS, DigitalOcean, Hetzner, Google Cloud, Azure ...).
- Any Linux OS.
- Docker Compose installed (see [Install Docker Compose](https://docs.docker.com/compose/install/)).
- Domain name pointing to the public IP address of your server.
- Open ports ```443, 33071, 33073, 10000, 3478``` (Dashboard, Management HTTP API, Management gRpc API, Signal gRpc, Coturn STUN/TURN respectively) on your server.
- Maybe a cup of coffee or tea :)
### Step-by-step guide
For this tutorial we will be using domain ```test.wiretrustee.com``` which points to our Ubuntu 20.04 machine hosted at Hetzner.
1. Create Auth0 account at [auth0.com](https://auth0.com/).
2. Login to your server, clone Wiretrustee repository:
```bash
git clone https://github.com/wiretrustee/wiretrustee.git wiretrustee/
```
and switch to the ```wiretrustee/infrastructure_files/``` folder that contains docker compose file:
```bash
cd wiretrustee/infrastructure_files/
```
3. Prepare configuration files.
To simplify the setup we have prepared a script to substitute required properties in the [docker-compose.yml.tmpl](../infrastructure_files/docker-compose.yml.tmpl) and [management.json.tmpl](../infrastructure_files/management.json.tmpl) files.
The [setup.env](../infrastructure_files/setup.env) file contains the following properties that have to be filled:
```bash
# e.g. app.mydomain.com
WIRETRUSTEE_DOMAIN=""
# e.g. dev-24vkclam.us.auth0.com
WIRETRUSTEE_AUTH0_DOMAIN=""
# e.g. 61u3JMXRO0oOevc7gCkZLCwePQvT4lL0
WIRETRUSTEE_AUTH0_CLIENT_ID=""
# e.g. https://app.mydomain.com/
WIRETRUSTEE_AUTH0_AUDIENCE=""
# e.g. hello@mydomain.com
WIRETRUSTEE_LETSENCRYPT_EMAIL=""
```
Please follow the steps to get the values.
4. Configure ```WIRETRUSTEE_AUTH0_DOMAIN``` ```WIRETRUSTEE_AUTH0_CLIENT_ID``` ```WIRETRUSTEE_AUTH0_AUDIENCE``` properties.
* To obtain these, please use [Auth0 React SDK Guide](https://auth0.com/docs/quickstart/spa/react/01-login#configure-auth0) up until "Install the Auth0 React SDK".
:grey_exclamation: Use ```https://YOUR DOMAIN``` as ````Allowed Callback URLs````, ```Allowed Logout URLs```, ```Allowed Web Origins``` and ```Allowed Origins (CORS)```
* set the variables in the ```setup.env```
5. Configure ```WIRETRUSTEE_AUTH0_AUDIENCE``` property.
* Check [Auth0 Golang API Guide](https://auth0.com/docs/quickstart/backend/golang) to obtain AuthAudience.
* set the property in the ```setup.env``` file.
6. Configure ```WIRETRUSTEE_LETSENCRYPT_EMAIL``` property.
This can be any email address. [Let's Encrypt](https://letsencrypt.org/) will create an account while generating a new certificate.
7. Make sure all the properties set in the ```setup.env``` file and run:
```bash
./configure.sh
```
This will export all the properties as environment variables and generate ```docker-compose.yml``` and ```management.json``` files substituting required variables.
8. Run docker compose:
```bash
docker-compose up -d
```
9. Optionally check the logs by running:
```bash
docker-compose logs signal
docker-compose logs management
docker-compose logs coturn
docker-compose logs dashboard

2
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.2.0 github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/kardianos/service v1.2.0 github.com/kardianos/service v1.2.1-0.20210728001519-a323c3813bc7
github.com/onsi/ginkgo v1.16.4 github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.13.0 github.com/onsi/gomega v1.13.0
github.com/pion/ice/v2 v2.1.7 github.com/pion/ice/v2 v2.1.7

4
go.sum
View File

@@ -146,8 +146,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g= github.com/kardianos/service v1.2.1-0.20210728001519-a323c3813bc7 h1:oohm9Rk9JAxxmp2NLZa7Kebgz9h4+AJDcc64txg3dQ0=
github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/kardianos/service v1.2.1-0.20210728001519-a323c3813bc7/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

View File

@@ -0,0 +1,7 @@
#!/bin/bash
unset $(grep -v '^#' ./setup.env | sed -E 's/(.*)=.*/\1/' | xargs)
export $(grep -v '^#' ./setup.env | xargs)
envsubst < docker-compose.yml.tmpl > docker-compose.yml
envsubst < management.json.tmpl > management.json

View File

@@ -1,56 +0,0 @@
version: "3"
services:
#UI dashboard
dashboard:
image: wiretrustee/dashboard:main
restart: unless-stopped
ports:
- 80:80
# - 443:443
environment:
- AUTH0_DOMAIN=<YOUR AUTH0 DOMAIN>
- AUTH0_CLIENT_ID=<YOUR AUTH0 CLIENT ID>
- AUTH0_AUDIENCE=<YOUR AUTH0 AUDIENCE>
- WIRETRUSTEE_MGMT_API_ENDPOINT=http://localhost:33071
# - NGINX_SSL_PORT: 443
# - LETSENCRYPT_DOMAIN: <YOUR DOMAIN>
# - LETSENCRYPT_EMAIL: <YOUR EMAIL>
# Signal
signal:
image: wiretrustee/signal:latest
restart: unless-stopped
volumes:
- wiretrustee-mgmt:/var/lib/wiretrustee
- /varl/log/wiretrustee/signal.log:/var/log/wiretrustee/signal.log
ports:
- 10000:10000
# # port and command for Let's Encrypt validation
# - 443:443
# command: ["--letsencrypt-domain", "<YOUR-DOMAIN>", "--log-file", "console"]
# Management
management:
image: wiretrustee/management:latest
restart: unless-stopped
volumes:
- wiretrustee-mgmt:/var/lib/wiretrustee
- ./management.json:/etc/wiretrustee/management.json
# - /var/log/wiretrustee/management.log:/var/log/wiretrustee/management.log
ports:
- 33073:33073 #gRPC port
- 33071:33071 #HTTP port
# # port and command for Let's Encrypt validation
# - 443:443
# command: ["--letsencrypt-domain", "<YOUR-DOMAIN>", "--log-file", "console"]
# Coturn
coturn:
image: coturn/coturn
restart: unless-stopped
domainname: stun.wiretrustee.com
volumes:
- ./turnserver.conf:/etc/turnserver.conf:ro
# - ./privkey.pem:/etc/coturn/private/privkey.pem:ro
# - ./cert.pem:/etc/coturn/certs/cert.pem:ro
network_mode: host
volumes:
wiretrustee-mgmt:
wiretrustee-signal:

View File

@@ -0,0 +1,61 @@
version: "3"
services:
#UI dashboard
dashboard:
image: wiretrustee/dashboard:main
restart: unless-stopped
ports:
- 80:80
- 443:443
environment:
- AUTH0_DOMAIN=$WIRETRUSTEE_AUTH0_DOMAIN
- AUTH0_CLIENT_ID=$WIRETRUSTEE_AUTH0_CLIENT_ID
- AUTH0_AUDIENCE=$WIRETRUSTEE_AUTH0_AUDIENCE
- WIRETRUSTEE_MGMT_API_ENDPOINT=https://$WIRETRUSTEE_DOMAIN:33071
- NGINX_SSL_PORT=443
- LETSENCRYPT_DOMAIN=$WIRETRUSTEE_DOMAIN
- LETSENCRYPT_EMAIL=$WIRETRUSTEE_LETSENCRYPT_EMAIL
volumes:
- /var/lib/wiretrustee/dashboard/letsencrypt:/etc/letsencrypt/
# Signal
signal:
image: wiretrustee/signal:latest
restart: unless-stopped
volumes:
- wiretrustee-signal:/var/lib/wiretrustee
# - /var/log/wiretrustee/signal.log:/var/log/wiretrustee/signal.log
ports:
- 10000:10000
# # port and command for Let's Encrypt validation
# - 443:443
# command: ["--letsencrypt-domain", "$WIRETRUSTEE_DOMAIN", "--log-file", "console"]
# Management
management:
image: wiretrustee/management:latest
restart: unless-stopped
depends_on:
- dashboard
volumes:
- wiretrustee-mgmt:/var/lib/wiretrustee
- /var/lib/wiretrustee/dashboard/letsencrypt:/etc/letsencrypt:ro
- ./management.json:/etc/wiretrustee/management.json
# - /var/log/wiretrustee/management.log:/var/log/wiretrustee/management.log
ports:
- 33073:33073 #gRPC port
- 33071:33071 #HTTP port
# # port and command for Let's Encrypt validation
# - 443:443
# command: ["--letsencrypt-domain", "$WIRETRUSTEE_DOMAIN", "--log-file", "console"]
# Coturn
coturn:
image: coturn/coturn
restart: unless-stopped
domainname: <YOUR DOMAIN>
volumes:
- ./turnserver.conf:/etc/turnserver.conf:ro
# - ./privkey.pem:/etc/coturn/private/privkey.pem:ro
# - ./cert.pem:/etc/coturn/certs/cert.pem:ro
network_mode: host
volumes:
wiretrustee-mgmt:
wiretrustee-signal:

View File

@@ -1,37 +0,0 @@
{
"Stuns": [
{
"Proto": "udp",
"URI": "stun:stun.wiretrustee.com:3468",
"Username": "",
"Password": null
}
],
"TURNConfig": {
"Turns": [
{
"Proto": "udp",
"URI": "turn:stun.wiretrustee.com:3468",
"Username": "some_user",
"Password": "c29tZV9wYXNzd29yZA=="
}
],
"CredentialsTTL": "1h",
"Secret": "c29tZV9wYXNzd29yZA==",
"TimeBasedCredentials": true
},
"Signal": {
"Proto": "http",
"URI": "signal.wiretrustee.com:10000",
"Username": "",
"Password": null
},
"Datadir": "",
"HttpConfig": {
"LetsEncryptDomain": "<PASTE YOUR LET'S ENCRYPT DOMAIN HERE>",
"Address": "0.0.0.0:33071",
"AuthIssuer": "<PASTE YOUR AUTH0 ISSUER HERE>,",
"AuthAudience": "<PASTE YOUR AUTH0 AUDIENCE HERE>",
"AuthKeysLocation": "<PASTE YOUR AUTH0 PUBLIC JWT KEYS LOCATION HERE>"
}
}

View File

@@ -0,0 +1,39 @@
{
"Stuns": [
{
"Proto": "udp",
"URI": "stun:$WIRETRUSTEE_DOMAIN:3478",
"Username": "",
"Password": null
}
],
"TURNConfig": {
"Turns": [
{
"Proto": "udp",
"URI": "turn:$WIRETRUSTEE_DOMAIN:3478",
"Username": "",
"Password": null
}
],
"CredentialsTTL": "12h",
"Secret": "secret",
"TimeBasedCredentials": false
},
"Signal": {
"Proto": "http",
"URI": "$WIRETRUSTEE_DOMAIN:10000",
"Username": "",
"Password": null
},
"Datadir": "",
"HttpConfig": {
"LetsEncryptDomain": "",
"CertFile":"/etc/letsencrypt/live/$WIRETRUSTEE_DOMAIN/fullchain.pem",
"CertKey":"/etc/letsencrypt/live/$WIRETRUSTEE_DOMAIN/privkey.pem",
"Address": "0.0.0.0:33071",
"AuthIssuer": "https://$WIRETRUSTEE_AUTH0_DOMAIN/",
"AuthAudience": "$WIRETRUSTEE_AUTH0_AUDIENCE",
"AuthKeysLocation": "https://$WIRETRUSTEE_AUTH0_DOMAIN/.well-known/jwks.json"
}
}

View File

@@ -0,0 +1,10 @@
# e.g. app.mydomain.com
WIRETRUSTEE_DOMAIN=""
# e.g. dev-24vkclam.us.auth0.com
WIRETRUSTEE_AUTH0_DOMAIN=""
# e.g. 61u3JMXRO0oOevc7gCkZLCwePQvT4lL0
WIRETRUSTEE_AUTH0_CLIENT_ID=""
# e.g. https://app.mydomain.com/
WIRETRUSTEE_AUTH0_AUDIENCE=""
# e.g. hello@mydomain.com
WIRETRUSTEE_LETSENCRYPT_EMAIL=""

View File

@@ -14,7 +14,8 @@ Flags:
-h, --help help for management -h, --help help for management
--letsencrypt-domain string a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS --letsencrypt-domain string a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS
--port int server port to listen on (default 33073) --port int server port to listen on (default 33073)
--cert-file string Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect
--cert-key string Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect
Global Flags: Global Flags:
--config string Wiretrustee config file location to write new config to (default "/etc/wiretrustee/config.json") --config string Wiretrustee config file location to write new config to (default "/etc/wiretrustee/config.json")
--log-level string (default "info") --log-level string (default "info")

View File

@@ -45,7 +45,7 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
})) }))
if err != nil { if err != nil {
log.Errorf("failed creating connection to Management Srvice %v", err) log.Errorf("failed creating connection to Management Service %v", err)
return nil, err return nil, err
} }
@@ -65,8 +65,8 @@ func (c *Client) Close() error {
} }
//defaultBackoff is a basic backoff mechanism for general issues //defaultBackoff is a basic backoff mechanism for general issues
func defaultBackoff() backoff.BackOff { func defaultBackoff(ctx context.Context) backoff.BackOff {
return &backoff.ExponentialBackOff{ return backoff.WithContext(&backoff.ExponentialBackOff{
InitialInterval: 800 * time.Millisecond, InitialInterval: 800 * time.Millisecond,
RandomizationFactor: backoff.DefaultRandomizationFactor, RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier, Multiplier: backoff.DefaultMultiplier,
@@ -74,14 +74,14 @@ func defaultBackoff() backoff.BackOff {
MaxElapsedTime: 24 * 3 * time.Hour, //stop after 3 days trying MaxElapsedTime: 24 * 3 * time.Hour, //stop after 3 days trying
Stop: backoff.Stop, Stop: backoff.Stop,
Clock: backoff.SystemClock, Clock: backoff.SystemClock,
} }, ctx)
} }
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages // Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
// Blocking request. The result will be sent via msgHandler callback function // Blocking request. The result will be sent via msgHandler callback function
func (c *Client) Sync(msgHandler func(msg *proto.SyncResponse) error) error { func (c *Client) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
var backOff = defaultBackoff() var backOff = defaultBackoff(c.ctx)
operation := func() error { operation := func() error {
@@ -114,7 +114,7 @@ func (c *Client) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
err := backoff.Retry(operation, backOff) err := backoff.Retry(operation, backOff)
if err != nil { if err != nil {
log.Errorf("exiting Management Service connection retry loop due to unrecoverable error %s ", err) log.Warnf("exiting Management Service connection retry loop due to unrecoverable error: %s", err)
return err return err
} }
@@ -145,7 +145,7 @@ func (c *Client) receiveEvents(stream proto.ManagementService_SyncClient, server
return err return err
} }
if err != nil { if err != nil {
log.Errorf("disconnected from Management Service sync stream: %v", err) log.Warnf("disconnected from Management Service sync stream: %v", err)
return err return err
} }
@@ -159,7 +159,7 @@ func (c *Client) receiveEvents(stream proto.ManagementService_SyncClient, server
err = msgHandler(decryptedResp) err = msgHandler(decryptedResp)
if err != nil { if err != nil {
log.Errorf("failed handling an update message received from Management Service %v", err.Error()) log.Errorf("failed handling an update message received from Management Service: %v", err.Error())
return err return err
} }
} }

View File

@@ -2,6 +2,7 @@ package cmd
import ( import (
"context" "context"
"crypto/tls"
"flag" "flag"
"fmt" "fmt"
"github.com/wiretrustee/wiretrustee/management/server" "github.com/wiretrustee/wiretrustee/management/server"
@@ -25,6 +26,8 @@ var (
mgmtDataDir string mgmtDataDir string
mgmtConfig string mgmtConfig string
mgmtLetsencryptDomain string mgmtLetsencryptDomain string
certFile string
certKey string
kaep = keepalive.EnforcementPolicy{ kaep = keepalive.EnforcementPolicy{
MinTime: 15 * time.Second, MinTime: 15 * time.Second,
@@ -71,12 +74,23 @@ var (
var httpServer *http.Server var httpServer *http.Server
if config.HttpConfig.LetsEncryptDomain != "" { if config.HttpConfig.LetsEncryptDomain != "" {
//automatically generate a new certificate with Let's Encrypt
certManager := encryption.CreateCertManager(config.Datadir, config.HttpConfig.LetsEncryptDomain) certManager := encryption.CreateCertManager(config.Datadir, config.HttpConfig.LetsEncryptDomain)
transportCredentials := credentials.NewTLS(certManager.TLSConfig()) transportCredentials := credentials.NewTLS(certManager.TLSConfig())
opts = append(opts, grpc.Creds(transportCredentials)) opts = append(opts, grpc.Creds(transportCredentials))
httpServer = http.NewHttpsServer(config.HttpConfig, certManager, accountManager) httpServer = http.NewHttpsServer(config.HttpConfig, certManager, accountManager)
} else if config.HttpConfig.CertFile != "" && config.HttpConfig.CertKey != "" {
//use provided certificate
tlsConfig, err := loadTLSConfig(config.HttpConfig.CertFile, config.HttpConfig.CertKey)
if err != nil {
log.Fatal("cannot load TLS credentials: ", err)
}
transportCredentials := credentials.NewTLS(tlsConfig)
opts = append(opts, grpc.Creds(transportCredentials))
httpServer = http.NewHttpsServerWithTLSConfig(config.HttpConfig, tlsConfig, accountManager)
} else { } else {
//start server without SSL
httpServer = http.NewHttpServer(config.HttpConfig, accountManager) httpServer = http.NewHttpServer(config.HttpConfig, accountManager)
} }
@@ -136,14 +150,37 @@ func loadConfig() (*server.Config, error) {
config.Datadir = mgmtDataDir config.Datadir = mgmtDataDir
} }
if certKey != "" && certFile != "" {
config.HttpConfig.CertFile = certFile
config.HttpConfig.CertKey = certKey
}
return config, err return config, err
} }
func loadTLSConfig(certFile string, certKey string) (*tls.Config, error) {
// Load server's certificate and private key
serverCert, err := tls.LoadX509KeyPair(certFile, certKey)
if err != nil {
return nil, err
}
// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{serverCert},
ClientAuth: tls.NoClientCert,
}
return config, nil
}
func init() { func init() {
mgmtCmd.Flags().IntVar(&mgmtPort, "port", 33073, "server port to listen on") mgmtCmd.Flags().IntVar(&mgmtPort, "port", 33073, "server port to listen on")
mgmtCmd.Flags().StringVar(&mgmtDataDir, "datadir", "/var/lib/wiretrustee/", "server data directory location") mgmtCmd.Flags().StringVar(&mgmtDataDir, "datadir", "/var/lib/wiretrustee/", "server data directory location")
mgmtCmd.Flags().StringVar(&mgmtConfig, "config", "/etc/wiretrustee/management.json", "Wiretrustee config file location. Config params specified via command line (e.g. datadir) have a precedence over configuration from this file") mgmtCmd.Flags().StringVar(&mgmtConfig, "config", "/etc/wiretrustee/management.json", "Wiretrustee config file location. Config params specified via command line (e.g. datadir) have a precedence over configuration from this file")
mgmtCmd.Flags().StringVar(&mgmtLetsencryptDomain, "letsencrypt-domain", "", "a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS") mgmtCmd.Flags().StringVar(&mgmtLetsencryptDomain, "letsencrypt-domain", "", "a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS")
mgmtCmd.Flags().StringVar(&certFile, "cert-file", "", "Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
mgmtCmd.Flags().StringVar(&certKey, "cert-key", "", "Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
rootCmd.MarkFlagRequired("config") //nolint rootCmd.MarkFlagRequired("config") //nolint

View File

@@ -36,7 +36,11 @@ type TURNConfig struct {
// HttpServerConfig is a config of the HTTP Management service server // HttpServerConfig is a config of the HTTP Management service server
type HttpServerConfig struct { type HttpServerConfig struct {
LetsEncryptDomain string LetsEncryptDomain string
Address string //CertFile is the location of the certificate
CertFile string
//CertKey is the location of the certificate private key
CertKey string
Address string
// AuthAudience identifies the recipients that the JWT is intended for (aud in JWT) // AuthAudience identifies the recipients that the JWT is intended for (aud in JWT)
AuthAudience string AuthAudience string
// AuthIssuer identifies principal that issued the JWT. // AuthIssuer identifies principal that issued the JWT.

View File

@@ -2,6 +2,7 @@ package http
import ( import (
"context" "context"
"crypto/tls"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/rs/cors" "github.com/rs/cors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@@ -17,10 +18,11 @@ type Server struct {
server *http.Server server *http.Server
config *s.HttpServerConfig config *s.HttpServerConfig
certManager *autocert.Manager certManager *autocert.Manager
tlsConfig *tls.Config
accountManager *s.AccountManager accountManager *s.AccountManager
} }
// NewHttpsServer creates a new HTTPs server (with HTTPS support) // NewHttpsServer creates a new HTTPs server (with HTTPS support) and a certManager that is responsible for generating and renewing Let's Encrypt certificate
// The listening address will be :443 no matter what was specified in s.HttpServerConfig.Address // The listening address will be :443 no matter what was specified in s.HttpServerConfig.Address
func NewHttpsServer(config *s.HttpServerConfig, certManager *autocert.Manager, accountManager *s.AccountManager) *Server { func NewHttpsServer(config *s.HttpServerConfig, certManager *autocert.Manager, accountManager *s.AccountManager) *Server {
server := &http.Server{ server := &http.Server{
@@ -32,6 +34,18 @@ func NewHttpsServer(config *s.HttpServerConfig, certManager *autocert.Manager, a
return &Server{server: server, config: config, certManager: certManager, accountManager: accountManager} return &Server{server: server, config: config, certManager: certManager, accountManager: accountManager}
} }
// NewHttpsServerWithTLSConfig creates a new HTTPs server with a provided tls.Config.
// Usually used when you already have a certificate
func NewHttpsServerWithTLSConfig(config *s.HttpServerConfig, tlsConfig *tls.Config, accountManager *s.AccountManager) *Server {
server := &http.Server{
Addr: config.Address,
WriteTimeout: time.Second * 15,
ReadTimeout: time.Second * 15,
IdleTimeout: time.Second * 60,
}
return &Server{server: server, config: config, tlsConfig: tlsConfig, accountManager: accountManager}
}
// NewHttpServer creates a new HTTP server (without HTTPS) // NewHttpServer creates a new HTTP server (without HTTPS)
func NewHttpServer(config *s.HttpServerConfig, accountManager *s.AccountManager) *Server { func NewHttpServer(config *s.HttpServerConfig, accountManager *s.AccountManager) *Server {
return NewHttpsServer(config, nil, accountManager) return NewHttpsServer(config, nil, accountManager)
@@ -71,13 +85,26 @@ func (s *Server) Start() error {
if s.certManager != nil { if s.certManager != nil {
// if HTTPS is enabled we reuse the listener from the cert manager // if HTTPS is enabled we reuse the listener from the cert manager
listener := s.certManager.Listener() listener := s.certManager.Listener()
log.Infof("http server listening on %s", listener.Addr()) log.Infof("HTTPs server listening on %s with Let's Encrypt autocert configured", listener.Addr())
if err = http.Serve(listener, s.certManager.HTTPHandler(r)); err != nil { if err = http.Serve(listener, s.certManager.HTTPHandler(r)); err != nil {
log.Errorf("failed to serve https server: %v", err) log.Errorf("failed to serve https server: %v", err)
return err return err
} }
} else if s.tlsConfig != nil {
listener, err := tls.Listen("tcp", s.config.Address, s.tlsConfig)
if err != nil {
log.Errorf("failed to serve https server: %v", err)
return err
}
log.Infof("HTTPs server listening on %s", listener.Addr())
if err = http.Serve(listener, r); err != nil {
log.Errorf("failed to serve https server: %v", err)
return err
}
} else { } else {
log.Infof("http server listening on %s", s.server.Addr) log.Infof("HTTP server listening on %s", s.server.Addr)
if err = s.server.ListenAndServe(); err != nil { if err = s.server.ListenAndServe(); err != nil {
log.Errorf("failed to serve http server: %v", err) log.Errorf("failed to serve http server: %v", err)
return err return err

View File

@@ -12,30 +12,27 @@ fi
cleanInstall() { cleanInstall() {
printf "\033[32m Post Install of an clean install\033[0m\n" printf "\033[32m Post Install of an clean install\033[0m\n"
# Step 3 (clean install), enable the service in the proper way for this platform # Step 3 (clean install), enable the service in the proper way for this platform
if [ "${use_systemctl}" = "True" ]; then /usr/local/bin/wiretrustee service install
printf "\033[32m Reload the service unit from disk\033[0m\n" /usr/local/bin/wiretrustee service start
systemctl daemon-reload ||:
printf "\033[32m Unmask the service\033[0m\n"
systemctl unmask wiretrustee ||:
printf "\033[32m Set the preset flag for the service unit\033[0m\n"
systemctl preset wiretrustee ||:
printf "\033[32m Set the enabled flag for the service unit\033[0m\n"
systemctl enable wiretrustee ||:
systemctl restart wiretrustee ||:
fi
} }
upgrade() { upgrade() {
printf "\033[32m Post Install of an upgrade\033[0m\n" printf "\033[32m Post Install of an upgrade\033[0m\n"
if [ "${use_systemctl}" = "True" ]; then if [ "${use_systemctl}" = "True" ]; then
printf "\033[32m Reload the service unit from disk\033[0m\n" printf "\033[32m Stopping the service\033[0m\n"
systemctl daemon-reload ||: systemctl stop wiretrustee 2> /dev/null || true
printf "\033[32m Restarting the service\033[0m\n"
systemctl restart wiretrustee ||:
fi fi
if [ -e /lib/systemd/system/wiretrustee.service ]; then
rm -f /lib/systemd/system/wiretrustee.service
systemctl daemon-reload
fi
# will trow an error until everyone upgrade
/usr/local/bin/wiretrustee service uninstall 2> /dev/null || true
/usr/local/bin/wiretrustee service install
/usr/local/bin/wiretrustee service start
} }
# Step 2, check if this is a clean install or an upgrade # Check if this is a clean install or an upgrade
action="$1" action="$1"
if [ "$1" = "configure" ] && [ -z "$2" ]; then if [ "$1" = "configure" ] && [ -z "$2" ]; then
# Alpine linux does not pass args, and deb passes $1=configure # Alpine linux does not pass args, and deb passes $1=configure
@@ -50,12 +47,9 @@ case "$action" in
cleanInstall cleanInstall
;; ;;
"2" | "upgrade") "2" | "upgrade")
printf "\033[32m Post Install of an upgrade\033[0m\n"
upgrade upgrade
;; ;;
*) *)
# $1 == version being installed
printf "\033[32m install\033[0m"
cleanInstall cleanInstall
;; ;;
esac esac

View File

@@ -0,0 +1,43 @@
#!/bin/sh
# decide if we should use systemd or init/upstart
use_systemctl="True"
systemd_version=0
if ! command -V systemctl >/dev/null 2>&1; then
use_systemctl="False"
else
systemd_version=$(systemctl --version | head -1 | sed 's/systemd //g')
fi
remove() {
printf "\033[32m Pre uninstall\033[0m\n"
if [ "${use_systemctl}" = "True" ]; then
printf "\033[32m Stopping the service\033[0m\n"
systemctl stop wiretrustee || true
if [ -e /lib/systemd/system/wiretrustee.service ]; then
rm -f /lib/systemd/system/wiretrustee.service
systemctl daemon-reload || true
fi
fi
printf "\033[32m Uninstalling the service\033[0m\n"
/usr/local/bin/wiretrustee service uninstall || true
if [ "${use_systemctl}" = "True" ]; then
printf "\n\033[32m running daemon reload\033[0m\n"
systemctl daemon-reload || true
fi
}
action="$1"
case "$action" in
"0" | "remove")
remove
;;
*)
exit 0
;;
esac

View File

@@ -1,30 +0,0 @@
{
"PrivateKey": "",
"Peers": [
{
"WgPubKey": "",
"WgAllowedIps": ""
}
],
"StunTurnURLs": [
{
"Scheme": 1,
"Host": "",
"Port": 3468,
"Username": "",
"Password": "",
"Proto": 1
},
{
"Scheme": 3,
"Host": "",
"Port": 3468,
"Username": "",
"Password": "",
"Proto": 1
}
],
"SignalAddr": "",
"WgAddr": "",
"WgIface": ""
}

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Wiretrustee Service
After=multi-user.target network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/wiretrustee up --config /etc/wiretrustee/config.json --log-level debug
[Install]
WantedBy=multi-user.target

View File

@@ -76,8 +76,8 @@ func NewClient(ctx context.Context, addr string, key wgtypes.Key, tlsEnabled boo
} }
//defaultBackoff is a basic backoff mechanism for general issues //defaultBackoff is a basic backoff mechanism for general issues
func defaultBackoff() backoff.BackOff { func defaultBackoff(ctx context.Context) backoff.BackOff {
return &backoff.ExponentialBackOff{ return backoff.WithContext(&backoff.ExponentialBackOff{
InitialInterval: 800 * time.Millisecond, InitialInterval: 800 * time.Millisecond,
RandomizationFactor: backoff.DefaultRandomizationFactor, RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier, Multiplier: backoff.DefaultMultiplier,
@@ -85,7 +85,8 @@ func defaultBackoff() backoff.BackOff {
MaxElapsedTime: 24 * 3 * time.Hour, //stop after 3 days trying MaxElapsedTime: 24 * 3 * time.Hour, //stop after 3 days trying
Stop: backoff.Stop, Stop: backoff.Stop,
Clock: backoff.SystemClock, Clock: backoff.SystemClock,
} }, ctx)
} }
// Receive Connects to the Signal Exchange message stream and starts receiving messages. // Receive Connects to the Signal Exchange message stream and starts receiving messages.
@@ -96,12 +97,13 @@ func (c *Client) Receive(msgHandler func(msg *proto.Message) error) {
c.connWg.Add(1) c.connWg.Add(1)
go func() { go func() {
var backOff = defaultBackoff() var backOff = defaultBackoff(c.ctx)
operation := func() error { operation := func() error {
err := c.connect(c.key.PublicKey().String(), msgHandler) err := c.connect(c.key.PublicKey().String(), msgHandler)
if err != nil { if err != nil {
log.Warnf("disconnected from the Signal Exchange due to an error %s. Retrying ... ", err) log.Warnf("disconnected from the Signal Exchange due to an error: %v", err)
c.connWg.Add(1) c.connWg.Add(1)
return err return err
} }
@@ -112,7 +114,7 @@ func (c *Client) Receive(msgHandler func(msg *proto.Message) error) {
err := backoff.Retry(operation, backOff) err := backoff.Retry(operation, backOff)
if err != nil { if err != nil {
log.Errorf("error while communicating with the Signal Exchange %s ", err) log.Errorf("exiting Signal Service connection retry loop due to unrecoverable error: %s", err)
return return
} }
}() }()