Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/christophwitzko/wg-hub
WireGuard® hub server
https://github.com/christophwitzko/wg-hub
wireguard wireguard-vpn
Last synced: 23 days ago
JSON representation
WireGuard® hub server
- Host: GitHub
- URL: https://github.com/christophwitzko/wg-hub
- Owner: christophwitzko
- License: mit
- Created: 2023-01-16T12:54:00.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-02-26T20:06:43.000Z (9 months ago)
- Last Synced: 2024-10-13T18:25:45.483Z (25 days ago)
- Topics: wireguard, wireguard-vpn
- Language: TypeScript
- Homepage:
- Size: 692 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# wg-hub
This application acts as a WireGuard® hub server to connect multiple clients (behind a NAT) with each other through a single hub. It runs entirely in the user space and can easily be deployed as a docker container or directly to [Fly.io](https://fly.io) (see [fly.toml](./fly.toml)).
For example, if `Host A` and `Host B` want to communicate with each other, they both connect to the `wg-hub` server.
![](./docs/wg-hub.svg)
`Host A` example WireGuard® config:
```
[Interface]
Address = 192.168.0.1/32
PrivateKey = ...[Peer]
PublicKey = hub/...
Endpoint = 1.2.3.4:9999
AllowedIPs = 192.168.0.0/24
PersistentKeepalive = 30
````Host B` example WireGuard® config:
```
[Interface]
Address = 192.168.0.2/32
PrivateKey = ...[Peer]
PublicKey = hub/...
Endpoint = 1.2.3.4:9999
AllowedIPs = 192.168.0.0/24
PersistentKeepalive = 30
````wireguard-hub.yaml` example config:
```yaml
privateKey: ...
port: 9999
peers:
- publicKey: hostA/...
allowedIPs: 192.168.0.1/32
- publicKey: hostB/...
allowedIPs: 192.168.0.2/32```
Start the `wg-hub` instance:
```
$ ./wg-hub --log-level info
INFO[2023-01-20T20:15:10+01:00] using config: wireguard-hub.yaml
INFO[2023-01-20T20:15:10+01:00] listening on :9999
INFO[2023-01-20T20:15:10+01:00] adding peer(876f…29ed): 192.168.0.1/32
INFO[2023-01-20T20:15:10+01:00] adding peer(876f…92de): 192.168.0.2/32```
Now `Host A` and `Host B` can communicate with each other through the `wg-hub` server.
## Installation
### Binary
```bash
curl -SL https://get-release.xyz/christophwitzko/wg-hub/linux/amd64 -o ./wg-hub && chmod +x ./wg-hub
```### Docker
```bash
docker run -it --rm \
-e PRIVATE_KEY="..."
-e PORT=9999 \
-e PEER_1="hostA/...,192.168.0.1/32" \
-e PEER_2="hostB/...,192.168.0.2/32" \
-p 9999:9999/udp \
ghcr.io/christophwitzko/wg-hub
```## Webui
To enable the Webui and dynamically manage peers the following config options need to be set.
```yaml
hubAddress: 192.168.0.254
webui: true
webuiJWTSecret: supersecure # random secret to sign JWT tokens
# use `caddy hash-password` or `htpasswd -nB admin` to generate the hash
webuiAdminPasswordHash: $2a$14$hTHK6KAynSb7tWknK4CvUum2eFVHIDSzbOuOlgDeP4bQW91ujnlli #admin
```
The Webui will be running on the `hubAddress` and port 80 (e.g. http://192.168.0.254).![](./docs/webui.png)
## API
The API will be served under the same endpoint the Webui is running (`hubAddress`). All API request (except `POST /api/auth`) require a valid `Authorization` header with the value `Bearer `. The token can be obtained by sending a `POST /api/auth` request with the `username` and `password` in the request body.
### POST /api/auth
Example request body
```json
{
"username": "admin",
"password": "admin"
}
```Example response body
```json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3OTM3MTI2NTgsImlhdCI6MTcwNzMxMjY1OCwidXNlcm5hbWUiOiJhZG1pbiJ9.fVvahKZPJ2LUZE_dOIYQ6toYFN4x_r295jxINqlXY88"
}
```### GET /api/auth
Example response body
```json
{
"exp": "2026-11-03T13:30:58Z",
"iat": "2024-02-07T13:30:58Z",
"username": "admin"
}
```### GET /api/peers
Example response body
```json
[
{
"publicKey": "ZbSHDrKwqmsQKpO5T6lOY/iipbcJpT4DPXTHGsLaGUU=",
"allowedIP": "192.168.0.254/32",
"endpoint": "127.0.0.1:64404",
"lastHandshake": 1707312755,
"txBytes": 4696,
"rxBytes": 4968,
"isHub": true,
"isRequester": false
},
{
"publicKey": "h1/wJ5KoQX1fQzQ25rlHb18wgAG80vkDLtn8B7pxOW0=",
"allowedIP": "192.168.0.1/32",
"endpoint": "127.0.0.1:58646",
"lastHandshake": 1707312760,
"txBytes": 4152,
"rxBytes": 5640,
"isHub": false,
"isRequester": true
},
{
"publicKey": "h2/PAmEgoIRLYBDDTL3dZKAOaLEhu4270vlNWXFMSys=",
"allowedIP": "192.168.0.2/32",
"endpoint": "",
"lastHandshake": 0,
"txBytes": 0,
"rxBytes": 0,
"isHub": false,
"isRequester": false
}
]
```### GET /api/config
Example response body
```json
{
"config": "privateKey: \nport: 9999\nlogLevel: debug\nhubAddress: 192.168.0.254\ndebugServer: true\nwebui: true\nwebuiJWTSecret: \nwebuiAdminPasswordHash: $2a$14$hTHK6KAynSb7tWknK4CvUum2eFVHIDSzbOuOlgDeP4bQW91ujnlli\npeers:\n - publicKey: h1/wJ5KoQX1fQzQ25rlHb18wgAG80vkDLtn8B7pxOW0=\n allowedIP: 192.168.0.1/32\n - publicKey: h2/PAmEgoIRLYBDDTL3dZKAOaLEhu4270vlNWXFMSys=\n allowedIP: 192.168.0.2/32\n"
}
```### POST /api/peers
Example requeset body
```json
{
"allowedIP": "192.168.0.55/32"
}
```Example response body
```json
{
"privateKey": "KEta3N3FXLlSlY7o2C22ty2nXnw+FJ44zyCFXxznrHU=",
"publicKey": "ylD5KC3idzgxdA+LnAW5QclS5tg/vilMbqn9Y6oKpwQ=",
"allowedIP": "192.168.0.55/32",
"hubNetwork": "192.168.0.0/24"
}
```### PUT /api/peers/:publicKey
Example requeset body
```json
{
"allowedIP": "192.168.0.55/32"
}
```Example response body
```json
{
"allowedIP": "192.168.0.55/32",
"hubNetwork": "192.168.0.0/24"
}
```### DELETE /api/peers/:publicKey
Example response body
```json
{
"status": "ok"
}
```### GET /api/hub
Example response body
```json
{
"publicKey": "hub/+QaIRMomZNnjd6zZqZY+MiyH0R9aalxhhbnvPXE=",
"port": 9999,
"hubNetwork": "192.168.0.0/24",
"randomFreeIP": "192.168.0.130/32"
}
```## Legal
[WireGuard](https://www.wireguard.com/) is a registered trademark of Jason A. Donenfeld.