Connect to AWS VPN from i3

Here's how to connect to the AWS VPN from i3, or other non-desktop Linux environments.

The Problem

AWS has a VPN client for connecting to AWS VPNs. And they have a build for Linux. ...Good. But it can only be run from a desktop environment, like Gnome. What's an i3 user to do?

One option: Patch a version of an OpenVPN client. Use a great little project with a script that'll associate an AWS VPN response to that client.

Patch OpenVPN Client

To prep for building the VPN client and then running our later script, you'll need some tools:

sudo apt install libssl-dev liblzo2-dev libpam0g-dev liblz4-dev dnsutils

Choose a compatible version of openvpn. The samm-git/aws-vpn-client repo has patches for 2.4.9 and 2.5.1. But I have also successfully used 2.5.5. And I've heard of someone using this patch in in the 2.6.x range.

Download and extract the openvpn source:

curl -O https://swupdate.openvpn.org/community/releases/openvpn-2.5.5.tar.gz
tar xvf openvpn-2.5.5.tar.gz

Clone the samm-git/aws-vpn-client repo:

git clone git@github.com:samm-git/aws-vpn-client.git

Now apply the patch:

# assuming openvpn dir at: ~/Downloads/openvpn-2.5.5
# assuming samm-git dir at: ~/dev/aws-vpn-client

cd ~/Downloads/openvpn-2.5.5
patch -p1 < ~/dev/aws-vpn-client/openvpn-v2.5.1-aws.patch && autoreconf -ivf && ./configure && make

(For the above, see also samm-git/aws-vpn-client#3.)

And move the patched version of openvpn to the aws-vpn-client directory:

cp openvpn ~/Downloads/aws-vpn-client

Get VPN Endpoint Config

Your particular AWS VPN endpoint will require a specific configuration. This is usually provided as an .ovpn file. As an option for acquiring this file, AWS provides a self-service portal.

First log into AWS. By default, that's at https://self-service.clientvpn.amazonaws.com/endpoints. You may need your administrator to provide you with the specific endpoint ID, which you can enter at the URL above. Sometimes they'll give you a URL with the endpoint ID built in.

Once you have access to the self-service portal for your endpoint, download the cvpn-endpoint-[id].ovpn file.

Modify the Script and Config

samm-git/aws-vpn-client provides the key script for connecting to the vpn. You'll need to update some values:

cd ~/Downloads/aws-vpn-client
nvim aws-connect.sh

# edit:
# - VPN_HOST - update the `[id]` portion, using id from the `cvpn-endpoint-[id].ovpn` file
# - PORT - update, as needed, to port 443 for HTTPS

And in the config:

nvim vpn.conf

# edit:
# - `<ca>` section - copy over the `<ca>` section from the `cvpn-endpoint-[id].ovpn` file

Also note that this vpn.conf file doesn't have the non-openvpn-standard headers that Amazon uses, such as auth-user-pass or auth-federate.

Listen for a SAML Response

In the next step, when we run the connect script, it'll make a request to AWS for a connection on the VPN. This will produce a response, and we need to have a process to accept it, running at localhost:35001, per the aws-connect.sh script.

The included server is written in Go. Install Go (Use asdf, which is great for this).

Then run the server:

cd ~/Downloads/aws-vpn-client
go run server.go

Run the Script

In a separate terminal, run the connect script:

cd ~/Downloads/aws-vpn-client
./aws-connect.sh

Be prepared to enter your local superuser password to help the script complete.

You'll know it worked when you see the browser say it got a SAML response, that you can close it, and your aws-connect.sh terminal has some output like this:

2024-03-13 10:13:59 [vpn.mydomain.com] Peer Connection Initiated with [AF_INET]54.130.227.72:443
...
2024-03-13 10:14:00 TUN/TAP device tun0 opened
...
2024-03-13 10:14:00 Initialization Sequence Completed

You should now be able to access VPN-only resources! And in i3. Happy day!

Optional: Troubleshoot the Script Run

Initially, I ran the script like this:

sh aws-connect.sh

And I got this error:

Getting SAML redirect URL from the AUTH_FAILED response (host: 35.183.98.133:443)
aws-connect.sh: 33: Syntax error: "(" unexpected

A friendly Daniel pointed out that when running scripts with sh, it runs them as POSIX scripts and ignores the #!/bin/bash directive. But this script uses bash, so run it like this to make it happy with the script syntax:

chmod +x aws-connect.sh
./aws-connect.sh

A small, separate bash tip: If you want to see more of what the script is doing, add this line to the top of the script to print out all commands for visibility:

set -x

Optional: Troubleshoot DNS

After I successfully connected to the VPN, I couldn't resolve DNS. I still can't. I'm dealing with some workarounds at them moment, eager to make them better. Here's what's working best so far:

Find the VPN network name with:

ifconfig

Mine's tun0. Then set the DNS server for that network:

resolvectl dns tun0 10.100.0.2

Now lookup the IP of your favorite VPN-only resource:

dig some-name.com @10.100.0.2

In the ANSWER section, there'll be something like this:

some-name.com.		21	IN	A	10.210.23.28

Now modify your /etc/hosts file to set your own DNS entry:

sudo $(which nvim) /etc/hosts

10.210.23.285   some-name.com

Now you should be able to browser to some-name.com and have it resolve. Yay!

Other things that did not work so far:

  1. Trying to specify the DNS server for the connection:

cd ~/Downloads/aws-vpn-client

nvim vpn.conf
# add:
dhcp-option DNS 10.100.0.2
  1. Trying to find the DNS server:

netstat -netp
  1. diging without the DNS server:

dig some-name.com

If anyone has hot tips on getting DNS to work in this VPN environment, please send them my way.