Self Hosted OpenVPN Service with Google OAuth Support (API Server)
424
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
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:
Static Passwords on parallel to TOTP authentication (implemented in Web UI and API)go.mod/logout to API and support on main SPA page as a button/logout and Reload endpoint / on error modal window (easiest way to logout if was selected wrong G-Suit/Gmail account)bifrost-ui, bifrost-api, bifrost-ovpn). See Docker folderbifrost with a UID/GID 1024:1024)/dev/stdout. For stateless and cloud-native containerDEBUG="true". It is recommended to disable it on productionbifrost-ui, bifrost-api and bifrost-vpn services by environment variables in Docker in time of launchThis project consists of 3 key components:
(bifrost-ui)bifrost-api)bifrost-ovpn)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 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 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:
ovpn-tls-verify.py - a script for OpenVPN's tls-verify hook that handles certificate validity and revocations via the databaseovpn-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 Authenticatorovpn-client-logger.py - a script for the client-connect and client-disconnect hooks that logs usage by IPOriginally 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:
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.
Each service can be configured individually by environment variables, below list for each of them
bifrost-ui)| Name | Description | Default | Required |
|---|---|---|---|
DEBUG | Allow enabling debugging information from application and Docker to stdout | false | no |
UI_HTTP_PORT | Web UI HTTP port for listening by web server. Must be greater than 1024 as application run from unprivileged user | 8080 | no |
UI_HTTPS_PORT | Web UI HTTPS port for listening by web server. Must be greater than 1024 as application run from unprivileged user | 8443 | no |
UI_SERVER_URL | Web 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:8443 | yes | |
UI_SERVER_CERT_FILE | Path to Web UI server certificate mounted by Docker Volume | /usr/local/etc/ui-server.cert | no |
UI_SERVER_KEY_FILE | Path to Web UI server certificate key mounted by Docker Volume | /usr/local/etc/ui-server.key | no |
API_CLIENT_CERT_FILE | Path to Web UI client certificate mounted by Docker Volume. Used for authentication connections between API server | /usr/local/etc/api-client.cert | no |
API_CLIENT_KEY_FILE | Path to Web UI client certificate key mounted by Docker Volume. Used for authentication connections between API server | /usr/local/etc/api-client.key | no |
API_SERVER_CERT_FILE | Path to API server certificate mounted by Docker Volume. Used for authentication connections from API server | /usr/local/etc/api-server.cert | no |
API_SERVER_URL | API 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:9443 | https://bifrost-api:9443 | no |
OAUTH_CLIENT_ID | OAuth2 Client ID form SSO provider | yes | |
OAUTH_CLIENT_SECRET | OAuth2 Client Secret form SSO provider | yes | |
OAUTH_REDIRECT_PREFIX | OAuth2 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:8443 | yes | |
ADMIN_USERS_LIST | Comma 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 domain | yes |
bifrost-api)| Name | Description | Default | Required |
|---|---|---|---|
DEBUG | Allow enabling debugging information from application and Docker to stdout | false | no |
CA_CERT_FILE | Path 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.cert | no |
CA_KEY_FILE | Path 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.key | no |
API_SERVER_CERT_FILE | Path to API server certificate mounted by Docker Volume | /usr/local/etc/api-server.cert | no |
API_SERVER_KEY_FILE | Path to API server certificate key mounted by Docker Volume | /usr/local/etc/api-server.key | no |
API_CLIENT_CERT_FILE | Path to Web UI client certificate mounted by Docker Volume. Used for authentication connections from Web UI client | /usr/local/etc/api-client.cert | no |
API_HTTPS_PORT | API HTTPS port for listening by web server. Must be greater than 1024 as application run from unprivileged user | 9443 | no |
OVPN_TLS_AUTH_FILE | Path to OpenVPN Static Key file mounted by Docker Volume | /usr/local/etc/ovpn-tls-auth.pem | no |
OVPN_CLIENT_TMPL_FILE | Optional environment to define and replace a standard OpenVPN Client config template | /usr/local/etc/client.ovpn | no |
OVPN_SERVER_PORT | OpenVPN server port where Bifrost OVPN listening a connections. The official OpenVPN port number is 1194 | 1194 | no |
OVPN_SERVER_PROTO | OpenVPN 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.html | udp | no |
OVPN_SERVER_HOST | OpenVPN server hostname or IP where Bifrost OVPN listening a connections | yes | |
SQLITE_DB_FILE | Optional environment for redefine a standard path of SQLite database | /var/local/bifrost/bifrost.sqlite3 | no |
bifrost-ovpn)| Name | Description | Default | Required |
|---|---|---|---|
DEBUG | Allow enabling debugging information from application and Docker to stdout | false | no |
CA_CERT_FILE | Path 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.cert | no |
OVPN_SERVER_CERT_FILE | Path to OpenVPN server certificate mounted by Docker Volume | /usr/local/etc/ovpn-server.cert | no |
OVPN_SERVER_KEY_FILE | Path to OpenVPN server certificate key mounted by Docker Volume | /usr/local/etc/ovpn-server.key | no |
OVPN_SERVER_PORT | OpenVPN server port where Bifrost OVPN listening a connections. The official OpenVPN port number is 1194 | 1194 | no |
OVPN_SERVER_PROTO | OpenVPN 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.html | udp4 | no |
OVPN_DH_KEY_FILE | Path to OpenVPN Static Key file mounted by Docker Volume | /usr/local/etc/ovpn-dh-key.pem | no |
OVPN_TLS_AUTH_FILE | Path to Diffie–Hellman parameters file mounted by Docker Volume | /usr/local/etc/ovpn-tls-auth.pem | no |
SQLITE_DB_FILE | Optional environment for redefine a standard path of SQLite database | /var/local/bifrost/bifrost.sqlite3 | no |
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 .
You can pull already build Docker images. Which are automatically building from source code in the repository
docker pull binlab/bifrost-ui:latest
docker pull binlab/bifrost-api:latest
docker pull binlab/bifrost-ovpn:latest
Content type
Image
Digest
Size
11.6 MB
Last updated
about 6 years ago
docker pull binlab/bifrost-api