-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 07d8892
Showing
11 changed files
with
1,123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
FROM golang:1.13 AS builder | ||
|
||
WORKDIR /go/src/github.com/jamescun/wireguard-api | ||
COPY . /go/src/github.com/jamescun/wireguard-api | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -o wireguard-api cmd/wireguard-api.go | ||
|
||
|
||
FROM scratch | ||
COPY --from=builder /go/src/github.com/jamescun/wireguard-api/wireguard-api /bin/wireguard-api | ||
CMD ["wireguard-api"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2020 James Cunningham | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
# WireGuard-API 🔐 | ||
|
||
WireGuard-API presents a JSON-RPC interface on top of a WireGuard network interface. | ||
|
||
* 💖 **Add/Remove Peers** | ||
Modify known peers without reloading | ||
|
||
* 📈 **Statistics** | ||
View data usage and allowed IPs of all peers | ||
|
||
* 📞 **JSON-RPC 2.0 API** | ||
No custom client integrations required, standard API accepted everywhere. | ||
|
||
**NOTE:** WireGuard-API is currently only compatible with the WireGuard Linux kernel module and userland wireguard-go. It does not currently work with the MacOS NetworkExtension. | ||
|
||
|
||
## Getting WireGuard-API | ||
|
||
### Pre-Built Binary | ||
|
||
Binaries for Linux are available [here](https://github.com/jamescun/wireguard-api/releases). | ||
|
||
### Build Yourself | ||
|
||
WireGuard-API requires at least Go 1.13. | ||
|
||
```sh | ||
go install github.com/jamescun/wireguard-api/cmd | ||
``` | ||
|
||
This should install the server binary `wireguard-api` in your $GOPATH/bin. | ||
|
||
### Docker | ||
|
||
WireGuard-API can also be run inside a Docker container, however the container will need to existing within the same network namespace as the host and have network administrator capability (CAP_NET_ADMIN) to be able to control the WireGuard interface. | ||
|
||
```sh | ||
docker run --name=wireguard-api -d -p 8080:8080 --network host --cap-add NET_ADMIN james/wireguard-api:latest wireguard-api --device=<my device> | ||
``` | ||
|
||
|
||
## Configuring WireGuard-API | ||
|
||
WireGuard is configured using command line arguments: | ||
|
||
```sh | ||
$ wireguard-api --help | ||
WireGuard-API presents a JSON-RPC API to a WireGuard device | ||
Usage: wireguard-api [options] | ||
|
||
Helpers: | ||
--list-devices list wireguard devices on this system and their name to be | ||
given to --device | ||
--version display the version number of WireGuard-API | ||
|
||
Options: | ||
--device=<name> (required) name of WireGuard device to manager | ||
--listen=<[host:]port> address where API server will bind | ||
(default localhost:8080) | ||
--tls enable Transport Layer Security (SSL) on server | ||
--tls-key TLS private key | ||
--tks-cert TLS certificate file | ||
--tls-client-ca enable mutual TLS authentication (mTLS) of the client | ||
|
||
Warnings: | ||
WireGuard-API can perform sensitive network operations, as such it should not | ||
be publically exposed. It should be bound to the local interface only, or | ||
failing that, be behind an authenticating proxy or have mTLS enabled. | ||
``` | ||
|
||
The only required argument is `--device`, which tells WireGuard-API which WireGuard device to control. To control multiple WireGuard devices, launch multiple instances of WireGuard-API. | ||
|
||
By default, this launches WireGuard-API on `localhost:8080` which may conflict with the typical development environment. To bind it elsewhere, use `--listen`: | ||
|
||
```sh | ||
$ wireguard-api --device=<my device> --listen=localhost:1234 | ||
``` | ||
|
||
**NOTE:** `--listen` will not prevent you from binding the server to a public interface. Care should be taken to prevent public access to the WireGuard-API server; such as binding it only to a local interface, placing an authenticating reverse proxy in-front of it or using mTLS (detailed below). | ||
|
||
WireGuard-API can optional listen using TLS and HTTP/2. To enable TLS, you will also need a TLS Certificate and matching private key. | ||
|
||
```sh | ||
$ wireguard-api --device=<my device> --tls --tls-key=key.pem --tls-cert=cert.pem | ||
``` | ||
|
||
And optionally WireGuard-API can request and validate client certificates to implement TLS Mutual Authentication (mTLS): | ||
|
||
```sh | ||
$ wireguard-api --device=<my device> --tls --tls-key=key.pem --tls-cert=cert.pem --tls-client-ca=clientca.pem | ||
``` | ||
|
||
|
||
## Using WireGuard-API | ||
|
||
WireGuard-API exposes a JSON-RPC 2.0 API with five methods. | ||
|
||
All calls are made using the POST method, and require the `Content-Type` header to be set to `application/json`. The server ignores the URL path it is given, allowing the server to be mounted under another hierarchy in a reverse proxy. | ||
|
||
The structures expected by the server can be found in [client/client.go](client/client.go). | ||
|
||
|
||
### GetDeviceInfo | ||
|
||
GetDeviceInfo returns information such as the public key and type of interface for the currently configured device. | ||
|
||
```sh | ||
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "GetDeviceInfo", "params": {}}' | ||
``` | ||
|
||
#### Example Response | ||
|
||
```json | ||
{ | ||
"device": { | ||
"name": "wg0", | ||
"type": "Linux kernel", | ||
"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY=", | ||
"listen_port": 51820, | ||
"num_peers": 13 | ||
} | ||
} | ||
``` | ||
|
||
|
||
### ListPeers | ||
|
||
ListPeers retrieves information about all Peers known to the current WireGuard interface, including allowed IP addresses and usage stats, optionally with pagination. | ||
|
||
```sh | ||
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "ListPeers", "params": {}}' | ||
``` | ||
|
||
#### Example Response | ||
|
||
```json | ||
{ | ||
"peers": [ | ||
{ | ||
"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY=", | ||
"has_preshared_key": false, | ||
"endpoint": "67.234.65.104:57436", | ||
"last_handshake": "2020-02-20T16:35:12Z", | ||
"receive_bytes": 834854756, | ||
"transmit_bytes": 3883746, | ||
"allowed_ips": [ | ||
"10.1.1.0/24" | ||
], | ||
"protocol_version": 1 | ||
}, | ||
... | ||
] | ||
} | ||
``` | ||
|
||
|
||
### GetPeer | ||
|
||
GetPeer retrieves a specific Peer by their public key. | ||
|
||
```sh | ||
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "GetPeer", "params": {"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY="}}' | ||
``` | ||
|
||
#### Example Response | ||
|
||
```json | ||
{ | ||
"peer": { | ||
"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY=", | ||
"has_preshared_key": false, | ||
"endpoint": "67.234.65.104:57436", | ||
"last_handshake": "2020-02-20T16:35:12Z", | ||
"receive_bytes": 834854756, | ||
"transmit_bytes": 3883746, | ||
"allowed_ips": [ | ||
"10.1.1.0/24" | ||
], | ||
"protocol_version": 1 | ||
} | ||
} | ||
``` | ||
|
||
|
||
### AddPeer | ||
|
||
AddPeer inserts a new Peer into the WireGuard interfaces table, multiple calls to AddPeer can be used to update details of the Peer. | ||
|
||
```sh | ||
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "AddPeer", "params": {"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY=","allowed_ips": [ "10.1.1.0/24" ]}}' | ||
``` | ||
|
||
|
||
### RemovePeer | ||
|
||
RemovePeer deletes a Peer from the WireGuard interfaces table by their public key, | ||
|
||
```sh | ||
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "RemovePeer", "params": {"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY="}}' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
// Client is the interface expected to be presented to consumers of the API. | ||
type Client interface { | ||
// GetDeviceInfo returns information such as the public key and type of | ||
// interface for the currently configured device. | ||
GetDeviceInfo(context.Context, *GetDeviceInfoRequest) (*GetDeviceInfoResponse, error) | ||
|
||
// ListPeers retrieves information about all Peers known to the current | ||
// WireGuard interface, including allowed IP addresses and usage stats, | ||
// optionally with pagination. | ||
ListPeers(context.Context, *ListPeersRequest) (*ListPeersResponse, error) | ||
|
||
// GetPeer retrieves a specific Peer by their public key. | ||
GetPeer(context.Context, *GetPeerRequest) (*GetPeerResponse, error) | ||
|
||
// AddPeer inserts a new Peer into the WireGuard interfaces table, multiple | ||
// calls to AddPeer can be used to update details of the Peer. | ||
AddPeer(context.Context, *AddPeerRequest) (*AddPeerResponse, error) | ||
|
||
// RemovePeer deletes a Peer from the WireGuard interfaces table by their | ||
// public key, | ||
RemovePeer(context.Context, *RemovePeerRequest) (*RemovePeerResponse, error) | ||
} | ||
|
||
type Device struct { | ||
Name string `json:"name"` | ||
Type string `json:"type"` | ||
PublicKey string `json:"public_key"` | ||
ListenPort int `json:"listen_port"` | ||
FirewallMark int `json:"firewall_mark,omitempty"` | ||
NumPeers int `json:"num_peers"` | ||
} | ||
|
||
type GetDeviceInfoRequest struct{} | ||
|
||
type GetDeviceInfoResponse struct { | ||
Device *Device `json:"device"` | ||
} | ||
|
||
type Peer struct { | ||
PublicKey string `json:"public_key"` | ||
HasPresharedKey bool `json:"has_preshared_key"` | ||
Endpoint string `json:"endpoint"` | ||
PersistentKeepAlive string `json:"persistent_keep_alive,omitempty"` | ||
LastHandshake time.Time `json:"last_handshake"` | ||
ReceiveBytes int64 `json:"receive_bytes"` | ||
TransmitBytes int64 `json:"transmit_bytes"` | ||
AllowedIPs []string `json:"allowed_ips"` | ||
ProtocolVersion int `json:"protocol_version"` | ||
} | ||
|
||
type ListPeersRequest struct { | ||
Limit int `json:"limit,omitempty"` | ||
Offset int `json:"offset,omitempty"` | ||
} | ||
|
||
type ListPeersResponse struct { | ||
Peers []*Peer `json:"peers"` | ||
} | ||
|
||
type GetPeerRequest struct { | ||
PublicKey string `json:"public_key"` | ||
} | ||
|
||
type GetPeerResponse struct { | ||
Peer *Peer `json:"peer"` | ||
} | ||
|
||
type AddPeerRequest struct { | ||
PublicKey string `json:"public_key"` | ||
PresharedKey string `json:"preshared_key,omitempty"` | ||
Endpoint string `json:"endpoint,omitempty"` | ||
PersistentKeepAlive string `json:"persistent_keep_alive,omitempty"` | ||
AllowedIPs []string `json:"allowed_ips,omitempty"` | ||
|
||
// ValidateOnly ensures only validation is completed, no side effects | ||
ValidateOnly bool `json:"validate_only"` | ||
} | ||
|
||
type AddPeerResponse struct { | ||
// OK will only ever be false if ValidateOnly has been requested. | ||
OK bool `json:"ok"` | ||
} | ||
|
||
type RemovePeerRequest struct { | ||
PublicKey string `json:"public_key"` | ||
|
||
// ValidateOnly ensures only validation is completed, no side effects | ||
ValidateOnly bool `json:"validate_only"` | ||
} | ||
|
||
type RemovePeerResponse struct { | ||
// OK will only ever be false if ValidateOnly has been requested. | ||
OK bool `json:"ok"` | ||
} |
Oops, something went wrong.