goSecure is an easy to use and portable Virtual Private Network (VPN) solution.
The system consists of a single server and one or many clients.
strongSwan is used to establish an IPsec tunnel with
pre-shared keys between the server and client(s).
The server component is a multi-homed [laptop/server/cloud instance/Raspberry Pi] that runs strongSwan.
The client component is a Raspberry Pi that runs strongSwan utilizing its hardware Random
Number Generator (RNG). It runs a web application for controlling the VPN client from a computer
behind that client.
The client currently supports 3 modes of operation:
This network diagram illustrates how these components relate to each other:
The original goSecure implementation
was intended for use by federal
government entities who have access to non-public software and documentation
(e.g., a minimal Linux instance, hardened per DISA
Security Technical
Implementation Guides (STIGs), following the NSA
Commercial
Solutions for Classified (CSfC) guidelines.)
This fork of goSecure
uses publicly available operating systems and configurations following
open source security guidance and practices. It has also been ported to
Python 3 and current Python modules, enhanced to integrate the
python_secrets
program, and this documentation updated. The effort to do this
was supported in part by a grant from the Comcast Innovation Fund.
From the ~/git/goSecure directory, perform the following steps.
Start by creating an environment to store the configuration variables and secrets needed to configure the client and server components of the system.
$ psec environments create --clone-from secrets/ new password variable "gosecure_pi_password" is not defined new password variable "gosecure_app_password" is not defined new string variable "gosecure_client_psk" is not defined new string variable "gosecure_client_ssid" is not defined new string variable "gosecure_pi_pubkey" is not defined new string variable "gosecure_pi_locale" is not defined new string variable "gosecure_pi_timezone" is not defined new string variable "gosecure_pi_wifi_country" is not defined new string variable "gosecure_pi_keyboard_model" is not defined new string variable "gosecure_pi_keyboard_layout" is not defined new string variable "gosecure_vpn_client_id" is not defined new string variable "gosecure_vpn_client_psk" is not defined environment "goSecure" (/Users/dittrich/.secrets/goSecure) created
Initially, none of the variables and/or secrets are set.
$ psec secrets show --no-redact +-----------------------------+-----------+-------+ | Variable | Type | Value | +-----------------------------+-----------+-------+ | gosecure_app_password | password | None | | gosecure_client_psk | string | None | | gosecure_client_ssid | string | None | | gosecure_pi_password | password | None | | gosecure_pi_pubkey | string | None | | gosecure_pi_timezone | string | None | | gosecure_pi_wifi_country | string | None | | gosecure_pi_keyboard_model | string | None | | gosecure_pi_keyboard_layout | string | None | | gosecure_vpn_client_id | string | None | | gosecure_vpn_client_psk | token_hex | None | +-----------------------------+-----------+-------+
Since default passwords are being avoided, generate the secrets that will be needed to configure the client and server components of for the VPN.
$ psec secrets generate $ psec secrets show --no-redact +-----------------------------+-----------+----------------------------------+ | Variable | Type | Value | +-----------------------------+-----------+----------------------------------+ | gosecure_app_password | password | brunt outclass alike turbine | | gosecure_client_psk | string | None | | gosecure_client_ssid | string | None | | gosecure_pi_password | password | brunt outclass alike turbine | | gosecure_pi_pubkey | string | None | | gosecure_pi_timezone | string | None | | gosecure_pi_wifi_country | string | None | | gosecure_pi_keyboard_model | string | None | | gosecure_pi_keyboard_layout | string | None | | gosecure_vpn_client_id | string | None | | gosecure_vpn_client_psk | token_hex | dda23bbdfc922622888a7f6e9549f10e | +-----------------------------+-----------+----------------------------------+
Note that the string variables were not automatically generated. These are external pieces of information necessary for accessing external devices (e.g., for internet access using WiFi tethering) or are previously generated secrets (e.g., the SSH key you wish to use for granting access to the goSecure Raspberry Pi client pi account.) These can be set manually like this:
$ psec secrets set gosecure_pi_pubkey=@~/.ssh/new_rsa.pub $ psec secrets set gosecure_client_psk="atjhK5AlsQMw3Zh" gosecure_client_ssid="YourWiFiSSID" \ > gosecure_pi_timezone="America/Los_Angeles" gosecure_pi_wifi_country="US" \ > gosecure_pi_keyboard_model="pc105" gosecure_pi_keyboard_layout="us" \ > gosecure_vpn_client_id="dave.dittrich@gmail.com"
If you prefer to be prompted for each variable, do so this way.
$ psec -q secrets set --undefined Pre-shared key for goSecure client WiFi AP? [None]: atjhK5AlsQMw3Zh SSID for goSecure client WiFi AP? [None]: YourWiFiSSID SSH public key for accessing "pi" account? [None]: @~/.ssh/new_rsa.pub Locale (e.g., "en_US.UTF-8")? [None]: en_US.UTF-8 Timezone (e.g., "America/Los_Angeles")? [None]: America/Los_Angeles Default VPN client ID? [None]: dave.dittrich@gmail.com WiFi country code (e.g., "US")? [None]: US Keyboard model (e.g., "pc105")? [None]: pc105 Keyboard layout (e.g., "us")? [None]: us
You may see the values this way:
$ psec secrets show --no-redact --fit-width +-----------------------------+-----------+------------------------------------------------------------------------------------------+ | Variable | Type | Value | +-----------------------------+-----------+------------------------------------------------------------------------------------------+ | gosecure_app_password | password | brunt outclass alike turbine | | gosecure_client_psk | string | atjhK5AlsQMw3Zh | | gosecure_client_ssid | string | YourWiFiSSID | | gosecure_pi_password | password | brunt outclass alike turbine | | gosecure_pi_pubkey | string | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+qUIucrPvRkTmY0tgxr9ac/VtBUHhYHfOdDVpU99AcryLMWiU | | | | uQ2/NVikfOfPo5mt9YTQyqRbeBzKlNgbHnsxh0AZatjhK5AlsQMw3ZhZUcLYZbt7szuQy8ineN0potlCJoVaMSOb | | | | 9htf9gAPvzwxUnHxg35jPCzAXYAi3Erc6y338+CL0XxQvCogXOA+MwH7wZGgdT3WpupLG/7HAr/3KJEQQk1FlS2m | | | | Rd+WuewnLbKkqBP21N+48ccq6XhEhAmlzzr9SENw5DMmrvMAYIYkoTwUeD3Qx4YebjFkCxZw+w7AafEFn0Kz6vCX | | | | 4mp/6ZF/Ko+o04HM2sVr6wtCu2dB dittrich@localhost | | gosecure_pi_timezone | string | America/Los_Angeles | | gosecure_pi_wifi_country | string | US | | gosecure_pi_keyboard_model | string | pc105 | | gosecure_pi_keyboard_layout | string | us | | gosecure_vpn_client_id | string | dave.dittrich@gmail.com | | gosecure_vpn_client_psk | token_hex | dda23bbdfc922622888a7f6e9549f10e | +-----------------------------+-----------+------------------------------------------------------------------------------------------+
This last command will remind you of the generated passwords if necessary. Generate new secrets whenever you want to start over (e.g., after returning from a trip where your hardware may have been accessed and its contents copied while outside of your posession). Having a "break-glass" procedure for refreshing access control authenticators in an emergency is wise.
Now that all the variables and secrets have been generated and/or set, you are ready to begin configuring the client and server components of the goSecure VPN. There is a helper Makefile that allows you to use the Unix command make to perform multiple complex steps using simple targets specified as arguments to the make command. You can get help on the targets available using the following command:
$ make help usage: make target [...] TARGETS: cloud-configs - generate cloud-config files from template "cloud-config.j2" client-sd - create SD card for goSecure client server-sd - create SD card for goSecure server clean - delete temporary files hypriot-img - download hypriotos-rpi-v1.9.0.img.zip file, check SHA256 sum, unzip DEVELOPMENT/DEBUGGING TARGETS: variables - show variables debug-server - copies current code to server and restarts service To generate new secrets, run "psec secrets generate" To set undefined string secrets, run "psec secrets set --undefined"
The SD cards for both the client and the server have shared information, use the same passwords, etc. The default password is replaced by the one generated earlier and will be different than any other deployment. This is done using the Jinja template engine. Raspberry Pi deployments use the HypriotOS Raspbian derivative that includes cloud-init for boot-time customization using cloud-config files. Generate the templates to be used for the client and sever:
$ make cloud-configs psec template cloud-config.client.j2 /Users/dittrich/.secrets/goSecure/tmp/cloud-config.client psec template cloud-config.server.j2 /Users/dittrich/.secrets/goSecure/tmp/cloud-config.server
Note: The server component build instructions are an example that can be used by affiliates that desire a complete solution, but the client component can interoperate with any VPN server that can be configured using the NSA CSFC guidelines.
When the Raspberry Pi first boots, it will execute the commands defined in the cloud-config.server.j2 These initial steps including firmware updating and downloading of the gosecure_server_install_pi.py script. Be patient. Depending on your network speed, this can take a long time.
Note: you now have the option to SSH into the goSecure client through eth1 (the USB to Ethernet adapter).
Log in to the pi account using the password you generated in Step 0.
# interfaces(5) file used by ifup(8) and ifdown(8) # Please note that this file is written to be used with dhcpcd # For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf' # Include files from /etc/network/interfaces.d: source-directory /etc/network/interfaces.d auto lo iface lo inet loopback auto eth0 allow-hotplug eth0 iface eth0 inet dhcp auto eth1 allow-hotplug eth1 iface eth1 inet static address 192.168.166.1 netmask 255.255.255.0 allow-hotplug wlan0 iface wlan0 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
Wait 30 seconds for eth0 to obtain an IP Address.
Note: you now have the option to SSH into the goSecure client through eth1 (the USB to Ethernet adapter). Copying and pasting the commands and configuration files is recommended. Be sure to change variables where specified.
Note: These commands will run for a long time.
Note: replace the 2 arguments in the command below with your values. (i.e. sudo python gosecure_server_install_pi.py client1@d2.local "mysupersecretpsk")
[Note: These cleanup steps are being cleaned up. They should have been scripted to begin with.]
Note: The following instructions are to build the client in mode 1 (see introduction section for mode definitions).
When the Raspberry Pi first boots, it will execute the commands defined in the cloud-config.client.j2 These initial steps including firmware updating and downloading of the gosecure_client_install.py script. Be patient. Depending on your network speed, this can take a long time.
Note: after a few moments, you have the option to SSH into the goSecure client through eth0 (192.168.50.1), or wlan0 if your computer is on the same Wifi network. Verify the SSH host key using the information output by the cloud-init process.
Log in to the pi account using the password you generated in Step 0.
[Note: These cleanup steps are being cleaned up. They should have been scripted to begin with.]
# interfaces(5) file used by ifup(8) and ifdown(8) # Please note that this file is written to be used with dhcpcd # For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf' # Include files from /etc/network/interfaces.d: source-directory /etc/network/interfaces.d auto lo iface lo inet loopback auto eth0 allow-hotplug eth0 iface eth0 inet static address 192.168.50.1 netmask 255.255.255.0 auto wlan0 allow-hotplug wlan0 iface wlan0 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
country=US ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="<YOUR_WIFI_SSID>" psk="<YOUR_WIFI_PASSWORD>" }
$ make hypriot-img wget -nc https://github.com/hypriot/image-builder-rpi/releases/download/v1.9.0/hypriotos-rpi-v1.9.0.img.zip --2018-09-09 12:07:19-- https://github.com/hypriot/image-builder-rpi/releases/download/v1.9.0/hypriotos-rpi-v1.9.0.img.zip Resolving github.com (github.com)... 192.30.255.112, 192.30.255.113 Connecting to github.com (github.com)|192.30.255.112|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/49221370/4f707dc4-4b28-11e8-851a-5571d179f48f?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20180909%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180909T190717Z&X-Amz-Expires=300&X-Amz-Signature=9573a5242bb9219f934469354fbf64ea4ccc68efa0cd4ec6bd4e91ba38240a18&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dhypriotos-rpi-v1.9.0.img.zip&response-content-type=application%2Foctet-stream [following] --2018-09-09 12:07:19-- https://github-production-release-asset-2e65be.s3.amazonaws.com/49221370/4f707dc4-4b28-11e8-851a-5571d179f48f?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20180909%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180909T190717Z&X-Amz-Expires=300&X-Amz-Signature=9573a5242bb9219f934469354fbf64ea4ccc68efa0cd4ec6bd4e91ba38240a18&X-Amz-SignedHeaders=host&actor_id=0& response-content-disposition=attachment%3B%20filename%3Dhypriotos-rpi-v1.9.0.img.zip&response-content-type=application%2Foctet-stream Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.17.24 Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.17.24|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 313413047 (299M) [application/octet-stream] Saving to: ‘hypriotos-rpi-v1.9.0.img.zip’ hypriotos-rpi-v1.9.0.img.zip 100%[======================================================================================>] 298.89M 2.99MB/s in 86s 2018-09-09 12:08:46 (3.48 MB/s) - ‘hypriotos-rpi-v1.9.0.img.zip’ saved [313413047/313413047] wget -nc https://github.com/hypriot/image-builder-rpi/releases/download/v1.9.0/hypriotos-rpi-v1.9.0.img.zip.sha256 File ‘hypriotos-rpi-v1.9.0.img.zip.sha256’ already there; not retrieving. sha256sum -c hypriotos-rpi-v1.9.0.img.zip.sha256 hypriotos-rpi-v1.9.0.img.zip: OK Archive: hypriotos-rpi-v1.9.0.img.zip inflating: hypriotos-rpi-v1.9.0.img
$ make client-sd flash --userdata /Users/dittrich/.secrets/goSecure/tmp/cloud-config.client hypriotos-rpi-v1.9.0.img Is /dev/disk3 correct? y Unmounting /dev/disk3 ... Unmount of all volumes on disk3 was successful Unmount of all volumes on disk3 was successful Flashing hypriotos-rpi-v1.9.0.img to /dev/rdisk3 ... Password: 1000MiB 0:01:26 [11.5MiB/s] [==================================================================================================================>] 100% 0+16000 records in 0+16000 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 82.7923 s, 12.7 MB/s Mounting Disk Mounting /dev/disk3 to customize... Copying cloud-init /Users/dittrich/.secrets/goSecure/tmp/cloud-config.client to /Volumes/HypriotOS/user-data ... Unmounting /dev/disk3 ... "disk3" unmounted. "disk3" ejected. Finished.
# | Action | curl command |
---|---|---|
1 | Set VPN credentials | curl --user admin:gosecure -H "Content-Type: application/json" -X POST https://192.168.50.1/v1.0/vpn/credentials -d '{"vpn_server":"server1@d2.local", "user_id":"client1@d2.local","user_psk":"mysecretpsk"}' |
2 | Reset (clear) VPN credentials | curl --user admin:gosecure -H "Content-Type: application/json" -X DELETE https://192.168.50.1/v1.0/vpn/credentials |
3 | Start VPN service and establish connection | curl --user admin:gosecure -H "Content-Type: application/json" -X POST https://192.168.50.1/v1.0/vpn/actions -d '{"action":"start_vpn"}' |
4 | Stop VPN service and close connection | curl --user admin:gosecure -H "Content-Type: application/json" -X POST https://192.168.50.1/v1.0/vpn/actions -d '{"action":"stop_vpn"}' |
5 | Restart VPN service and establish connection | curl --user admin:gosecure -H "Content-Type: application/json" -X POST https://192.168.50.1/v1.0/vpn/actions -d '{"action":"restart_vpn"}' |
Refer to the comments in the /etc/ipsec.conf configuration file on the goSecure server. Also add a new line to the /etc/ipsec.secrets configuration file on the goSecure server that contains the new unique_id_of_client and a new unique password.
[The initial work was prepared by an U.S. Government employee and, therefore, is excluded from copyright by Section 105 of the Copyright Act of 1976. Copyright and Related Rights in the Work worldwide are waived through the CC0 1.0 Universal license.
Modificiations subsequent to forking of the original repo were released under the Apache License 2.0.This Work is provided "as is." Any express or implied warranties, including but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the United States Government be liable for any direct, indirect, incidental, special, exemplary or consequential damages (including, but not limited to, procurement of substitute goods or services, loss of use, data or profits, or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this Guidance, even if advised of the possibility of such damage.
The User of this Work agrees to hold harmless and indemnify the United States Government, its agents and employees from every claim or liability (whether in tort or in contract), including attorneys' fees, court costs, and expenses, arising in direct consequence of Recipient's use of the item, including, but not limited to, claims or liabilities made for injury to or death of personnel of User or third parties, damage to or destruction of property of User or third parties, and infringement or other violations of intellectual property or technical data rights.
Nothing in this Work is intended to constitute an endorsement, explicit or implied, by the U.S. Government of any particular manufacturer's product or service.
Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise, in this Work does not constitute an endorsement, recommendation, or favoring by the United States Government and shall not be used for advertising or product endorsement purposes.