diff --git a/config.cfg b/config.cfg index d7f345e..bf65e45 100644 --- a/config.cfg +++ b/config.cfg @@ -11,6 +11,10 @@ users: ### Advanced users only below this line ### +# Store the PKI in a ram disk. Enabled only if store_pki (retain the PKI) is set to false +# Supports on MacOS and Linux only (including Windows Subsystem for Linux) +pki_in_tmpfs: true + # If True re-init all existing certificates. Boolean keys_clean_all: False diff --git a/docs/cloud-do.md b/docs/cloud-do.md index ced8d69..6603dc8 100644 --- a/docs/cloud-do.md +++ b/docs/cloud-do.md @@ -87,7 +87,7 @@ ansible-playbook main.yml -e "provider=digitalocean dns_adblocking=false ssh_tunneling=false windows=false - store_cakey=true + store_pki=true region=nyc3 do_token=token" ``` diff --git a/docs/deploy-from-ansible.md b/docs/deploy-from-ansible.md index 62e126d..bc093b6 100644 --- a/docs/deploy-from-ansible.md +++ b/docs/deploy-from-ansible.md @@ -18,7 +18,7 @@ ansible-playbook main.yml -e "provider=digitalocean dns_adblocking=true ssh_tunneling=true windows=false - store_cakey=true + store_pki=true region=ams3 do_token=token" ``` diff --git a/docs/deploy-from-script-or-cloud-init-to-localhost.md b/docs/deploy-from-script-or-cloud-init-to-localhost.md index 3a6472a..22ba295 100644 --- a/docs/deploy-from-script-or-cloud-init-to-localhost.md +++ b/docs/deploy-from-script-or-cloud-init-to-localhost.md @@ -19,7 +19,7 @@ The command will prepare the environment and install AlgoVPN with the default pa `ONDEMAND_WIFI` - "Connect On Demand" when connected to Wi-Fi. Default: false. `ONDEMAND_WIFI_EXCLUDE` - List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand". Comma-separated list. `WINDOWS` - To support Windows 10 or Linux Desktop clients. Default: false. -`STORE_CAKEY` - To retain the CA key. (required to add users in the future, but less secure). Default: false. +`STORE_PKI` - To retain the PKI. (required to add users in the future, but less secure). Default: false. `DNS_ADBLOCKING` - To install an ad blocking DNS resolver. Default: false. `SSH_TUNNELING` - Enable SSH tunneling for each user. Default: false. `ENDPOINT` - The public IP address or domain name of your server: (IMPORTANT! This is used to verify the certificate). It will be gathered automatically for DigitalOcean, AWS, GCE, Azure or Vultr if the `METHOD` is cloud. Otherwise you need to define this variable according to your public IP address. diff --git a/input.yml b/input.yml index 763b2cd..40005dc 100644 --- a/input.yml +++ b/input.yml @@ -10,7 +10,7 @@ dns_adblocking: false ssh_tunneling: false windows: false - store_cakey: false + store_pki: false providers_map: - { name: DigitalOcean, alias: digitalocean } - { name: Amazon Lightsail, alias: lightsail } @@ -87,13 +87,13 @@ register: _windows when: windows is undefined - - name: Retain the CA key prompt + - name: Retain the PKI prompt pause: prompt: | - Do you want to retain the CA key? (required to add users in the future, but less secure) + Do you want to retain the keys (PKI)? (required to add users in the future, but less secure) [y/N] - register: _store_cakey - when: store_cakey is undefined + register: _store_pki + when: store_pki is undefined when: ipsec_enabled - name: DNS adblocking prompt @@ -145,9 +145,9 @@ {% if windows is defined %}{{ windows | bool }} {%- elif _windows.user_input is defined %}{{ booleans_map[_windows.user_input] | default(defaults['windows']) }} {%- else %}false{% endif %} - algo_store_cakey: >- - {% if ipsec_enabled %}{%- if store_cakey is defined %}{{ store_cakey | bool }} - {%- elif _store_cakey.user_input is defined %}{{ booleans_map[_store_cakey.user_input] | default(defaults['store_cakey']) }} + algo_store_pki: >- + {% if ipsec_enabled %}{%- if store_pki is defined %}{{ store_pki | bool }} + {%- elif _store_pki.user_input is defined %}{{ booleans_map[_store_pki.user_input] | default(defaults['store_pki']) }} {%- else %}false{% endif %}{% endif %} rescue: - include_tasks: playbooks/rescue.yml diff --git a/install.sh b/install.sh index ff3e343..51de5bd 100644 --- a/install.sh +++ b/install.sh @@ -7,7 +7,7 @@ ONDEMAND_CELLULAR="${2:-${ONDEMAND_CELLULAR:-false}}" ONDEMAND_WIFI="${3:-${ONDEMAND_WIFI:-false}}" ONDEMAND_WIFI_EXCLUDE="${4:-${ONDEMAND_WIFI_EXCLUDE:-_null}}" WINDOWS="${5:-${WINDOWS:-false}}" -STORE_CAKEY="${6:-${STORE_CAKEY:-false}}" +STORE_PKI="${6:-${STORE_PKI:-false}}" DNS_ADBLOCKING="${7:-${DNS_ADBLOCKING:-false}}" SSH_TUNNELING="${8:-${SSH_TUNNELING:-false}}" ENDPOINT="${9:-${ENDPOINT:-localhost}}" @@ -92,7 +92,7 @@ deployAlgo() { -e "ondemand_wifi=${ONDEMAND_WIFI}" \ -e "ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE}" \ -e "windows=${WINDOWS}" \ - -e "store_cakey=${STORE_CAKEY}" \ + -e "store_pki=${STORE_PKI}" \ -e "dns_adblocking=${DNS_ADBLOCKING}" \ -e "ssh_tunneling=${SSH_TUNNELING}" \ -e "endpoint=$ENDPOINT" \ diff --git a/playbooks/cloud-post.yml b/playbooks/cloud-post.yml index 95eacfe..6fd9087 100644 --- a/playbooks/cloud-post.yml +++ b/playbooks/cloud-post.yml @@ -18,7 +18,7 @@ algo_dns_adblocking: "{{ algo_dns_adblocking }}" algo_ssh_tunneling: "{{ algo_ssh_tunneling }}" algo_windows: "{{ algo_windows }}" - algo_store_cakey: "{{ algo_store_cakey }}" + algo_store_pki: "{{ algo_store_pki }}" IP_subject_alt_name: "{{ IP_subject_alt_name }}" - name: Additional variables for the server @@ -37,6 +37,14 @@ state: present when: cloud_instance_ip != "localhost" +- name: Mount tmpfs + import_tasks: tmpfs/main.yml + when: + - pki_in_tmpfs + - not algo_store_pki + - ansible_system == "Darwin" or + ansible_system == "Linux" + - debug: var: IP_subject_alt_name diff --git a/playbooks/tmpfs/linux.yml b/playbooks/tmpfs/linux.yml new file mode 100644 index 0000000..64a9651 --- /dev/null +++ b/playbooks/tmpfs/linux.yml @@ -0,0 +1,5 @@ +--- +- name: Linux | set OS specific facts + set_fact: + tmpfs_volume_name: "AlgoVPN-{{ IP_subject_alt_name }}" + tmpfs_volume_path: /dev/shm diff --git a/playbooks/tmpfs/macos.yml b/playbooks/tmpfs/macos.yml new file mode 100644 index 0000000..72243da --- /dev/null +++ b/playbooks/tmpfs/macos.yml @@ -0,0 +1,12 @@ +--- +- name: MacOS | set OS specific facts + set_fact: + tmpfs_volume_name: "AlgoVPN-{{ IP_subject_alt_name }}" + tmpfs_volume_path: /Volumes + +- name: MacOS | mount a ram disk + shell: > + /usr/sbin/diskutil info "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/" || + /usr/sbin/diskutil erasevolume HFS+ "{{ tmpfs_volume_name }}" $(hdiutil attach -nomount ram://64000) + args: + creates: "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}" diff --git a/playbooks/tmpfs/main.yml b/playbooks/tmpfs/main.yml new file mode 100644 index 0000000..d8fd7c2 --- /dev/null +++ b/playbooks/tmpfs/main.yml @@ -0,0 +1,19 @@ +--- +- name: Include tasks for MacOS + import_tasks: macos.yml + when: ansible_system == "Darwin" + +- name: Include tasks for Linux + import_tasks: linux.yml + when: ansible_system == "Linux" + +- name: Set config paths as facts + set_fact: + wireguard_pki_path: "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/WireGuard/" + ipsec_pki_path: "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/IPsec/" + +- name: Update config paths + add_host: + name: "{{ 'localhost' if cloud_instance_ip == 'localhost' else cloud_instance_ip }}" + wireguard_pki_path: "{{ wireguard_pki_path }}" + ipsec_pki_path: "{{ ipsec_pki_path }}" diff --git a/playbooks/tmpfs/umount.yml b/playbooks/tmpfs/umount.yml new file mode 100644 index 0000000..681278e --- /dev/null +++ b/playbooks/tmpfs/umount.yml @@ -0,0 +1,26 @@ +--- +- name: Linux | Delete the PKI directory + file: + path: "/{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/" + state: absent + when: facts.ansible_system == "Linux" + +- block: + - name: MacOS | check fs the ramdisk exists + command: /usr/sbin/diskutil info "{{ facts.tmpfs_volume_name }}" + ignore_errors: true + changed_when: false + register: diskutil_info + + - name: MacOS | unmount and eject the ram disk + shell: > + /usr/sbin/diskutil umount force "/{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/" && + /usr/sbin/diskutil eject "{{ facts.tmpfs_volume_name }}" + changed_when: false + when: diskutil_info.rc == 0 + register: result + until: result.rc == 0 + retries: 5 + delay: 3 + when: + - facts.ansible_system == "Darwin" diff --git a/roles/strongswan/defaults/main.yml b/roles/strongswan/defaults/main.yml index 962899c..7bc9974 100644 --- a/roles/strongswan/defaults/main.yml +++ b/roles/strongswan/defaults/main.yml @@ -8,7 +8,6 @@ algo_ondemand_cellular: false algo_ondemand_wifi: false algo_ondemand_wifi_exclude: '_null' algo_windows: false -algo_store_cakey: false algo_dns_adblocking: false ipv6_support: false dns_encryption: true diff --git a/roles/strongswan/tasks/main.yml b/roles/strongswan/tasks/main.yml index e59295d..7ffb1d1 100644 --- a/roles/strongswan/tasks/main.yml +++ b/roles/strongswan/tasks/main.yml @@ -29,3 +29,13 @@ enabled: true - meta: flush_handlers + +- name: Delete the PKI directory + file: + path: "{{ ipsec_pki_path }}" + state: absent + become: false + delegate_to: localhost + when: + - not algo_store_pki + - not pki_in_tmpfs diff --git a/roles/strongswan/tasks/openssl.yml b/roles/strongswan/tasks/openssl.yml index b813e61..8420211 100644 --- a/roles/strongswan/tasks/openssl.yml +++ b/roles/strongswan/tasks/openssl.yml @@ -231,13 +231,3 @@ - gencrl.changed notify: - rereadcrls - -- name: Delete the CA key - file: - path: "{{ ipsec_pki_path }}/private/cakey.pem" - state: absent - become: false - delegate_to: localhost - when: - - ipsec_enabled - - not algo_store_cakey diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml index c34580b..4e38762 100644 --- a/roles/wireguard/tasks/main.yml +++ b/roles/wireguard/tasks/main.yml @@ -1,13 +1,14 @@ --- - name: Ensure the required directories exist file: - dest: "{{ wireguard_pki_path }}/{{ item }}" + dest: "{{ item }}" state: directory recurse: true with_items: - - private - - public - - preshared + - "{{ wireguard_pki_path }}/preshared" + - "{{ wireguard_pki_path }}/private" + - "{{ wireguard_pki_path }}/public" + - "{{ wireguard_config_path }}" delegate_to: localhost become: false @@ -82,4 +83,14 @@ state: started enabled: true +- name: Delete the PKI directory + file: + path: "{{ wireguard_pki_path }}" + state: absent + become: false + delegate_to: localhost + when: + - not algo_store_pki + - not pki_in_tmpfs + - meta: flush_handlers diff --git a/server.yml b/server.yml index 9a0d395..3e51c22 100644 --- a/server.yml +++ b/server.yml @@ -51,7 +51,7 @@ algo_dns_adblocking: {{ algo_dns_adblocking }} algo_ssh_tunneling: {{ algo_ssh_tunneling }} algo_windows: {{ algo_windows }} - algo_store_cakey: {{ algo_store_cakey }} + algo_store_pki: {{ algo_store_pki }} IP_subject_alt_name: {{ IP_subject_alt_name }} ipsec_enabled: {{ ipsec_enabled }} wireguard_enabled: {{ wireguard_enabled }} @@ -70,11 +70,21 @@ force: true when: inventory_hostname == 'localhost' + - name: Import tmpfs tasks + import_tasks: playbooks/tmpfs/umount.yml + become: false + delegate_to: localhost + vars: + facts: "{{ hostvars['localhost'] }}" + when: + - pki_in_tmpfs + - not algo_store_pki + - debug: msg: - "{{ congrats.common.split('\n') }}" - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" - - " {{ congrats.ca_key_pass if algo_store_cakey and ipsec_enabled else '' }}" + - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" tags: always rescue: diff --git a/tests/cloud-init.sh b/tests/cloud-init.sh index 19d3030..0dbec14 100755 --- a/tests/cloud-init.sh +++ b/tests/cloud-init.sh @@ -5,7 +5,7 @@ export ONDEMAND_CELLULAR=true export ONDEMAND_WIFI=true export ONDEMAND_WIFI_EXCLUDE=test1,test2 export WINDOWS=true -export STORE_CAKEY=true +export STORE_PKI=true export DNS_ADBLOCKING=true export SSH_TUNNELING=true export ENDPOINT=10.0.8.100 diff --git a/tests/local-deploy.sh b/tests/local-deploy.sh index f452fe4..6f57537 100755 --- a/tests/local-deploy.sh +++ b/tests/local-deploy.sh @@ -2,7 +2,7 @@ set -ex -DEPLOY_ARGS="provider=local server=10.0.8.100 ssh_user=ubuntu endpoint=10.0.8.100 apparmor_enabled=false ondemand_cellular=true ondemand_wifi=true ondemand_wifi_exclude=test dns_adblocking=true ssh_tunneling=true windows=true store_cakey=true install_headers=false tests=true local_service_ip=172.16.0.1" +DEPLOY_ARGS="provider=local server=10.0.8.100 ssh_user=ubuntu endpoint=10.0.8.100 apparmor_enabled=false ondemand_cellular=true ondemand_wifi=true ondemand_wifi_exclude=test dns_adblocking=true ssh_tunneling=true windows=true store_pki=true install_headers=false tests=true local_service_ip=172.16.0.1" if [ "${DEPLOY}" == "docker" ] then diff --git a/users.yml b/users.yml index 540a158..479c28c 100644 --- a/users.yml +++ b/users.yml @@ -113,7 +113,7 @@ msg: - "{{ congrats.common.split('\n') }}" - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" - - " {{ congrats.ca_key_pass if algo_store_cakey and ipsec_enabled else '' }}" + - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" tags: always rescue: