Sign inSign up

binlab/bifrost-api

By binlab

Updated about 6 years ago

Self Hosted OpenVPN Service with Google OAuth Support (API Server)

Image
0

424

binlab/bifrost-api repository overview

Self hosted OpenVPN Server with Google OAuth2 support

Bifröst is a multi-component implementation of convenient Web UI for control of the OpenVPN server. A Bifröst is written on GoLang and Vue.js and consists of Web UI service, API service, and of course OpenVPN server. For authentication it uses Google OAuth2 implementation as an SSO, so for a using you need a corporate G-Suit or at list a personal Gmail account. By the way, it can works with any combinations of G-Suite for different domains (one or more domains) and support manually added emails accounts for an external employee outside the organization domain.

Bifröst originally has been developed by Playground Global, LLC, and then distributed by @morrildl as an open-source by Apache License. Special thanks for this! Original distributions you can find here and archived mirror here

Why?

Original implementation works fine and can be deployed by instruction with almost no problem. But it has a lack of flexibility in a modern environment. For example, it can't be deployed by Docker, and Kubernetes/Docker Swarm as well. It asking a specific version of the operating system on VPS instance and can't be easily ported to another one. Also, not possible to scale.

But the biggest motivation was in another disadvantage - TOTP authentication. Mostly the benefits are obvious generally it very secure but day-to-day usage causes a lot of inconvenience. You can't save a password on a client and must enter each time when you connect. If your phone was locked, network reconnects etc.

So it was decided to return to a less secure method but a more convenient way of authentication - static passwords. It can be generated by the backend (so, length and type can be securely predefined) and also might be regenerated, so you don't have to a store or remember it. Technically it the same as the generation of TOTP seed. And of course, the original method by TOTP authentication also left for usage. The administrator can choose a preferred method in settings.

Below is a list of differences from the original version and new features:

  • Added support for Static Passwords on parallel to TOTP authentication (implemented in Web UI and API)
  • Updated all Golang dependencies and add go.mod
  • Were a favicon and logo change to OpenVPN logo
  • Changed behavior for redirecting from HTTP to HTTPS. Can be provided a full URL
  • Added Logout endpoint /logout to API and support on main SPA page as a button
  • Added Logout endpoint /logout and Reload endpoint / on error modal window (easiest way to logout if was selected wrong G-Suit/Gmail account)
  • Added Google account prompt selections - it ALWAYS will be present even you have just one account logged in. More predictable behavior when you select needed account
  • Migration all OpenVPN user scripts to Python3
  • Reworked structure and names in the SQLite database, and added new columns
  • Added separate Dockerfiles for each service (bifrost-ui, bifrost-api, bifrost-ovpn). See Docker folder
  • Running an API and Web UI as non-privileged users (bifrost with a UID/GID 1024:1024)
  • Move application logs to /dev/stdout. For stateless and cloud-native container
  • Added outputting some debugging information in time to launch an application DEBUG="true". It is recommended to disable it on production
  • Added support for configuring bifrost-ui, bifrost-api and bifrost-vpn services by environment variables in Docker in time of launch
  • Added Terraform module for deploy Bifrost OpenVPN in AWS

Overview

This project consists of 3 key components:

  • Bifröst Web UI service (bifrost-ui)
  • Bifröst API service (bifrost-api)
  • OpenVPN service (bifrost-ovpn)
Bifröst Web UI Service

The Bifröst web UI is where policy enforcement happens. This project is intended for use by a relatively small number of total users, perhaps up to a couple hundred. The UI is intended to be generally self-service.

Users can create and revoke certificates, up to a limit on a number of extant certificates set by the administrator. For instance, the admin can set the limit to 1, allowing for only one machine at a time, intended to be a laptop. Or, the admin can set the limit to 3, perhaps allowing for a laptop, desktop, and tablet. If a user is at the limit, they must revoke a certificate to create a new one.

The administrator can opt to either have a manual whitelist of users or allow unrestricted access to a particular domain via Google's OAuth2. In both cases, the certificate limits are enforced.

Bifröst API Service

Bifröst API is an server to front the SQLite3 database. The client authentication runtime scripts use the database to read certificate status (i.e. for validity and revocations) and write logs to it. The API server provides REST endpoints to manage certificates -- create users, reset TOTP seeds/Static password, issue and revoke certificates, etc.

The Bifröst Web UI is simply a front-end to Bifröst API. A command-line front-end is also provided, but generally, it's expected that most operations will be done via the Bifröst Web UI.

Bifröst API authenticates its client via certificate pinning. The intention is that the Bifröst API process itself runs on the OpenVPN server, where the SQLite3 database is located. The Bifröst Web UI can be run anywhere, using Bifröst API as its back-end.

The simple configuration Bifröst API and Bifröst Web UI running on the same machine. This is also fine, though with a reduced security posture; but the two were built separately to make it straightforward to split the two if desired.

OpenVPN Service

OpenVPN is, of course, doing all the heavy lifting. This project is essentially a constellation of tools to help deploy an OpenVPN with a decently secure configuration, with decent usability.

The key moving pieces are:

  • a SQLite3 database with a simple schema tracking certificate validity, and audit logs
  • ovpn-tls-verify.py - a script for OpenVPN's tls-verify hook that handles certificate validity and revocations via the database
  • ovpn-auth-user-pass-verify.py - a script for the auth-user-pass-verify hook that implements TOTP authentication or Static passwords. In case of TOTP authentication suitable for use FreeOTP with open-source https://freeotp.github.io or Google Authenticator
  • ovpn-client-logger.py - a script for the client-connect and client-disconnect hooks that logs usage by IP
Security Posture

Originally Bifröst has been developed for the high-grade level of security. Which nudged to take it as a basis since it was attracted by the architectural implementation. Next are original concepts of security which are also kept in the current implementation.

The model is multi-factor authentication with a minimum of integration or overhead, in particular avoiding dependencies on other systems, especially password databases.

Essentially this is three-factor authentication. To access the VPN you must have:

  1. The client certificate on the device (i.e. laptop) wanting to use VPN (ideally stored in a hardware TPM, but beyond the scope of this project)
  2. The device (i.e. phone) where the TOTP app is installed
  3. The OS passwords/lock codes to those devices

That is, if an attacker wants to get onto the VPN, he must steal your phone, and your laptop, and know your screensaver password and your phone unlock code.

Naturally the actual security of this model depends on the OS and user behavior, so sensible policies must also be used. Specifically, the device used for TOTP must not itself have a VPN client certificate (because then you lose a factor). And of course suitable OS-level screen locks must be used.

Note that this implementation (currently) does not use the OpenVPN administrative runtime hooks to disconnect a device with an extant connection, if that device's cert is revoked. Since the expectation is that the web UI runs behind the VPN, and not necessarily on the public internet, VPN access is required to refresh device certificates. Thus we cannot revoke clients immediately via OpenVPN admin hooks: it would kick users off instantly as soon as they click the disconnect button but before they can generate a new certificate for their device. Certainly a dedicated "re-up this device" UI flow for this case is possible, but it would be more complicated, and the current UI is specifically intended to be dirt simple. All of which is to say, this is a conscious usability vs. security tradeoff.

Configuration

Each service can be configured individually by environment variables, below list for each of them

Bifröst Web UI Service (bifrost-ui)
NameDescriptionDefaultRequired
DEBUGAllow enabling debugging information from application and Docker to stdoutfalseno
UI_HTTP_PORTWeb UI HTTP port for listening by web server. Must be greater than 1024 as application run from unprivileged user8080no
UI_HTTPS_PORTWeb UI HTTPS port for listening by web server. Must be greater than 1024 as application run from unprivileged user8443no
UI_SERVER_URLWeb UI server endpoint URL with https support, used for redirecting from http connection. It can be different from main domain/IP address when Web UI hidden behind reverse proxy. It should be next format: https://vpn.company.tld or https://vpn.company.tld:8443yes
UI_SERVER_CERT_FILEPath to Web UI server certificate mounted by Docker Volume/usr/local/etc/ui-server.certno
UI_SERVER_KEY_FILEPath to Web UI server certificate key mounted by Docker Volume/usr/local/etc/ui-server.keyno
API_CLIENT_CERT_FILEPath to Web UI client certificate mounted by Docker Volume. Used for authentication connections between API server/usr/local/etc/api-client.certno
API_CLIENT_KEY_FILEPath to Web UI client certificate key mounted by Docker Volume. Used for authentication connections between API server/usr/local/etc/api-client.keyno
API_SERVER_CERT_FILEPath to API server certificate mounted by Docker Volume. Used for authentication connections from API server/usr/local/etc/api-server.cert no
API_SERVER_URLAPI server endpoint URL where API server running. It can be different instance or location and internal domain/hostname either. It should be next format: https://bifrost-api.company.tld or https://bifrost-api.company.tld:9443https://bifrost-api:9443no
OAUTH_CLIENT_IDOAuth2 Client ID form SSO provideryes
OAUTH_CLIENT_SECRETOAuth2 Client Secret form SSO provideryes
OAUTH_REDIRECT_PREFIXOAuth2 redirect prefix. Your public endpoint URL where listening Web UI with HTTPS support. It should be next format: https://vpn.company.tld or https://vpn.company.tld:8443yes
ADMIN_USERS_LISTComma separated list of e-mails of user who will be recognized by Bifrost Web UI as an Administrative user. It should be in next format: "[email protected],[email protected],[email protected]". E-mail addresses can be either from the company's domain G-Suit or private Gmail or even from different G-Suit domainyes
Bifröst API Service (bifrost-api)
NameDescriptionDefaultRequired
DEBUGAllow enabling debugging information from application and Docker to stdoutfalseno
CA_CERT_FILEPath to Root Certificate Authority - certificate file mounted by Docker Volume. It should by a certificate which have used for signing OpenVPN server certificate and API server and client/usr/local/etc/ca.certno
CA_KEY_FILEPath to Root Certificate Authority - certificate key file mounted by Docker Volume. It should by a certificate which have used for signing OpenVPN server certificate and API server and clien/usr/local/etc/ca.keyno
API_SERVER_CERT_FILEPath to API server certificate mounted by Docker Volume/usr/local/etc/api-server.certno
API_SERVER_KEY_FILEPath to API server certificate key mounted by Docker Volume/usr/local/etc/api-server.keyno
API_CLIENT_CERT_FILEPath to Web UI client certificate mounted by Docker Volume. Used for authentication connections from Web UI client/usr/local/etc/api-client.certno
API_HTTPS_PORTAPI HTTPS port for listening by web server. Must be greater than 1024 as application run from unprivileged user9443no
OVPN_TLS_AUTH_FILEPath to OpenVPN Static Key file mounted by Docker Volume/usr/local/etc/ovpn-tls-auth.pemno
OVPN_CLIENT_TMPL_FILEOptional environment to define and replace a standard OpenVPN Client config template/usr/local/etc/client.ovpnno
OVPN_SERVER_PORTOpenVPN server port where Bifrost OVPN listening a connections. The official OpenVPN port number is 11941194no
OVPN_SERVER_PROTOOpenVPN server protocol where Bifrost OVPN listening a connections. Try to avoid a changing this parameter to prevent loss of performance and speed. More: http://sites.inka.de/bigred/devel/tcp-tcp.htmludpno
OVPN_SERVER_HOSTOpenVPN server hostname or IP where Bifrost OVPN listening a connectionsyes
SQLITE_DB_FILEOptional environment for redefine a standard path of SQLite database/var/local/bifrost/bifrost.sqlite3no
OpenVPN Service (bifrost-ovpn)
NameDescriptionDefaultRequired
DEBUGAllow enabling debugging information from application and Docker to stdoutfalseno
CA_CERT_FILEPath to Root Certificate Authority - certificate file mounted by Docker Volume. It should by a certificate which have used for signing OpenVPN server certificate/usr/local/etc/ca.certno
OVPN_SERVER_CERT_FILEPath to OpenVPN server certificate mounted by Docker Volume/usr/local/etc/ovpn-server.certno
OVPN_SERVER_KEY_FILEPath to OpenVPN server certificate key mounted by Docker Volume/usr/local/etc/ovpn-server.keyno
OVPN_SERVER_PORTOpenVPN server port where Bifrost OVPN listening a connections. The official OpenVPN port number is 11941194no
OVPN_SERVER_PROTOOpenVPN server protocol where Bifrost OVPN listening a connections. Try to avoid a changing this parameter to prevent loss of performance and speed. More: http://sites.inka.de/bigred/devel/tcp-tcp.htmludp4no
OVPN_DH_KEY_FILEPath to OpenVPN Static Key file mounted by Docker Volume/usr/local/etc/ovpn-dh-key.pemno
OVPN_TLS_AUTH_FILEPath to Diffie–Hellman parameters file mounted by Docker Volume/usr/local/etc/ovpn-tls-auth.pemno
SQLITE_DB_FILEOptional environment for redefine a standard path of SQLite database/var/local/bifrost/bifrost.sqlite3no

Build

For building each component run next command. You need to have a Docker installed already

  • Bifröst Web UI Server

    docker build --tag bifrost-ui -f docker/bifrost-ui/Dockerfile .
    
  • Bifröst API Server

    docker build --tag bifrost-api -f docker/bifrost-api/Dockerfile .
    
  • OpenVPN Server

    docker build --tag bifrost-ovpn -f docker/bifrost-ovpn/Dockerfile .
    

Download

You can pull already build Docker images. Which are automatically building from source code in the repository

Tag summary

Content type

Image

Digest

Size

11.6 MB

Last updated

about 6 years ago

docker pull binlab/bifrost-api