diff --git a/algo.egg-info/PKG-INFO b/algo.egg-info/PKG-INFO new file mode 100644 index 000000000..f566afd00 --- /dev/null +++ b/algo.egg-info/PKG-INFO @@ -0,0 +1,34 @@ +Metadata-Version: 2.4 +Name: algo +Version: 2.0.0b0 +Summary: Set up a personal IPSEC VPN in the cloud +Requires-Python: >=3.11 +License-File: LICENSE +Requires-Dist: ansible==11.8.0 +Requires-Dist: jinja2>=3.1.6 +Requires-Dist: netaddr==1.3.0 +Requires-Dist: pyyaml>=6.0.2 +Requires-Dist: pyopenssl>=0.15 +Requires-Dist: segno>=1.6.0 +Provides-Extra: aws +Requires-Dist: boto3>=1.34.0; extra == "aws" +Requires-Dist: boto>=2.49.0; extra == "aws" +Provides-Extra: azure +Requires-Dist: azure-identity>=1.15.0; extra == "azure" +Requires-Dist: azure-mgmt-compute>=30.0.0; extra == "azure" +Requires-Dist: azure-mgmt-network>=25.0.0; extra == "azure" +Requires-Dist: azure-mgmt-resource>=23.0.0; extra == "azure" +Requires-Dist: msrestazure>=0.6.4; extra == "azure" +Provides-Extra: gcp +Requires-Dist: google-auth>=2.28.0; extra == "gcp" +Requires-Dist: requests>=2.31.0; extra == "gcp" +Provides-Extra: hetzner +Requires-Dist: hcloud>=1.33.0; extra == "hetzner" +Provides-Extra: linode +Requires-Dist: linode-api4>=5.15.0; extra == "linode" +Provides-Extra: openstack +Requires-Dist: openstacksdk>=2.1.0; extra == "openstack" +Provides-Extra: cloudstack +Requires-Dist: cs>=3.0.0; extra == "cloudstack" +Requires-Dist: sshpubkeys>=3.3.1; extra == "cloudstack" +Dynamic: license-file diff --git a/algo.egg-info/SOURCES.txt b/algo.egg-info/SOURCES.txt new file mode 100644 index 000000000..acc891bab --- /dev/null +++ b/algo.egg-info/SOURCES.txt @@ -0,0 +1,10 @@ +LICENSE +README.md +pyproject.toml +algo.egg-info/PKG-INFO +algo.egg-info/SOURCES.txt +algo.egg-info/dependency_links.txt +algo.egg-info/requires.txt +algo.egg-info/top_level.txt +tests/test_cloud_init_template.py +tests/test_package_preinstall.py \ No newline at end of file diff --git a/algo.egg-info/dependency_links.txt b/algo.egg-info/dependency_links.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/algo.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/algo.egg-info/requires.txt b/algo.egg-info/requires.txt new file mode 100644 index 000000000..876f52684 --- /dev/null +++ b/algo.egg-info/requires.txt @@ -0,0 +1,34 @@ +ansible==11.8.0 +jinja2>=3.1.6 +netaddr==1.3.0 +pyyaml>=6.0.2 +pyopenssl>=0.15 +segno>=1.6.0 + +[aws] +boto3>=1.34.0 +boto>=2.49.0 + +[azure] +azure-identity>=1.15.0 +azure-mgmt-compute>=30.0.0 +azure-mgmt-network>=25.0.0 +azure-mgmt-resource>=23.0.0 +msrestazure>=0.6.4 + +[cloudstack] +cs>=3.0.0 +sshpubkeys>=3.3.1 + +[gcp] +google-auth>=2.28.0 +requests>=2.31.0 + +[hetzner] +hcloud>=1.33.0 + +[linode] +linode-api4>=5.15.0 + +[openstack] +openstacksdk>=2.1.0 diff --git a/algo.egg-info/top_level.txt b/algo.egg-info/top_level.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/algo.egg-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/config.cfg b/config.cfg index 30b142c0f..d4a1164fb 100644 --- a/config.cfg +++ b/config.cfg @@ -129,7 +129,69 @@ keys_clean_all: false # StrongSwan log level # https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration -strongswan_log_level: 2 +# Privacy enhancement: Set to -1 to disable logging of VPN connection details +# Level 2 logs connection attempts and authentication which may reveal usage patterns +# Level -1 disables logging entirely for enhanced privacy +strongswan_log_level: -1 + +### Privacy Enhancements ### +# Additional privacy measures to reduce server-side traces of VPN usage +# These settings help protect user privacy by minimizing log retention and filtering sensitive data + +# Enable enhanced privacy features +# Set to false to disable all privacy enhancements (useful for debugging) +privacy_enhancements_enabled: true + +# Log rotation and retention settings +privacy_log_rotation: + # Maximum age for logs in days (shorter = more private, but less debugging info) + max_age: 7 + # Maximum size for individual log files in MB + max_size: 10 + # Number of rotated files to keep + rotate_count: 3 + # Compress rotated logs to save space + compress: true + # Force daily rotation + daily_rotation: true + +# History clearing configuration +privacy_history_clearing: + # Clear bash/shell history after deployment + clear_bash_history: true + # Clear system command history logs + clear_system_history: true + # Disable persistent history for system users + disable_service_history: true + +# Log filtering to exclude VPN-related entries +privacy_log_filtering: + # Filter out VPN connection logs (WireGuard, StrongSwan, etc.) + exclude_vpn_logs: true + # Filter out detailed authentication logs (reduces security logging - use with caution) + exclude_auth_logs: false + # Filter kernel messages related to VPN traffic + filter_kernel_vpn_logs: true + +# Automatic cleanup policies +privacy_auto_cleanup: + # Enable automatic cleanup of old logs and temporary files + enabled: true + # Cleanup frequency: daily, weekly, or monthly + frequency: "daily" + # Remove temporary files older than N days + temp_files_max_age: 1 + # Clean package manager cache + clean_package_cache: true + +# Advanced privacy settings (use with caution) +privacy_advanced: + # Disable logging of successful SSH connections (keeps failures for security) + disable_ssh_success_logs: false + # Reduce kernel log verbosity to minimize VPN traces + reduce_kernel_verbosity: true + # Clear all logs on system shutdown (extreme privacy measure) + clear_logs_on_shutdown: false # rightsourceip for ipsec # ipv4 diff --git a/docs/faq.md b/docs/faq.md index 399256762..bd66c9305 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -10,6 +10,7 @@ * [I deployed an Algo server. Can you update it with new features?](#i-deployed-an-algo-server-can-you-update-it-with-new-features) * [Where did the name "Algo" come from?](#where-did-the-name-algo-come-from) * [Can DNS filtering be disabled?](#can-dns-filtering-be-disabled) +* [Does Algo support zero logging?](#does-algo-support-zero-logging) * [Wasn't IPSEC backdoored by the US government?](#wasnt-ipsec-backdoored-by-the-us-government) * [What inbound ports are used?](#what-inbound-ports-are-used) * [How do I monitor user activity?](#how-do-i-monitor-user-activity) @@ -59,6 +60,37 @@ Algo is short for "Al Gore", the **V**ice **P**resident of **N**etworks everywhe You can temporarily disable DNS filtering for all IPsec clients at once with the following workaround: SSH to your Algo server (using the 'shell access' command printed upon a successful deployment), edit `/etc/ipsec.conf`, and change `rightdns=` to `rightdns=8.8.8.8`. Then run `sudo systemctl restart strongswan`. DNS filtering for WireGuard clients has to be disabled on each client device separately by modifying the settings in the app, or by directly modifying the `DNS` setting on the `clientname.conf` file. If all else fails, we recommend deploying a new Algo server without the adblocking feature enabled. +## Does Algo support zero logging? + +Algo was not originally designed for zero-logging, but recent updates have introduced privacy enhancements to significantly reduce the logging footprint. Here's what you need to know: + +**Recent Privacy Enhancements:** +* **StrongSwan logging disabled by default** - Connection logs no longer record who connects, when, or from which IP +* **DNSCrypt syslog disabled** - DNS queries are not logged to system logs +* **Sensitive data protection** - All passwords, keys, and credentials are now hidden from Ansible logs +* **Aggressive log rotation** - Logs are automatically rotated and deleted after 7 days +* **Optional privacy features** - Bash history clearing, VPN log filtering, and more + +**What May Still Be Logged:** +* System errors and security events (failed authentications, system updates) +* SSH administrative access for server management +* Cloud provider logs and metadata (outside Algo's control) +* Kernel messages and system diagnostics needed for troubleshooting + +**How to Maximize Privacy:** +* Keep the default privacy settings enabled in `config.cfg` +* Use the privacy monitoring script: `sudo /usr/local/bin/privacy-monitor.sh` +* Deploy on ephemeral cloud instances that can be destroyed when needed +* Review the privacy settings in `config.cfg` for additional options + +**Important Limitations:** +* WireGuard inherently shows last endpoint and handshake time via `sudo wg` +* Cloud providers maintain their own logs and traffic metadata +* Your ISP and destination websites can still observe traffic patterns +* Complete zero-logging may make troubleshooting difficult + +The privacy enhancements are enabled by default but can be disabled if you need more detailed logging for debugging. See the `privacy_enhancements_enabled` setting in `config.cfg`. + ## Wasn't IPSEC backdoored by the US government? No. diff --git a/roles/cloud-azure/tasks/prompts.yml b/roles/cloud-azure/tasks/prompts.yml index 99fd03b33..38f0b3756 100644 --- a/roles/cloud-azure/tasks/prompts.yml +++ b/roles/cloud-azure/tasks/prompts.yml @@ -4,6 +4,7 @@ tenant: "{{ azure_tenant | default(lookup('env','AZURE_TENANT'), true) }}" client_id: "{{ azure_client_id | default(lookup('env','AZURE_CLIENT_ID'), true) }}" subscription_id: "{{ azure_subscription_id | default(lookup('env','AZURE_SUBSCRIPTION_ID'), true) }}" + no_log: true - block: - name: Set the default region diff --git a/roles/cloud-cloudstack/tasks/main.yml b/roles/cloud-cloudstack/tasks/main.yml index ea0593824..744dd62e1 100644 --- a/roles/cloud-cloudstack/tasks/main.yml +++ b/roles/cloud-cloudstack/tasks/main.yml @@ -57,3 +57,4 @@ CLOUDSTACK_KEY: "{{ algo_cs_key }}" CLOUDSTACK_SECRET: "{{ algo_cs_token }}" CLOUDSTACK_ENDPOINT: "{{ algo_cs_url }}" + no_log: true diff --git a/roles/cloud-cloudstack/tasks/prompts.yml b/roles/cloud-cloudstack/tasks/prompts.yml index 78d299f3e..d09d46347 100644 --- a/roles/cloud-cloudstack/tasks/prompts.yml +++ b/roles/cloud-cloudstack/tasks/prompts.yml @@ -8,6 +8,7 @@ when: - cs_key is undefined - lookup('env','CLOUDSTACK_KEY')|length <= 0 + no_log: true - pause: prompt: | @@ -17,6 +18,7 @@ when: - cs_secret is undefined - lookup('env','CLOUDSTACK_SECRET')|length <= 0 + no_log: true - pause: prompt: | @@ -34,6 +36,7 @@ {{ cs_url | default(_cs_url.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_ENDPOINT'), true) | default('https://api.exoscale.com/compute', true) }} + no_log: true - name: Get zones on cloud cs_zone_info: @@ -42,6 +45,7 @@ CLOUDSTACK_KEY: "{{ algo_cs_key }}" CLOUDSTACK_SECRET: "{{ algo_cs_token }}" CLOUDSTACK_ENDPOINT: "{{ algo_cs_url }}" + no_log: true - name: Extract zones from output set_fact: diff --git a/roles/cloud-digitalocean/tasks/prompts.yml b/roles/cloud-digitalocean/tasks/prompts.yml index 7f24e3f90..67a9401fd 100644 --- a/roles/cloud-digitalocean/tasks/prompts.yml +++ b/roles/cloud-digitalocean/tasks/prompts.yml @@ -7,10 +7,12 @@ when: - do_token is undefined - lookup('env','DO_API_TOKEN')|length <= 0 + no_log: true - name: Set the token as a fact set_fact: algo_do_token: "{{ do_token | default(_do_token.user_input|default(None)) | default(lookup('env','DO_API_TOKEN'), true) }}" + no_log: true - name: Get regions uri: @@ -21,6 +23,7 @@ Content-Type: application/json Authorization: Bearer {{ algo_do_token }} register: _do_regions + no_log: true - name: Set facts about the regions set_fact: diff --git a/roles/cloud-ec2/tasks/cloudformation.yml b/roles/cloud-ec2/tasks/cloudformation.yml index 75dd5f361..407b34870 100644 --- a/roles/cloud-ec2/tasks/cloudformation.yml +++ b/roles/cloud-ec2/tasks/cloudformation.yml @@ -20,3 +20,4 @@ tags: Environment: Algo register: stack + no_log: true diff --git a/roles/cloud-ec2/tasks/main.yml b/roles/cloud-ec2/tasks/main.yml index 5f68c9270..e6e302073 100644 --- a/roles/cloud-ec2/tasks/main.yml +++ b/roles/cloud-ec2/tasks/main.yml @@ -15,6 +15,7 @@ architecture: "{{ cloud_providers.ec2.image.arch }}" name: ubuntu/images/hvm-ssd/{{ cloud_providers.ec2.image.name }}-*64-server-* register: ami_search + no_log: true - name: Set the ami id as a fact set_fact: diff --git a/roles/cloud-ec2/tasks/prompts.yml b/roles/cloud-ec2/tasks/prompts.yml index 73224727c..fecc58468 100644 --- a/roles/cloud-ec2/tasks/prompts.yml +++ b/roles/cloud-ec2/tasks/prompts.yml @@ -73,6 +73,7 @@ aws_session_token: "{{ session_token if session_token else omit }}" region: us-east-1 register: _aws_regions + no_log: true - name: Set facts about the regions set_fact: @@ -114,6 +115,7 @@ aws_session_token: "{{ session_token if session_token else omit }}" region: "{{ algo_region }}" register: raw_eip_addresses + no_log: true - set_fact: available_eip_addresses: "{{ raw_eip_addresses.addresses | selectattr('association_id', 'undefined') | list }}" diff --git a/roles/cloud-gce/tasks/prompts.yml b/roles/cloud-gce/tasks/prompts.yml index b770da50a..1b19db98b 100644 --- a/roles/cloud-gce/tasks/prompts.yml +++ b/roles/cloud-gce/tasks/prompts.yml @@ -7,19 +7,23 @@ when: - gce_credentials_file is undefined - lookup('env','GCE_CREDENTIALS_FILE_PATH')|length <= 0 + no_log: true - set_fact: credentials_file_path: >- {{ gce_credentials_file | default(_gce_credentials_file.user_input|default(None)) | default(lookup('env','GCE_CREDENTIALS_FILE_PATH'), true) }} ssh_public_key_lookup: "{{ lookup('file', '{{ SSH_keys.public }}') }}" + no_log: true - set_fact: credentials_file_lookup: "{{ lookup('file', '{{ credentials_file_path }}') }}" + no_log: true - set_fact: service_account_email: "{{ credentials_file_lookup.client_email | default(lookup('env','GCE_EMAIL')) }}" project_id: "{{ credentials_file_lookup.project_id | default(lookup('env','GCE_PROJECT')) }}" + no_log: true - block: - name: Get regions diff --git a/roles/cloud-hetzner/tasks/prompts.yml b/roles/cloud-hetzner/tasks/prompts.yml index 3663b7e67..d12b33877 100644 --- a/roles/cloud-hetzner/tasks/prompts.yml +++ b/roles/cloud-hetzner/tasks/prompts.yml @@ -7,10 +7,12 @@ when: - hcloud_token is undefined - lookup('env','HCLOUD_TOKEN')|length <= 0 + no_log: true - name: Set the token as a fact set_fact: algo_hcloud_token: "{{ hcloud_token | default(_hcloud_token.user_input|default(None)) | default(lookup('env','HCLOUD_TOKEN'), true) }}" + no_log: true - name: Get regions hetzner.hcloud.datacenter_info: diff --git a/roles/cloud-lightsail/tasks/cloudformation.yml b/roles/cloud-lightsail/tasks/cloudformation.yml index d3798a90d..1a1c37d4e 100644 --- a/roles/cloud-lightsail/tasks/cloudformation.yml +++ b/roles/cloud-lightsail/tasks/cloudformation.yml @@ -17,3 +17,4 @@ Environment: Algo Lightsail: true register: stack + no_log: true diff --git a/roles/cloud-lightsail/tasks/prompts.yml b/roles/cloud-lightsail/tasks/prompts.yml index 49e6bd01f..d49cc5dee 100644 --- a/roles/cloud-lightsail/tasks/prompts.yml +++ b/roles/cloud-lightsail/tasks/prompts.yml @@ -8,6 +8,7 @@ when: - aws_access_key is undefined - lookup('env','AWS_ACCESS_KEY_ID')|length <= 0 + no_log: true - pause: prompt: | @@ -17,10 +18,12 @@ when: - aws_secret_key is undefined - lookup('env','AWS_SECRET_ACCESS_KEY')|length <= 0 + no_log: true - set_fact: access_key: "{{ aws_access_key | default(_aws_access_key.user_input|default(None)) | default(lookup('env','AWS_ACCESS_KEY_ID'), true) }}" secret_key: "{{ aws_secret_key | default(_aws_secret_key.user_input|default(None)) | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true) }}" + no_log: true - block: - name: Get regions @@ -29,6 +32,7 @@ aws_secret_key: "{{ secret_key }}" region: us-east-1 register: _lightsail_regions + no_log: true - name: Set facts about the regions set_fact: diff --git a/roles/cloud-linode/tasks/main.yml b/roles/cloud-linode/tasks/main.yml index 8cdd47f40..4b316f1b9 100644 --- a/roles/cloud-linode/tasks/main.yml +++ b/roles/cloud-linode/tasks/main.yml @@ -23,6 +23,7 @@ script: | {{ stackscript }} register: _linode_stackscript + no_log: true - name: Update the stackscript uri: @@ -36,6 +37,7 @@ Content-Type: application/json Authorization: Bearer {{ algo_linode_token }} when: (_linode_stackscript.stackscript.script | hash('md5')) != (stackscript | hash('md5')) + no_log: true - name: Creating an instance... linode_v4: @@ -48,6 +50,7 @@ authorized_keys: "{{ public_key }}" stackscript_id: "{{ _linode_stackscript.stackscript.id }}" register: _linode + no_log: true - set_fact: cloud_instance_ip: "{{ _linode.instance.ipv4[0] }}" diff --git a/roles/cloud-linode/tasks/prompts.yml b/roles/cloud-linode/tasks/prompts.yml index 84d85b92d..90f7f2bc5 100644 --- a/roles/cloud-linode/tasks/prompts.yml +++ b/roles/cloud-linode/tasks/prompts.yml @@ -7,10 +7,12 @@ when: - linode_token is undefined - lookup('env','LINODE_API_TOKEN')|length <= 0 + no_log: true - name: Set the token as a fact set_fact: algo_linode_token: "{{ linode_token | default(_linode_token.user_input|default(None)) | default(lookup('env','LINODE_API_TOKEN'), true) }}" + no_log: true - name: Get regions uri: diff --git a/roles/cloud-scaleway/tasks/prompts.yml b/roles/cloud-scaleway/tasks/prompts.yml index 7e371d213..d0f35fe77 100644 --- a/roles/cloud-scaleway/tasks/prompts.yml +++ b/roles/cloud-scaleway/tasks/prompts.yml @@ -7,6 +7,7 @@ when: - scaleway_token is undefined - lookup('env','SCW_TOKEN')|length <= 0 + no_log: true - pause: prompt: | @@ -27,3 +28,4 @@ {% if region is defined %}{{ region }} {%- elif _algo_region.user_input %}{{ scaleway_regions[_algo_region.user_input | int -1 ]['alias'] }} {%- else %}{{ scaleway_regions.0.alias }}{% endif %} + no_log: true diff --git a/roles/cloud-vultr/tasks/prompts.yml b/roles/cloud-vultr/tasks/prompts.yml index 04108219a..d58ff4b2f 100644 --- a/roles/cloud-vultr/tasks/prompts.yml +++ b/roles/cloud-vultr/tasks/prompts.yml @@ -7,10 +7,12 @@ when: - vultr_config is undefined - lookup('env','VULTR_API_CONFIG')|length <= 0 + no_log: true - name: Set the token as a fact set_fact: algo_vultr_config: "{{ vultr_config | default(_vultr_config.user_input) | default(lookup('env','VULTR_API_CONFIG'), true) }}" + no_log: true - name: Set the Vultr API Key as a fact set_fact: diff --git a/roles/common/tasks/facts.yml b/roles/common/tasks/facts.yml index 61a17ae64..681626454 100644 --- a/roles/common/tasks/facts.yml +++ b/roles/common/tasks/facts.yml @@ -3,11 +3,13 @@ set_fact: p12_export_password: "{{ p12_password|default(lookup('password', '/dev/null length=9 chars=ascii_letters,digits,_,@')) }}" tags: update-users + no_log: true - name: Set facts set_fact: CA_password: "{{ ca_password|default(lookup('password', '/dev/null length=16 chars=ascii_letters,digits,_,@')) }}" IP_subject_alt_name: "{{ IP_subject_alt_name }}" + no_log: true - name: Set IPv6 support as a fact set_fact: diff --git a/roles/dns/templates/dnscrypt-proxy.toml.j2 b/roles/dns/templates/dnscrypt-proxy.toml.j2 index d0e2e0938..0a07dfccc 100644 --- a/roles/dns/templates/dnscrypt-proxy.toml.j2 +++ b/roles/dns/templates/dnscrypt-proxy.toml.j2 @@ -137,8 +137,11 @@ lb_strategy = 'p2' ## Log level (0-6, default: 2 - 0 is very verbose, 6 only contains fatal errors) +## Privacy enhancement: Set to 4 (warnings and errors only) to reduce information disclosure +## Lower levels may log DNS queries and connection details that could compromise privacy +## Level 4 provides essential error information while minimizing privacy-sensitive logging -log_level = 2 +log_level = 4 ## log file for the application @@ -147,8 +150,11 @@ log_level = 2 ## Use the system logger (syslog on Unix, Event Log on Windows) +## Privacy enhancement: Disabled by default to prevent DNS query logging in system logs +## DNS queries logged to syslog can reveal browsing patterns and compromise privacy +## Enable only if required for debugging purposes -use_syslog = true +use_syslog = false ## Delay, in minutes, after which certificates are reloaded @@ -332,6 +338,9 @@ cache_neg_max_ttl = 600 ############################### ## Log client queries to a file +## Privacy warning: Enabling query logging will record all DNS requests +## which can reveal detailed browsing patterns and compromise user privacy +## Only enable for debugging purposes and disable immediately after use [query_log] @@ -358,6 +367,8 @@ cache_neg_max_ttl = 600 ## Log queries for nonexistent zones ## These queries can reveal the presence of malware, broken/obsolete applications, ## and devices signaling their presence to 3rd parties. +## Privacy warning: This logging can still reveal browsing patterns and queried domains +## Only enable for security monitoring purposes when necessary [nx_log] diff --git a/roles/privacy/README.md b/roles/privacy/README.md new file mode 100644 index 000000000..31461f5b4 --- /dev/null +++ b/roles/privacy/README.md @@ -0,0 +1,205 @@ +# Privacy Enhancements Role + +This Ansible role implements additional privacy enhancements for Algo VPN to minimize server-side traces of VPN usage and reduce log retention. These measures help protect user privacy while maintaining system security. + +## Features + +### 1. Aggressive Log Rotation +- Configures shorter log retention periods (default: 7 days) +- Implements more frequent log rotation +- Compresses rotated logs to save space +- Automatically cleans up old log files + +### 2. History Clearing +- Clears bash/shell history after deployment +- Disables persistent command history for system users +- Clears temporary files and caches +- Sets up automatic history clearing on user logout + +### 3. VPN Log Filtering +- Filters out VPN connection logs from rsyslog +- Excludes WireGuard and StrongSwan messages from persistent storage +- Filters kernel messages related to VPN traffic +- Optional filtering of authentication logs (use with caution) + +### 4. Automatic Cleanup +- Daily/weekly/monthly cleanup of old logs and temporary files +- Package cache cleaning +- Configurable retention policies +- Optional shutdown cleanup for extreme privacy + +### 5. Advanced Privacy Settings +- Reduced kernel log verbosity +- Disabled successful SSH connection logging (optional) +- Volatile systemd journal storage +- Privacy monitoring script + +## Configuration + +All privacy settings are configured in `config.cfg` under the "Privacy Enhancements" section: + +```yaml +# Enable/disable all privacy enhancements +privacy_enhancements_enabled: true + +# Log rotation settings +privacy_log_rotation: + max_age: 7 # Days to keep logs + max_size: 10 # Max size per log file (MB) + rotate_count: 3 # Number of rotated files to keep + compress: true # Compress rotated logs + daily_rotation: true # Force daily rotation + +# History clearing +privacy_history_clearing: + clear_bash_history: true + clear_system_history: true + disable_service_history: true + +# Log filtering +privacy_log_filtering: + exclude_vpn_logs: true + exclude_auth_logs: false # Use with caution + filter_kernel_vpn_logs: true + +# Automatic cleanup +privacy_auto_cleanup: + enabled: true + frequency: "daily" # daily, weekly, monthly + temp_files_max_age: 1 + clean_package_cache: true + +# Advanced settings +privacy_advanced: + disable_ssh_success_logs: false + reduce_kernel_verbosity: true + clear_logs_on_shutdown: false # Extreme measure +``` + +## Security Considerations + +### Safe Settings (Default) +- `exclude_vpn_logs: true` - Safe, only filters VPN-specific messages +- `clear_bash_history: true` - Safe, improves privacy without affecting security +- `reduce_kernel_verbosity: true` - Safe, reduces noise in logs + +### Use With Caution +- `exclude_auth_logs: true` - Reduces security logging, makes incident investigation harder +- `disable_ssh_success_logs: true` - Removes audit trail for successful connections +- `clear_logs_on_shutdown: true` - Extreme measure, makes debugging very difficult + +## Files Created + +### Configuration Files +- `/etc/logrotate.d/99-privacy-enhanced` - Main log rotation config +- `/etc/logrotate.d/99-auth-privacy` - Auth log rotation +- `/etc/logrotate.d/99-kern-privacy` - Kernel log rotation +- `/etc/rsyslog.d/49-privacy-vpn-filter.conf` - VPN log filtering +- `/etc/rsyslog.d/48-privacy-kernel-filter.conf` - Kernel log filtering +- `/etc/rsyslog.d/47-privacy-auth-filter.conf` - Auth log filtering (optional) +- `/etc/rsyslog.d/46-privacy-ssh-filter.conf` - SSH log filtering (optional) +- `/etc/rsyslog.d/45-privacy-minimal.conf` - Minimal logging config + +### Scripts +- `/usr/local/bin/privacy-auto-cleanup.sh` - Automatic cleanup script +- `/usr/local/bin/privacy-log-cleanup.sh` - Initial log cleanup +- `/usr/local/bin/privacy-monitor.sh` - Privacy status monitoring +- `/etc/bash.bash_logout` - History clearing on logout + +### Systemd Services +- `/etc/systemd/system/privacy-shutdown-cleanup.service` - Shutdown cleanup (optional) + +## Usage + +### Enable Privacy Enhancements +Privacy enhancements are enabled by default. To disable them: + +```yaml +privacy_enhancements_enabled: false +``` + +### Run Specific Privacy Tasks +You can run specific privacy components using tags: + +```bash +# Run only log rotation setup +ansible-playbook server.yml --tags privacy-logs + +# Run only history clearing +ansible-playbook server.yml --tags privacy-history + +# Run only log filtering +ansible-playbook server.yml --tags privacy-filtering + +# Run only cleanup tasks +ansible-playbook server.yml --tags privacy-cleanup + +# Run all privacy enhancements +ansible-playbook server.yml --tags privacy +``` + +### Monitor Privacy Status +Check the status of privacy enhancements: + +```bash +sudo /usr/local/bin/privacy-monitor.sh +``` + +### Manual Cleanup +Run manual cleanup: + +```bash +sudo /usr/local/bin/privacy-auto-cleanup.sh +``` + +## Debugging + +If you need to debug VPN issues, temporarily disable privacy enhancements: + +1. Set `privacy_enhancements_enabled: false` in `config.cfg` +2. Re-run the deployment: `./algo` +3. Debug your issues with full logging +4. Re-enable privacy enhancements when done + +Alternatively, disable specific features: +- Set `exclude_vpn_logs: false` to see VPN connection logs +- Set `reduce_kernel_verbosity: false` for full kernel logging +- Check `/var/log/privacy-cleanup.log` for cleanup operation logs + +## Impact on System + +### Positive Effects +- Improved user privacy +- Reduced disk usage from logs +- Faster log searches +- Reduced attack surface + +### Potential Drawbacks +- Limited debugging information +- Shorter audit trail +- May complicate troubleshooting +- Could hide security incidents + +## Compatibility + +- **Ubuntu 22.04**: Fully supported +- **FreeBSD**: Limited support (log rotation and history clearing only) +- **Other distributions**: May require adaptation + +## Best Practices + +1. **Start Conservative**: Use default settings initially +2. **Test Thoroughly**: Verify VPN functionality after enabling privacy features +3. **Monitor Logs**: Check that essential security logs are still being captured +4. **Document Changes**: Keep track of privacy settings for troubleshooting +5. **Regular Reviews**: Periodically review privacy settings and their effectiveness + +## Privacy vs. Security Balance + +This role aims to balance privacy with security by: +- Keeping security-critical logs (authentication failures, system errors) +- Filtering only VPN-specific operational logs +- Providing granular control over what gets filtered +- Maintaining essential audit trails while reducing VPN usage traces + +For maximum privacy, consider running your own log analysis before enabling aggressive filtering options. \ No newline at end of file diff --git a/roles/privacy/defaults/main.yml b/roles/privacy/defaults/main.yml new file mode 100644 index 000000000..b96119c40 --- /dev/null +++ b/roles/privacy/defaults/main.yml @@ -0,0 +1,57 @@ +--- +# Privacy enhancement configuration defaults +# These settings can be overridden in config.cfg + +# Enable privacy enhancements (disabled for debugging when false) +privacy_enhancements_enabled: true + +# Log rotation settings +privacy_log_rotation: + # Maximum age for system logs in days + max_age: 7 + # Maximum size for individual log files in MB + max_size: 10 + # Number of rotated files to keep + rotate_count: 3 + # Compress rotated logs + compress: true + # Force daily rotation regardless of size + daily_rotation: true + +# History clearing settings +privacy_history_clearing: + # Clear bash history after deployment + clear_bash_history: true + # Clear system command history + clear_system_history: true + # Disable bash history persistence for service users + disable_service_history: true + +# Log filtering settings +privacy_log_filtering: + # Exclude VPN connection logs from persistent storage + exclude_vpn_logs: true + # Exclude authentication logs (be careful with this) + exclude_auth_logs: false + # Filter kernel logs related to VPN traffic + filter_kernel_vpn_logs: true + +# Automatic cleanup settings +privacy_auto_cleanup: + # Enable automatic log cleanup + enabled: true + # Cleanup frequency (daily, weekly, monthly) + frequency: "daily" + # Clean up temporary files older than N days + temp_files_max_age: 1 + # Clean up old package cache + clean_package_cache: true + +# Advanced privacy settings +privacy_advanced: + # Disable logging of successful SSH connections + disable_ssh_success_logs: false + # Reduce kernel log verbosity + reduce_kernel_verbosity: true + # Clear logs on shutdown (use with caution) + clear_logs_on_shutdown: false diff --git a/roles/privacy/handlers/main.yml b/roles/privacy/handlers/main.yml new file mode 100644 index 000000000..6de5993db --- /dev/null +++ b/roles/privacy/handlers/main.yml @@ -0,0 +1,29 @@ +--- +# Privacy role handlers +# These handlers are triggered by privacy configuration changes + +- name: restart rsyslog + systemd: + name: rsyslog + state: restarted + daemon_reload: yes + become: yes + +- name: restart systemd-journald + systemd: + name: systemd-journald + state: restarted + daemon_reload: yes + become: yes + +- name: reload systemd + systemd: + daemon_reload: yes + become: yes + +- name: enable privacy shutdown cleanup + systemd: + name: privacy-shutdown-cleanup.service + enabled: yes + daemon_reload: yes + become: yes diff --git a/roles/privacy/tasks/advanced_privacy.yml b/roles/privacy/tasks/advanced_privacy.yml new file mode 100644 index 000000000..65b442ad4 --- /dev/null +++ b/roles/privacy/tasks/advanced_privacy.yml @@ -0,0 +1,83 @@ +--- +# Advanced privacy settings for enhanced anonymity + +- name: Reduce kernel log verbosity for privacy + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + state: present + reload: yes + loop: + - { name: 'kernel.printk', value: '3 4 1 3' } + - { name: 'kernel.dmesg_restrict', value: '1' } + - { name: 'net.core.bpf_jit_enable', value: '0' } + when: privacy_advanced.reduce_kernel_verbosity | bool + +- name: Configure kernel parameters for privacy + lineinfile: + path: /etc/sysctl.d/99-privacy.conf + line: "{{ item }}" + create: yes + mode: '0644' + loop: + - "# Privacy enhancements - reduce kernel logging" + - "kernel.printk = 3 4 1 3" + - "kernel.dmesg_restrict = 1" + - "# Disable BPF JIT to reduce attack surface" + - "net.core.bpf_jit_enable = 0" + when: privacy_advanced.reduce_kernel_verbosity | bool + +- name: Configure journal settings for privacy + lineinfile: + path: /etc/systemd/journald.conf + regexp: "^#?{{ item.key }}=" + line: "{{ item.key }}={{ item.value }}" + backup: yes + loop: + - { key: 'MaxRetentionSec', value: '{{ privacy_log_rotation.max_age * 24 * 3600 }}' } + - { key: 'MaxFileSec', value: '1day' } + - { key: 'SystemMaxUse', value: '100M' } + - { key: 'SystemMaxFileSize', value: '{{ privacy_log_rotation.max_size }}M' } + - { key: 'ForwardToSyslog', value: 'no' } + notify: restart systemd-journald + +- name: Disable persistent systemd journal + file: + path: /var/log/journal + state: absent + when: privacy_advanced.reduce_kernel_verbosity | bool + +- name: Create journal configuration for volatile storage only + lineinfile: + path: /etc/systemd/journald.conf + regexp: "^#?Storage=" + line: "Storage=volatile" + backup: yes + notify: restart systemd-journald + +- name: Configure rsyslog for minimal logging + template: + src: privacy-rsyslog.conf.j2 + dest: /etc/rsyslog.d/45-privacy-minimal.conf + mode: '0644' + owner: root + group: root + notify: restart rsyslog + +- name: Set up privacy monitoring script + template: + src: privacy-monitor.sh.j2 + dest: /usr/local/bin/privacy-monitor.sh + mode: '0755' + owner: root + group: root + +- name: Display privacy configuration summary + debug: + msg: + - "Privacy enhancements applied:" + - " - Log retention: {{ privacy_log_rotation.max_age }} days" + - " - VPN log filtering: {{ privacy_log_filtering.exclude_vpn_logs | bool }}" + - " - History clearing: {{ privacy_history_clearing.clear_bash_history | bool }}" + - " - Auto cleanup: {{ privacy_auto_cleanup.enabled | bool }}" + - " - Kernel verbosity reduction: {{ privacy_advanced.reduce_kernel_verbosity | bool }}" diff --git a/roles/privacy/tasks/auto_cleanup.yml b/roles/privacy/tasks/auto_cleanup.yml new file mode 100644 index 000000000..7fa1436a7 --- /dev/null +++ b/roles/privacy/tasks/auto_cleanup.yml @@ -0,0 +1,70 @@ +--- +# Automatic cleanup tasks for enhanced privacy + +- name: Create privacy cleanup script + template: + src: privacy-auto-cleanup.sh.j2 + dest: /usr/local/bin/privacy-auto-cleanup.sh + mode: '0755' + owner: root + group: root + +- name: Set up automatic privacy cleanup cron job + cron: + name: "Privacy auto cleanup" + job: "/usr/local/bin/privacy-auto-cleanup.sh" + minute: "30" + hour: "2" + user: root + state: "{{ 'present' if privacy_auto_cleanup.enabled else 'absent' }}" + when: privacy_auto_cleanup.frequency == 'daily' + +- name: Set up weekly privacy cleanup cron job + cron: + name: "Privacy auto cleanup weekly" + job: "/usr/local/bin/privacy-auto-cleanup.sh" + minute: "30" + hour: "2" + weekday: "0" + user: root + state: "{{ 'present' if privacy_auto_cleanup.enabled else 'absent' }}" + when: privacy_auto_cleanup.frequency == 'weekly' + +- name: Set up monthly privacy cleanup cron job + cron: + name: "Privacy auto cleanup monthly" + job: "/usr/local/bin/privacy-auto-cleanup.sh" + minute: "30" + hour: "2" + day: "1" + user: root + state: "{{ 'present' if privacy_auto_cleanup.enabled else 'absent' }}" + when: privacy_auto_cleanup.frequency == 'monthly' + +- name: Create systemd service for privacy cleanup on shutdown + template: + src: privacy-shutdown-cleanup.service.j2 + dest: /etc/systemd/system/privacy-shutdown-cleanup.service + mode: '0644' + owner: root + group: root + when: privacy_advanced.clear_logs_on_shutdown | bool + notify: + - reload systemd + - enable privacy shutdown cleanup + +- name: Clean up temporary files immediately + shell: | + find /tmp -type f -mtime +{{ privacy_auto_cleanup.temp_files_max_age }} -delete + find /var/tmp -type f -mtime +{{ privacy_auto_cleanup.temp_files_max_age }} -delete + changed_when: false + when: privacy_auto_cleanup.enabled | bool + +- name: Clean package cache immediately + shell: | + apt-get clean + apt-get autoclean + changed_when: false + when: + - privacy_auto_cleanup.enabled | bool + - privacy_auto_cleanup.clean_package_cache | bool diff --git a/roles/privacy/tasks/clear_history.yml b/roles/privacy/tasks/clear_history.yml new file mode 100644 index 000000000..35cc9211e --- /dev/null +++ b/roles/privacy/tasks/clear_history.yml @@ -0,0 +1,61 @@ +--- +# Clear command history and disable persistent history for privacy + +- name: Clear bash history for all users + shell: | + for user_home in /home/* /root; do + if [ -d "$user_home" ]; then + rm -f "$user_home/.bash_history" + rm -f "$user_home/.zsh_history" + rm -f "$user_home/.sh_history" + fi + done + when: privacy_history_clearing.clear_bash_history | bool + changed_when: false + +- name: Clear system command history logs + file: + path: "{{ item }}" + state: absent + loop: + - /var/log/lastlog + - /var/log/wtmp.1 + - /var/log/btmp.1 + - /tmp/.X* + - /tmp/.font-unix + - /tmp/.ICE-unix + when: privacy_history_clearing.clear_system_history | bool + ignore_errors: true + +- name: Configure bash to not save history for service users + lineinfile: + path: "{{ item }}/.bashrc" + line: "{{ history_disable_line }}" + create: true + mode: '0644' + loop: + - /root + - /home/ubuntu + vars: + history_disable_line: | + # Privacy enhancement: disable bash history + export HISTFILE=/dev/null + export HISTSIZE=0 + export HISTFILESIZE=0 + unset HISTFILE + when: privacy_history_clearing.disable_service_history | bool + ignore_errors: true + +- name: Create history clearing script for logout + template: + src: clear-history-on-logout.sh.j2 + dest: /etc/bash.bash_logout + mode: '0644' + owner: root + group: root + when: privacy_history_clearing.clear_bash_history | bool + +- name: Clear current session history + shell: history -c + changed_when: false + when: privacy_history_clearing.clear_bash_history | bool diff --git a/roles/privacy/tasks/log_filtering.yml b/roles/privacy/tasks/log_filtering.yml new file mode 100644 index 000000000..8a3f73563 --- /dev/null +++ b/roles/privacy/tasks/log_filtering.yml @@ -0,0 +1,61 @@ +--- +# Configure rsyslog to filter out VPN-related logs for privacy + +- name: Create rsyslog privacy configuration directory + file: + path: /etc/rsyslog.d + state: directory + mode: '0755' + owner: root + group: root + +- name: Configure rsyslog to exclude VPN-related logs + template: + src: 49-privacy-vpn-filter.conf.j2 + dest: /etc/rsyslog.d/49-privacy-vpn-filter.conf + mode: '0644' + owner: root + group: root + notify: restart rsyslog + when: privacy_log_filtering.exclude_vpn_logs | bool + +- name: Configure rsyslog to filter kernel VPN logs + template: + src: 48-privacy-kernel-filter.conf.j2 + dest: /etc/rsyslog.d/48-privacy-kernel-filter.conf + mode: '0644' + owner: root + group: root + notify: restart rsyslog + when: privacy_log_filtering.filter_kernel_vpn_logs | bool + +- name: Configure rsyslog to exclude detailed auth logs (optional) + template: + src: 47-privacy-auth-filter.conf.j2 + dest: /etc/rsyslog.d/47-privacy-auth-filter.conf + mode: '0644' + owner: root + group: root + notify: restart rsyslog + when: privacy_log_filtering.exclude_auth_logs | bool + +- name: Create rsyslog privacy filter for SSH success logs + template: + src: 46-privacy-ssh-filter.conf.j2 + dest: /etc/rsyslog.d/46-privacy-ssh-filter.conf + mode: '0644' + owner: root + group: root + notify: restart rsyslog + when: privacy_advanced.disable_ssh_success_logs | bool + +- name: Test rsyslog configuration + command: rsyslogd -N1 + register: rsyslog_test + changed_when: false + failed_when: rsyslog_test.rc != 0 + +- name: Display rsyslog test results + debug: + msg: "Rsyslog configuration test passed" + when: rsyslog_test.rc == 0 diff --git a/roles/privacy/tasks/log_rotation.yml b/roles/privacy/tasks/log_rotation.yml new file mode 100644 index 000000000..bf39de030 --- /dev/null +++ b/roles/privacy/tasks/log_rotation.yml @@ -0,0 +1,51 @@ +--- +# Aggressive log rotation configuration for privacy +# Reduces log retention time and implements more frequent rotation + +- name: Configure aggressive logrotate for system logs + template: + src: privacy-logrotate.j2 + dest: /etc/logrotate.d/99-privacy-enhanced + mode: '0644' + owner: root + group: root + notify: restart rsyslog + +- name: Configure logrotate for auth logs with shorter retention + template: + src: auth-logrotate.j2 + dest: /etc/logrotate.d/99-auth-privacy + mode: '0644' + owner: root + group: root + notify: restart rsyslog + +- name: Configure logrotate for kern logs with VPN filtering + template: + src: kern-logrotate.j2 + dest: /etc/logrotate.d/99-kern-privacy + mode: '0644' + owner: root + group: root + notify: restart rsyslog + +- name: Set more frequent logrotate execution + cron: + name: "Enhanced privacy log rotation" + job: "/usr/sbin/logrotate /etc/logrotate.conf" + minute: "0" + hour: "*/6" + user: root + state: present + +- name: Create privacy log cleanup script + template: + src: privacy-log-cleanup.sh.j2 + dest: /usr/local/bin/privacy-log-cleanup.sh + mode: '0755' + owner: root + group: root + +- name: Force immediate log rotation to apply new settings + command: /usr/sbin/logrotate -f /etc/logrotate.conf + changed_when: false diff --git a/roles/privacy/tasks/main.yml b/roles/privacy/tasks/main.yml new file mode 100644 index 000000000..aad22ac88 --- /dev/null +++ b/roles/privacy/tasks/main.yml @@ -0,0 +1,36 @@ +--- +# Privacy enhancements for Algo VPN +# This role implements additional privacy measures to reduce log retention +# and minimize traces of VPN usage on the server + +- name: Display privacy enhancements status + debug: + msg: "Privacy enhancements are {{ 'enabled' if privacy_enhancements_enabled else 'disabled' }}" + +- name: Privacy enhancements block + block: + - name: Include log rotation tasks + include_tasks: log_rotation.yml + tags: privacy-logs + + - name: Include history clearing tasks + include_tasks: clear_history.yml + tags: privacy-history + + - name: Include log filtering tasks + include_tasks: log_filtering.yml + tags: privacy-filtering + + - name: Include automatic cleanup tasks + include_tasks: auto_cleanup.yml + tags: privacy-cleanup + + - name: Include advanced privacy tasks + include_tasks: advanced_privacy.yml + tags: privacy-advanced + + - name: Display privacy enhancements completion + debug: + msg: "Privacy enhancements have been successfully applied" + + when: privacy_enhancements_enabled | bool diff --git a/roles/privacy/templates/46-privacy-ssh-filter.conf.j2 b/roles/privacy/templates/46-privacy-ssh-filter.conf.j2 new file mode 100644 index 000000000..dca38ff66 --- /dev/null +++ b/roles/privacy/templates/46-privacy-ssh-filter.conf.j2 @@ -0,0 +1,15 @@ +# Privacy-enhanced SSH log filtering +# Filters successful SSH connections while keeping failures for security +# Generated by Algo VPN privacy role + +{% if privacy_advanced.disable_ssh_success_logs %} +# Filter successful SSH connections (keep failures for security monitoring) +:msg, contains, "sshd.*Accepted" stop +:msg, contains, "sshd.*session opened" stop +:msg, contains, "sshd.*session closed" stop + +# Filter SSH key-based authentication success +:msg, contains, "sshd.*publickey" stop +{% endif %} + +# Continue processing SSH failure messages and other logs \ No newline at end of file diff --git a/roles/privacy/templates/47-privacy-auth-filter.conf.j2 b/roles/privacy/templates/47-privacy-auth-filter.conf.j2 new file mode 100644 index 000000000..86907c86c --- /dev/null +++ b/roles/privacy/templates/47-privacy-auth-filter.conf.j2 @@ -0,0 +1,19 @@ +# Privacy-enhanced authentication log filtering +# WARNING: Use with caution - this reduces security logging +# Only enable if you understand the security implications +# Generated by Algo VPN privacy role + +{% if privacy_log_filtering.exclude_auth_logs %} +# Filter successful authentication messages (reduces audit trail) +:msg, contains, "authentication success" stop +:msg, contains, "session opened" stop +:msg, contains, "session closed" stop + +# Filter sudo success messages (keep failures for security) +:msg, regex, "sudo.*COMMAND" stop + +# Filter cron messages +:msg, contains, "CRON" stop +{% endif %} + +# Continue processing other auth messages \ No newline at end of file diff --git a/roles/privacy/templates/48-privacy-kernel-filter.conf.j2 b/roles/privacy/templates/48-privacy-kernel-filter.conf.j2 new file mode 100644 index 000000000..cb35fbd75 --- /dev/null +++ b/roles/privacy/templates/48-privacy-kernel-filter.conf.j2 @@ -0,0 +1,21 @@ +# Privacy-enhanced kernel log filtering +# Filters kernel messages that may reveal VPN usage patterns +# Generated by Algo VPN privacy role + +{% if privacy_log_filtering.filter_kernel_vpn_logs %} +# Filter iptables/netfilter messages related to VPN +:msg, contains, "iptables" stop +:msg, contains, "netfilter" stop + +# Filter connection tracking messages +:msg, contains, "nf_conntrack" stop + +# Filter network interface up/down messages for VPN interfaces +:msg, regex, "wg[0-9]+.*link" stop +:msg, regex, "ipsec[0-9]+.*link" stop + +# Filter routing table changes +:msg, contains, "rtnetlink" stop +{% endif %} + +# Continue processing non-filtered messages \ No newline at end of file diff --git a/roles/privacy/templates/49-privacy-vpn-filter.conf.j2 b/roles/privacy/templates/49-privacy-vpn-filter.conf.j2 new file mode 100644 index 000000000..6ff6da70e --- /dev/null +++ b/roles/privacy/templates/49-privacy-vpn-filter.conf.j2 @@ -0,0 +1,34 @@ +# Privacy-enhanced rsyslog configuration +# Filters VPN-related log entries for enhanced privacy +# Generated by Algo VPN privacy role + +# Stop processing VPN-related messages to prevent them from being logged +# This helps maintain user privacy by not storing VPN connection details + +{% if privacy_log_filtering.exclude_vpn_logs %} +# Filter WireGuard messages +:msg, contains, "wireguard" stop + +# Filter StrongSwan/IPsec messages +:msg, contains, "strongswan" stop +:msg, contains, "ipsec" stop +:msg, contains, "charon" stop +:msg, contains, "xl2tpd" stop + +# Filter VPN interface messages +:msg, contains, "wg0" stop +:msg, contains, "ipsec0" stop + +# Filter VPN-related kernel messages +:msg, regex, "IN=wg[0-9]+" stop +:msg, regex, "OUT=wg[0-9]+" stop +{% endif %} + +{% if privacy_log_filtering.filter_kernel_vpn_logs %} +# Filter kernel messages related to VPN traffic +:msg, contains, "netfilter" stop +:msg, regex, "FORWARD.*DPT:(51820|500|4500)" stop +{% endif %} + +# Continue processing other messages +& stop \ No newline at end of file diff --git a/roles/privacy/templates/auth-logrotate.j2 b/roles/privacy/templates/auth-logrotate.j2 new file mode 100644 index 000000000..8de7a094c --- /dev/null +++ b/roles/privacy/templates/auth-logrotate.j2 @@ -0,0 +1,26 @@ +# Privacy-enhanced auth log rotation +# Reduces retention time for authentication logs +# Generated by Algo VPN privacy role + +/var/log/auth.log +{ + # Shorter retention for auth logs (privacy) + rotate 2 + maxage {{ privacy_log_rotation.max_age | int // 2 }} + size {{ privacy_log_rotation.max_size // 2 }}M + + daily + missingok + notifempty + compress + delaycompress + + create 0640 syslog adm + copytruncate + + postrotate + if [ -f /var/run/rsyslogd.pid ]; then + kill -HUP `cat /var/run/rsyslogd.pid` + fi + endscript +} \ No newline at end of file diff --git a/roles/privacy/templates/clear-history-on-logout.sh.j2 b/roles/privacy/templates/clear-history-on-logout.sh.j2 new file mode 100644 index 000000000..0765b78f7 --- /dev/null +++ b/roles/privacy/templates/clear-history-on-logout.sh.j2 @@ -0,0 +1,36 @@ +#!/bin/bash +# Privacy-enhanced history clearing on logout +# This script clears command history when users log out +# Generated by Algo VPN privacy role + +{% if privacy_history_clearing.clear_bash_history %} +# Clear bash history +if [ -f ~/.bash_history ]; then + > ~/.bash_history +fi + +# Clear zsh history +if [ -f ~/.zsh_history ]; then + > ~/.zsh_history +fi + +# Clear current session history +history -c +history -w + +# Clear less history +if [ -f ~/.lesshst ]; then + rm -f ~/.lesshst +fi + +# Clear vim history +if [ -f ~/.viminfo ]; then + rm -f ~/.viminfo +fi +{% endif %} + +{% if privacy_history_clearing.clear_system_history %} +# Clear temporary files in user directory +find ~/tmp -type f -delete 2>/dev/null || true +find ~/.cache -type f -delete 2>/dev/null || true +{% endif %} \ No newline at end of file diff --git a/roles/privacy/templates/kern-logrotate.j2 b/roles/privacy/templates/kern-logrotate.j2 new file mode 100644 index 000000000..a2f44baec --- /dev/null +++ b/roles/privacy/templates/kern-logrotate.j2 @@ -0,0 +1,37 @@ +# Privacy-enhanced kernel log rotation +# Reduces retention time for kernel logs that may contain VPN traces +# Generated by Algo VPN privacy role + +/var/log/kern.log +{ + # Aggressive rotation for kernel logs + rotate {{ privacy_log_rotation.rotate_count }} + maxage {{ privacy_log_rotation.max_age }} + size {{ privacy_log_rotation.max_size }}M + + daily + missingok + notifempty + compress + delaycompress + + create 0640 syslog adm + copytruncate + + # Pre-rotation script to filter VPN-related entries + prerotate + # Create filtered version excluding VPN traces + if [ -f /var/log/kern.log ]; then + grep -v -E "(wireguard|ipsec|strongswan|xl2tpd)" /var/log/kern.log > /tmp/kern.log.filtered || true + if [ -s /tmp/kern.log.filtered ]; then + mv /tmp/kern.log.filtered /var/log/kern.log + fi + fi + endscript + + postrotate + if [ -f /var/run/rsyslogd.pid ]; then + kill -HUP `cat /var/run/rsyslogd.pid` + fi + endscript +} \ No newline at end of file diff --git a/roles/privacy/templates/privacy-auto-cleanup.sh.j2 b/roles/privacy/templates/privacy-auto-cleanup.sh.j2 new file mode 100644 index 000000000..695ce2728 --- /dev/null +++ b/roles/privacy/templates/privacy-auto-cleanup.sh.j2 @@ -0,0 +1,75 @@ +#!/bin/bash +# Privacy auto-cleanup script +# Automatically cleans up logs and temporary files for enhanced privacy +# Generated by Algo VPN privacy role + +set -euo pipefail + +# Configuration +LOG_MAX_AGE={{ privacy_auto_cleanup.temp_files_max_age }} +SCRIPT_LOG="/var/log/privacy-cleanup.log" + +# Logging function +log_message() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$SCRIPT_LOG" +} + +log_message "Starting privacy cleanup" + +{% if privacy_auto_cleanup.enabled %} +# Rotate log files to prevent the cleanup log from growing +if [ -f "$SCRIPT_LOG" ] && [ $(wc -l < "$SCRIPT_LOG") -gt 1000 ]; then + tail -n 500 "$SCRIPT_LOG" > "$SCRIPT_LOG.tmp" + mv "$SCRIPT_LOG.tmp" "$SCRIPT_LOG" +fi + +# Clean temporary files +log_message "Cleaning temporary files older than ${LOG_MAX_AGE} days" +find /tmp -type f -mtime +${LOG_MAX_AGE} -delete 2>/dev/null || true +find /var/tmp -type f -mtime +${LOG_MAX_AGE} -delete 2>/dev/null || true + +# Clean old log files that may have escaped rotation +log_message "Cleaning old rotated logs" +find /var/log -name "*.log.*" -type f -mtime +{{ privacy_log_rotation.max_age }} -delete 2>/dev/null || true +find /var/log -name "*.gz" -type f -mtime +{{ privacy_log_rotation.max_age }} -delete 2>/dev/null || true + +# Clean systemd journal if it exists +if [ -d /var/log/journal ]; then + log_message "Cleaning systemd journal files" + journalctl --vacuum-time={{ privacy_log_rotation.max_age }}d 2>/dev/null || true + journalctl --vacuum-size=50M 2>/dev/null || true +fi + +{% if privacy_auto_cleanup.clean_package_cache %} +# Clean package cache +log_message "Cleaning package cache" +apt-get clean 2>/dev/null || true +apt-get autoclean 2>/dev/null || true +{% endif %} + +# Clean bash history files +log_message "Cleaning bash history files" +for user_home in /home/* /root; do + if [ -d "$user_home" ]; then + rm -f "$user_home/.bash_history" 2>/dev/null || true + rm -f "$user_home/.zsh_history" 2>/dev/null || true + rm -f "$user_home/.lesshst" 2>/dev/null || true + rm -f "$user_home/.viminfo" 2>/dev/null || true + fi +done + +# Clean core dumps +log_message "Cleaning core dumps" +find /var/crash -type f -name "*.crash" -mtime +1 -delete 2>/dev/null || true + +# Force log rotation +log_message "Forcing log rotation" +/usr/sbin/logrotate -f /etc/logrotate.conf 2>/dev/null || true + +log_message "Privacy cleanup completed successfully" +{% else %} +log_message "Privacy cleanup is disabled" +{% endif %} + +# Clean up old privacy cleanup logs +find /var/log -name "privacy-cleanup.log.*" -type f -mtime +7 -delete 2>/dev/null || true \ No newline at end of file diff --git a/roles/privacy/templates/privacy-log-cleanup.sh.j2 b/roles/privacy/templates/privacy-log-cleanup.sh.j2 new file mode 100644 index 000000000..7b6af7007 --- /dev/null +++ b/roles/privacy/templates/privacy-log-cleanup.sh.j2 @@ -0,0 +1,22 @@ +#!/bin/bash +# Privacy log cleanup script +# Immediately cleans up existing logs and applies privacy settings +# Generated by Algo VPN privacy role + +set -euo pipefail + +echo "Starting privacy log cleanup..." + +# Truncate existing log files to apply new rotation settings immediately +find /var/log -type f -name "*.log" -size +{{ privacy_log_rotation.max_size }}M -exec truncate -s {{ privacy_log_rotation.max_size }}M {} \; 2>/dev/null || true + +# Remove old rotated logs that exceed our retention policy +find /var/log -type f \( -name "*.log.*" -o -name "*.gz" \) -mtime +{{ privacy_log_rotation.max_age }} -delete 2>/dev/null || true + +# Clean up systemd journal to respect new settings +if [ -d /var/log/journal ]; then + journalctl --vacuum-time={{ privacy_log_rotation.max_age }}d 2>/dev/null || true + journalctl --vacuum-size={{ privacy_log_rotation.max_size * 10 }}M 2>/dev/null || true +fi + +echo "Privacy log cleanup completed" \ No newline at end of file diff --git a/roles/privacy/templates/privacy-logrotate.j2 b/roles/privacy/templates/privacy-logrotate.j2 new file mode 100644 index 000000000..7c8a1a7c4 --- /dev/null +++ b/roles/privacy/templates/privacy-logrotate.j2 @@ -0,0 +1,47 @@ +# Privacy-enhanced logrotate configuration +# This configuration enforces aggressive log rotation for privacy +# Generated by Algo VPN privacy role + +/var/log/syslog +/var/log/messages +/var/log/daemon.log +/var/log/debug +/var/log/user.log +{ + # Rotate {{ privacy_log_rotation.rotate_count }} times before deletion + rotate {{ privacy_log_rotation.rotate_count }} + + # Maximum age in days + maxage {{ privacy_log_rotation.max_age }} + + # Maximum size per file + size {{ privacy_log_rotation.max_size }}M + + {% if privacy_log_rotation.daily_rotation %} + # Force daily rotation + daily + {% endif %} + + {% if privacy_log_rotation.compress %} + # Compress rotated files + compress + delaycompress + {% endif %} + + # Don't rotate if empty + notifempty + + # Create new files with specific permissions + create 0640 syslog adm + + # Truncate original file after rotation + copytruncate + + # Execute after rotation + postrotate + # Send SIGHUP to rsyslog + if [ -f /var/run/rsyslogd.pid ]; then + kill -HUP `cat /var/run/rsyslogd.pid` + fi + endscript +} \ No newline at end of file diff --git a/roles/privacy/templates/privacy-monitor.sh.j2 b/roles/privacy/templates/privacy-monitor.sh.j2 new file mode 100644 index 000000000..dfe71dd7c --- /dev/null +++ b/roles/privacy/templates/privacy-monitor.sh.j2 @@ -0,0 +1,85 @@ +#!/bin/bash +# Privacy monitoring script +# Monitors and reports on privacy settings status +# Generated by Algo VPN privacy role + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}Algo VPN Privacy Status Monitor${NC}" +echo "========================================" + +# Check log rotation settings +echo -e "\n${YELLOW}Log Rotation Status:${NC}" +if [ -f /etc/logrotate.d/99-privacy-enhanced ]; then + echo -e " ${GREEN}✓${NC} Privacy log rotation configured" +else + echo -e " ${RED}✗${NC} Privacy log rotation not found" +fi + +# Check rsyslog filtering +echo -e "\n${YELLOW}Log Filtering Status:${NC}" +if [ -f /etc/rsyslog.d/49-privacy-vpn-filter.conf ]; then + echo -e " ${GREEN}✓${NC} VPN log filtering enabled" +else + echo -e " ${RED}✗${NC} VPN log filtering not configured" +fi + +# Check history clearing +echo -e "\n${YELLOW}History Clearing Status:${NC}" +if [ -f /etc/bash.bash_logout ]; then + echo -e " ${GREEN}✓${NC} Logout history clearing configured" +else + echo -e " ${RED}✗${NC} Logout history clearing not configured" +fi + +# Check auto cleanup +echo -e "\n${YELLOW}Auto Cleanup Status:${NC}" +if [ -f /usr/local/bin/privacy-auto-cleanup.sh ]; then + echo -e " ${GREEN}✓${NC} Auto cleanup script installed" + if crontab -l | grep -q "privacy-auto-cleanup"; then + echo -e " ${GREEN}✓${NC} Auto cleanup scheduled" + else + echo -e " ${YELLOW}!${NC} Auto cleanup script exists but not scheduled" + fi +else + echo -e " ${RED}✗${NC} Auto cleanup not configured" +fi + +# Check current log sizes +echo -e "\n${YELLOW}Current Log Status:${NC}" +total_log_size=$(du -sh /var/log 2>/dev/null | cut -f1 || echo "Unknown") +echo " Total log directory size: $total_log_size" + +if [ -f /var/log/auth.log ]; then + auth_size=$(du -h /var/log/auth.log | cut -f1) + echo " Auth log size: $auth_size" +fi + +if [ -f /var/log/syslog ]; then + syslog_size=$(du -h /var/log/syslog | cut -f1) + echo " Syslog size: $syslog_size" +fi + +# Check systemd journal status +echo -e "\n${YELLOW}Journal Status:${NC}" +if [ -d /var/log/journal ]; then + journal_size=$(du -sh /var/log/journal 2>/dev/null | cut -f1 || echo "Unknown") + echo " Journal size: $journal_size" +else + echo -e " ${GREEN}✓${NC} Persistent journal disabled (using volatile storage)" +fi + +# Privacy configuration summary +echo -e "\n${YELLOW}Privacy Configuration Summary:${NC}" +echo " Log retention: {{ privacy_log_rotation.max_age }} days" +echo " Max log size: {{ privacy_log_rotation.max_size }}MB" +echo " VPN log filtering: {{ privacy_log_filtering.exclude_vpn_logs }}" +echo -e " History clearing: {{ privacy_history_clearing.clear_bash_history }}" + +echo -e "\n${GREEN}Privacy monitoring complete${NC}" \ No newline at end of file diff --git a/roles/privacy/templates/privacy-rsyslog.conf.j2 b/roles/privacy/templates/privacy-rsyslog.conf.j2 new file mode 100644 index 000000000..088d5eb5f --- /dev/null +++ b/roles/privacy/templates/privacy-rsyslog.conf.j2 @@ -0,0 +1,32 @@ +# Privacy-enhanced rsyslog configuration +# Minimal logging configuration for enhanced privacy +# Generated by Algo VPN privacy role + +# Global settings for privacy +$ModLoad imuxsock # provides support for local system logging +$ModLoad imklog # provides kernel logging support + +# Reduce logging verbosity +$KLogPermitNonKernelFacility on +$SystemLogSocketName /run/systemd/journal/syslog + +# Privacy-enhanced rules +{% if privacy_advanced.reduce_kernel_verbosity %} +# Reduce kernel message verbosity +kern.info;kern.!debug /var/log/kern.log +{% else %} +kern.* /var/log/kern.log +{% endif %} + +# Essential system messages only +*.emerg :omusrmsg:* +*.alert /var/log/alert.log +*.crit /var/log/critical.log +*.err /var/log/error.log + +# Compress and limit emergency logs +$template PrivacyTemplate,"%timegenerated% %hostname% %syslogtag%%msg%\n" +$ActionFileDefaultTemplate PrivacyTemplate + +# Stop processing after essential logs to prevent detailed logging +& stop \ No newline at end of file diff --git a/roles/privacy/templates/privacy-shutdown-cleanup.service.j2 b/roles/privacy/templates/privacy-shutdown-cleanup.service.j2 new file mode 100644 index 000000000..9d05b34be --- /dev/null +++ b/roles/privacy/templates/privacy-shutdown-cleanup.service.j2 @@ -0,0 +1,44 @@ +# Privacy shutdown cleanup systemd service +# Clears logs and sensitive data on system shutdown +# Generated by Algo VPN privacy role + +[Unit] +Description=Privacy Cleanup on Shutdown +DefaultDependencies=false +Before=shutdown.target reboot.target halt.target +Requires=-.mount + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStart=/bin/true +ExecStop=/bin/bash -c ' + # Clear all logs + find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true; + + # Clear rotated logs + find /var/log -type f \( -name "*.log.*" -o -name "*.gz" \) -delete 2>/dev/null || true; + + # Clear systemd journal + if [ -d /var/log/journal ]; then + rm -rf /var/log/journal/* 2>/dev/null || true; + fi; + + # Clear bash history + for user_home in /home/* /root; do + if [ -d "$user_home" ]; then + rm -f "$user_home"/.bash_history 2>/dev/null || true; + rm -f "$user_home"/.zsh_history 2>/dev/null || true; + fi; + done; + + # Clear temporary files + rm -rf /tmp/* /var/tmp/* 2>/dev/null || true; + + # Sync to ensure changes are written + sync; +' +TimeoutStopSec=30 + +[Install] +WantedBy=shutdown.target \ No newline at end of file diff --git a/roles/strongswan/tasks/openssl.yml b/roles/strongswan/tasks/openssl.yml index e64ccdc68..170c6e61c 100644 --- a/roles/strongswan/tasks/openssl.yml +++ b/roles/strongswan/tasks/openssl.yml @@ -36,6 +36,7 @@ type: ECC curve: secp384r1 mode: "0600" + no_log: true # CA certificate with name constraints to prevent certificate misuse (Issue #75) - name: Create certificate signing request (CSR) for CA certificate with security constraints @@ -91,6 +92,7 @@ privatekey_passphrase: "{{ CA_password }}" provider: selfsigned mode: "0644" + no_log: true - name: Copy the CA certificate copy: @@ -164,6 +166,7 @@ ownca_not_after: "+{{ certificate_validity_days }}d" ownca_not_before: "-1d" mode: "0644" + no_log: true - name: Sign client certificates with CA community.crypto.x509_certificate: @@ -178,6 +181,7 @@ mode: "0644" with_items: "{{ client_csr_jobs.results }}" register: client_sign_results + no_log: true - name: Generate p12 files community.crypto.openssl_pkcs12: @@ -189,6 +193,7 @@ mode: "0600" encryption_level: "compatibility2022" # Apple device compatibility with_items: "{{ users }}" + no_log: true - name: Generate p12 files with CA certificate included community.crypto.openssl_pkcs12: @@ -202,6 +207,7 @@ mode: "0600" encryption_level: "compatibility2022" # Apple device compatibility with_items: "{{ users }}" + no_log: true - name: Copy the p12 certificates copy: @@ -255,6 +261,7 @@ issuer: CN: "{{ IP_subject_alt_name }}" revoked_certificates: "{{ revoked_certificates }}" + no_log: true - name: Set CRL file permissions file: diff --git a/roles/wireguard/tasks/keys.yml b/roles/wireguard/tasks/keys.yml index 3c37d8876..0f7aa23f7 100644 --- a/roles/wireguard/tasks/keys.yml +++ b/roles/wireguard/tasks/keys.yml @@ -17,6 +17,7 @@ with_items: - "{{ users }}" - "{{ IP_subject_alt_name }}" + no_log: true - name: Generate raw preshared keys community.crypto.openssl_privatekey: @@ -36,6 +37,7 @@ with_items: - "{{ users }}" - "{{ IP_subject_alt_name }}" + no_log: true - name: Generate public keys x25519_pubkey: @@ -44,3 +46,4 @@ with_items: - "{{ users }}" - "{{ IP_subject_alt_name }}" + no_log: true diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml index 31b35638f..b63fe1c0d 100644 --- a/roles/wireguard/tasks/main.yml +++ b/roles/wireguard/tasks/main.yml @@ -72,6 +72,7 @@ args: chdir: "{{ wireguard_config_path }}" executable: bash + no_log: true become: false delegate_to: localhost diff --git a/server.yml b/server.yml index b33cad283..663ae2f5a 100644 --- a/server.yml +++ b/server.yml @@ -177,6 +177,11 @@ - algo_ssh_tunneling tags: ssh_tunneling + - import_role: + name: privacy + when: privacy_enhancements_enabled | default(true) + tags: privacy + - block: - name: Dump the configuration copy: