Coder Social home page Coder Social logo

wg-api's Introduction

WG-API ๐Ÿ”

WG-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: WG-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 WG-API

Pre-Built Binary

Binaries for Linux are available here.

Build Yourself

WG-API requires at least Go 1.17.

go install github.com/jamescun/wg-api

This should install the server binary wg-api in your $GOPATH/bin.

Docker

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

docker run --name=wg-api -d -p 8080:8080 --network host --cap-add NET_ADMIN james/wg-api:latest --device=<my device>

The Docker container now supports Linux on AMD64, ARM64 and ARMv7 architectures.

Configuring WG-API

WG is configured using command line arguments:

$ wg-api --help
WG-API presents a JSON-RPC API to a WireGuard device
Usage: wg-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 WG-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
  --token                 opaque value provided by the client to authenticate
                          requests. may be specified multiple times.

Environment Variables:
  WGAPI_TOKENS  comma seperated list of authentication tokens, equivalent to
                calling --token one or more times.

Warnings:
  WG-API can perform sensitive network operations, as such it should not be
  publicly exposed. It should be bound to the local interface only, or
  failing that, be behind an authenticating proxy or have mTLS enabled.
  Additionally authentication tokens should be configured.

The only required argument is --device, which tells WG-API which WireGuard device to control. To control multiple WireGuard devices, launch multiple instances of WG-API.

By default, this launches WG-API on localhost:8080 which may conflict with the typical development environment. To bind it elsewhere, use --listen:

$ wg-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 WG-API server; such as binding it only to a local interface, enabling auth tokens, placing an authenticating reverse proxy in-front of it or using mTLS (detailed below).

Authentication tokens can be provided either on the command line or via an environment variable. --token may be specified multiple times, or a comma-seperated list may be provided with the WGAPI_TOKENS environment variable. Environment variables are preferred as the token may be visible from process lists when using the command line --token.

$ WGAPI_TOKENS=<random string> wg-api --device=<my device>

Then provided as part of the HTTP exchange in the HTTP Authorization header as the Token scheme.

$ curl http://localhost:8080 -H "Authorization: Token <random string>" ...
POST / HTTP/1.1
Host: localhost:8080
Authorization: Token <random string>
Content-Type: application/json

WG-API can optional listen using TLS and HTTP/2. To enable TLS, you will also need a TLS Certificate and matching private key.

$ wg-api --device=<my device> --tls --tls-key=key.pem --tls-cert=cert.pem

And optionally WG-API can request and validate client certificates to implement TLS Mutual Authentication (mTLS):

$ wg-api --device=<my device> --tls --tls-key=key.pem --tls-cert=cert.pem --tls-client-ca=clientca.pem

Using WG-API

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

Authentication may optionally be configured. This is supplied via the Authorization header as the Token scheme. See Configuring WG-API for an example.

GetDeviceInfo

GetDeviceInfo returns information such as the public key and type of interface for the currently configured device.

curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "GetDeviceInfo", "params": {}}'

Example Response

{
  "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.

curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "ListPeers", "params": {}}'

Example Response

{
  "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.

curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "GetPeer", "params": {"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY="}}'

Example Response

{
  "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.

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,

curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "RemovePeer", "params": {"public_key": "xoY2MZZ1UmbEakFBPyqryHwTaMi6ae4myP+vuILmJUY="}}'

Thanks

With many thanks to:

wg-api's People

Contributors

jamescun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

wg-api's Issues

start on bootup

Hey there!
How does one set this service to start on reboot on Ubuntu 18.04?

Thanks!

Persistence: WireGuad Interface/Peer Configuration

WG-API currently makes no attempt to persist WireGuard configuration between restarts. The restart may be of the wg-api daemon, or of the system itself.

In the case of the wg-api daemon being restarted, all configuration is persisted as the WireGuard interface itself is used as the source of truth. No persistence nessecary.

In the case of the system restarting, the system may not be configured with wg-quick to load configuration on startup, and thus wg-api will see an empty state. No attempt is made to store configuration changes made by wg-api on termination, this must be done seperately.

WG-API should have a mechanism to snapshot and restore WireGuard's interface/peer configuration, perferably in a format that is compatible with wg-quick.

Authentication: Tokens

Configuring a reverse proxy to apply authentication, or issuing client certificates, is laborious. It hampers the initial setup flow in environments that already have other means of authentication.

It should be possible to configure one or more static tokens, which the client is expected to provide through some out-of-band means, that allows the request to continue.

These tokens would likely be provided on startup by passing one or more --token command line arguments. As other processes may be able to inspect the command, it might be wise to also support environment variables for this process, perhaps a comma seperated list in WGAPI_TOKEN.

As for providing the token, HTTP headers are convenient and many JSON-RPC clients support this explicitely for authentication. A decision must be made to what header and format is used, for example:

  • Authorization: Token <token>
  • Authorization: Basic base64(<token>:)
  • Wgapi-Token: <token>

This should be decided based on the ease of configuration in popular JSON-RPC clients.

adding peer without restart ?

Hi
if i have thousand users and i make config for each of them on the fly may this cause interruption of other users ? (since creating and inserting each peer should restart the service to make user be able to connect successfully with that newly created config)

Authentication: UNIX Sockets

Configuring a reverse proxy to apply authentication, or issuing client certificates, is laborious. It hampers the initial setup flow in environments that already have other means of authentication.

It should be possible to configure the server to listen on a UNIX socket rather than a network interface.

This is widely supported by the Go standard library, and has the added advantage of using the systems existing file permissioning system.

This would likely be configured by passing a filename to --listen instead of a host:port combination.

A decision must be made as to what permissions are initially assigned to the socket. My working idea as this would be the same user/group as the process and 0660 to allow only the process user/group access to the socket. There must be a command line flag to configure this, otherwise any change to permissions will not be persisted across restarts.

add access token authentication

placing an authenticating reverse proxy or using mTLS is annoying
the json-rpc request object has an id member, can we use this parameter to pass the authentication token?
the server:
wg-api --device=<my device> --listen=localhost:1234 --token=abcdef
then the request:
curl http://localhost:8080 -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "GetDeviceInfo", "params": {}, "id":"abcdef"}'
The server performs Token authentication on each request from the client. If it does not match, it just returns an error and without performing any operation.

the argument --token is optional

Can this run with WG in Docker?

Hi,

I would like to use all my application only using Docker, so I have set up WireGuard to run in Docker as well, using the Linuxserver image.

Now I also have spun up wg-api in Docker but have some trouble getting this running proably because wg-api cannot get info from WireGuard in the other container. Is that something that can be solved or is this not a configuration that is possible?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.