Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/script to generate conf files #54

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from

Conversation

Joseph-Drapeau
Copy link
Collaborator

Creating a VPN for Rootski using Wireguard (Phase 1)

This PR explains how the configuration files for the wireguard VPN are created.

Scope

The three phases of this project will include:

  1. Generation of configuration files needed to help build a Lightsail instance as infrastructure as code, which will host the rootski wireguard virtual private network (VPN).
  2. Writing infrastructure as code to deploy the wireguard VPN as a Lightsail instance to AWS.
  3. Distribution of the peer configuration files.

The scope of this PR only covers phase 1.

Server Configuration File

In order to create a VPN, one must write the VPN's server configuration file which depends on a RSA key pair for

  1. the server,
  2. each rootski service (e.g. mlflow.rootski.io, database.rootski.io), and
  3. each rootski contributor.

A wireguard server configuration file has one [Interface] section followed by any number of [Peer] sections.

The interface section needs to know the server's private key while a peer section needs to know the client's public key. We can also assign each peer a specific IP address on the VPN that is unique to them as AllowedIPs in the peer section.

Here is an example of a server configuration file that needs to be on the machine hosting the Wireguard service.

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = GAc+xaQISKysifZ1oRFU6rsbptr/ptjKEhouB74ECNg=
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Username = Eric
PublicKey = vnRKWLMdDIy64+h+dHHvmY6IyM2hhKLXdvJlH74eTRc=
AllowedIPs = 10.0.0.12/32

[Peer]
# Username = Issac
PublicKey = ioypT+0NzR9XjH/OYInaF54n2N3QG6ePyRQNoUw1LnI=
AllowedIPs = 10.0.0.13/32

Peer Configuration File

Then each client needs to create a client configuration file on their machine using their own private key and the server's public key.

Like the server's configuration file, the client configuration file will also include an [Interface] and [Peer] section.

The difference is the client's private key now goes in the [Interface] section while the server's public key is in the [Peer] section.

Here is an example of a peer configuration file using the Wireguard desktop client. Also notice that the peer section has a endpoint which is the VPN's public IP address or DNS name.

Screen Shot 2022-05-01 at 12 49 52 AM

Problem addressed by this PR

The Wireguard VPN is a stateful system that depends on knowledge of several RSA key pairs. The server needs to know each client's public key and each client needs to know the server's public key.

If the server's key pair were to become compromised or lost, then we would need to

  1. generate a new RSA key pair for the Wireguard VPN server
  2. provide each rootski contributor with the new server public key,
  3. have each contributor correctly update their client configuration file, and
  4. generate a new server configuration file, including a copy of every contributor's public key

We wanted to create a solution that preserved the state of the system without having to contact rootski contributors if the system failed. This requires that the key pairs be accessible yet securely stored at the same time.

Solution

Our solution is to store the state of the system (the key pairs) in AWS Parameter Store. This way, we can use infrastructure as code to to create a Lightsail instance and an IAM user with permissions to access Parameter Store. We can then use the parameters to recreate lost configuration files if the Lightsail instance crashes.

We did this by first writing the file wireguard_keygen_utils.py. This file generates the wireguard key pairs and then wraps them in a dataclass with additional information about the associated IP address, key owner, and additional note. Here is an example of the server's VpnKeyPairData

Screen Shot 2022-05-01 at 12 46 18 AM

Notice the note saying this key pair is reserved (for rootski services) and not for contributors. Key pairs meant for rootski contributors will have a note that says "null"

Screen Shot 2022-05-01 at 12 43 24 AM

Did you notice I just exposed Eric's private key?!

Using this key pair data, we wrote another file (store_keys_on_aws.py) to store the key pairs on Parameter store. Observe each key pair almost has the same name except for the ending, which is the assigned ip-address.

Screen Shot 2022-05-01 at 12 47 20 AM

The last file created is generate_server_conf.py file. This file pulls the key pair data from Parameter Store and creates three file:

  1. The server configuration file (wg0.conf)
  2. The file holding the server's private key (server.key)
  3. The file holding the server's public key (server.pub)

generate_server_conf.py will be used in the install_wireguard.sh where it will be concatenated locally on the AWS Lisghtsail instance and run there.

@github-actions
Copy link

github-actions bot commented May 1, 2022

The docs for the most recent build have been published here: https://docs.rootski.io/review/feature/script_to_generate_conf_files. Please verify that they render correctly.

@codecov-commenter
Copy link

Codecov Report

Merging #54 (3fafd5d) into trunk (bc345c2) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##            trunk      #54   +/-   ##
=======================================
  Coverage   73.70%   73.70%           
=======================================
  Files          42       42           
  Lines        1289     1289           
  Branches      183      183           
=======================================
  Hits          950      950           
  Misses        317      317           
  Partials       22       22           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bc345c2...3fafd5d. Read the comment docs.

@Joseph-Drapeau
Copy link
Collaborator Author

I created a diagram to better illustrate how the process will work.

Screen Shot 2022-05-03 at 2 59 29 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants