Compare commits
36 Commits
v0.1.0-bet
...
v0.2.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b2c26847b | ||
|
|
595ea0d4f8 | ||
|
|
f714868fdd | ||
|
|
81821a1f39 | ||
|
|
842b143a48 | ||
|
|
1323a74db0 | ||
|
|
74485d3b13 | ||
|
|
bef3b3392b | ||
|
|
fcea3c99d4 | ||
|
|
96799a25b5 | ||
|
|
07291cdb93 | ||
|
|
21139938c1 | ||
|
|
5cf2d0a6a9 | ||
|
|
8551afe04e | ||
|
|
1685817171 | ||
|
|
e17f662683 | ||
|
|
a764fb870c | ||
|
|
cabff941ac | ||
|
|
b5f35dfb5e | ||
|
|
1d426b7f81 | ||
|
|
e4f9406d44 | ||
|
|
7c79ff62ee | ||
|
|
32c369257b | ||
|
|
08dd719aa1 | ||
|
|
84c714dd93 | ||
|
|
996c8d7c62 | ||
|
|
25e68ce493 | ||
|
|
4881dcbd51 | ||
|
|
d505f70972 | ||
|
|
6a80684378 | ||
|
|
2624a7c4e6 | ||
|
|
9a412e7bf1 | ||
|
|
b5d1690129 | ||
|
|
d4bec15ca3 | ||
|
|
3212aca7c7 | ||
|
|
b97a2251d3 |
33
.github/workflows/release.yml
vendored
@@ -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 }}" }'
|
||||||
2
.gitignore
vendored
@@ -4,3 +4,5 @@ dist/
|
|||||||
.env
|
.env
|
||||||
conf.json
|
conf.json
|
||||||
http-cmds.sh
|
http-cmds.sh
|
||||||
|
infrastructure_files/management.json
|
||||||
|
infrastructure_files/docker-compose.yml
|
||||||
@@ -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
|
||||||
@@ -197,3 +215,19 @@ brews:
|
|||||||
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
|
||||||
202
README.md
@@ -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
|
|
||||||

|
|
||||||
|
|
||||||
### 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).
|
||||||
|
|||||||
@@ -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)")
|
//}
|
||||||
}
|
|
||||||
|
|||||||
@@ -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,7 +24,6 @@ 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: "",
|
||||||
@@ -31,6 +32,7 @@ var (
|
|||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
err := runClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
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 {
|
||||||
|
go func() {
|
||||||
stopCh <- 1
|
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")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
189
client/cmd/up.go
@@ -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 {
|
||||||
//validate our peer's Wireguard PRIVATE key
|
log.Warnf("failed retrieving service status: %v", err)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
if srvStatus == service.StatusRunning {
|
||||||
// connect (just a connection, no stream yet) and login to Management Service to get an initial global Wiretrustee config
|
stopCmd.Run(cmd, args)
|
||||||
mgmClient, loginResp, err := connectToManagement(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn(err)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
return startCmd.RunE(cmd, args)
|
||||||
// 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()
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -0,0 +1,2 @@
|
|||||||
|
### Architecture
|
||||||
|
TODO
|
||||||
BIN
docs/media/add-peer.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/media/auth.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/media/empty-peers.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
docs/media/high-level-dia.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
docs/media/logo-full.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/media/logo.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/media/peerA.gif
Normal file
|
After Width: | Height: | Size: 409 KiB |
BIN
docs/media/peerB.gif
Normal file
|
After Width: | Height: | Size: 526 KiB |
|
Before Width: | Height: | Size: 5.9 MiB After Width: | Height: | Size: 5.9 MiB |
BIN
docs/media/peers.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
41
docs/quickstart.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
## Quickstart guide (Cloud Managed version)
|
||||||
|
Step-by-step video guide on YouTube:
|
||||||
|
|
||||||
|
[](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
@@ -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:
|
||||||
|
|
||||||
|
[](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
@@ -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
@@ -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=
|
||||||
|
|||||||
7
infrastructure_files/configure.sh
Executable 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
|
||||||
@@ -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:
|
|
||||||
61
infrastructure_files/docker-compose.yml.tmpl
Normal 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:
|
||||||
@@ -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>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
39
infrastructure_files/management.json.tmpl
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
infrastructure_files/setup.env
Normal 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=""
|
||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ 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
|
||||||
|
//CertFile is the location of the certificate
|
||||||
|
CertFile string
|
||||||
|
//CertKey is the location of the certificate private key
|
||||||
|
CertKey string
|
||||||
Address 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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
43
release_files/pre_remove.sh
Normal 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
|
||||||
@@ -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": ""
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||