Streisand was once the go-to tool for spinning up a multi-protocol VPN server with a single command. It was archived in 2021, and its Ubuntu 16.04 foundation means it no longer works on anything modern. Algo VPN from Trail of Bits fills that gap. It deploys WireGuard and IKEv2 on a fresh server using Ansible, strips out legacy protocols entirely, and generates client configs for every major platform.
This guide walks through deploying Algo VPN on Ubuntu 24.04 using the local installation method, which turns the server itself into a VPN endpoint. Algo also supports cloud provisioning (DigitalOcean, AWS, Azure, GCP, Hetzner, Vultr, and more) if you prefer to deploy from your laptop. We cover the full setup: dependencies, running the installer, verifying both VPN protocols, and connecting clients. If you already run WireGuard manually on Ubuntu, Algo adds IKEv2 and encrypted DNS on top with no extra effort.
Tested April 2026 on Ubuntu 24.04.4 LTS (kernel 6.17), Algo VPN (commit 76ba849), strongSwan 5.9.13, WireGuard tools 1.0.20210914, dnscrypt-proxy 2.0.45
What Algo VPN Deploys
Algo installs and configures the following on the target server:
- WireGuard for fast, modern VPN tunneling (UDP 51820)
- IKEv2 via strongSwan for native OS support on iOS, macOS, Windows, and Linux without third-party apps (UDP 500 + 4500)
- DNSCrypt-proxy for encrypted DNS resolution with optional ad blocking
- iptables firewall locked down to VPN and SSH traffic only
- Privacy hardening including reduced logging, log rotation, and kernel verbosity reduction
It deliberately rejects legacy protocols like L2TP, IKEv1, PPTP, and OpenVPN. If you need OpenVPN specifically, Pritunl is a better choice.
Prerequisites
- A dedicated Ubuntu 24.04 server (cloud instance or bare metal) with root access. Algo modifies firewall rules and DNS settings aggressively, so do not run it on a server hosting other services
- A public IP address (Algo auto-detects it on AWS, DigitalOcean, GCP, Azure, and Hetzner)
- UDP ports 500, 4500, and 51820 open in your cloud provider’s security group or firewall
- Tested on: Ubuntu 24.04.4 LTS (kernel 6.17.0-1010-aws), t3.small instance
Update the System
Start with a fully patched system. Algo’s Ansible playbook expects up-to-date packages.
sudo apt update && sudo apt upgrade -y
Install the base dependencies that Algo needs:
sudo apt install -y git curl jq
Clone the Algo Repository
Clone the latest Algo source from GitHub:
cd /opt
sudo git clone https://github.com/trailofbits/algo.git
cd algo
Confirm the clone by checking the latest commit:
git log --oneline -3
You should see recent commits from the active project:
76ba849 chore(deps): bump cryptography from 46.0.6 to 46.0.7 (#14989)
5b53b85 chore(deps): bump the python group with 3 updates (#14988)
ea34a12 chore(deps): bump the python group with 2 updates (#14987)
Install uv (Python Package Manager)
Algo uses uv, a fast Rust-based Python package manager, to handle its dependencies. Install it:
curl -LsSf https://astral.sh/uv/install.sh | sh
The installer places the binary in ~/.local/bin. Add it to your current session’s PATH:
export PATH="$HOME/.local/bin:$PATH"
Verify the installation:
uv --version
This should print the version number (0.11.x or later).
Install Algo’s Python Dependencies
From inside the /opt/algo directory, let uv resolve and install everything Ansible needs:
cd /opt/algo
uv sync
This creates a .venv virtual environment and installs Ansible, cryptography, and all other dependencies. The process takes about 30 seconds.
Configure VPN Users
Algo generates per-device client configurations. Edit config.cfg to define your VPN users. Each entry represents one device:
sudo vi /opt/algo/config.cfg
Find the users section and adjust the list to match your devices:
users:
- phone
- laptop
- desktop
You can add up to 65,534 users over the lifetime of the server. Other settings worth reviewing in the same file:
dns_encryption: trueenables DNSCrypt (recommended, keeps DNS queries encrypted)BetweenClients_DROP: trueisolates VPN clients from each otherblock_smb: trueandblock_netbios: trueprevent SMB traffic leaksssh_port: 4160sets the SSH port for cloud deployments (does not apply to local installs)
Fix for Ubuntu 24.04: Patch the Crypto Module
Ubuntu 24.04 ships with Python 3.12 and a Rust-backed cryptography library (version 46.x). The community.crypto Ansible collection included with Algo uses a deprecated method to look up elliptic curves, which fails silently with the error “Your cryptography version does not support SECP384R1” even though the library does support it.
Apply this one-line fix before running the deployment:
sudo sed -i 's/cryptography.hazmat.primitives.asymmetric.ec.__dict__.get(self.ectype)/getattr(cryptography.hazmat.primitives.asymmetric.ec, self.ectype, None)/' \
/opt/algo/.venv/lib/python3.12/site-packages/ansible_collections/community/crypto/plugins/module_utils/_crypto/module_backends/privatekey.py
The root cause: the Ansible module uses ec.__dict__.get("SECP384R1") to find the curve class, but in Rust-backed cryptography, module attributes are exposed via getattr() rather than appearing in the module’s __dict__. The fix switches to the standard Python attribute lookup. This has been reported upstream and will likely be resolved in a future community.crypto release.
Deploy Algo VPN
Run the Ansible playbook with the local provider. Replace 10.0.1.50 with your server’s public IP address:
cd /opt/algo
sudo bash -c "export HOME=/root && \
export ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp && \
export ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp && \
export PATH=$HOME/.local/bin:\$PATH && \
uv run ansible-playbook main.yml \
-e provider=local \
-e local_install_confirmed=true \
-e endpoint=10.0.1.50 \
-e server=localhost \
-e ssh_user=root \
-e dns_adblocking=true \
-e ssh_tunneling=true \
--skip-tags debug"
The deployment takes 5 to 10 minutes depending on server specs. Ansible will install WireGuard, strongSwan, dnscrypt-proxy, configure iptables, generate all client certificates, and apply privacy hardening. When it finishes, you should see the congratulations banner:
TASK [debug] *****************************************************
ok: [localhost] => {
"msg": [
[
"# Congratulations! #",
"# Your Algo server is running. #",
"# Config files and certificates are in the ./configs/ directory. #",
"# Go to https://whoer.net/ after connecting #",
"# and ensure that all your traffic passes through the VPN. #",
],
]
}
PLAY RECAP ***************************************************
localhost : ok=197 changed=66 unreachable=0 failed=0
Verify WireGuard is Running
Check the WireGuard interface:
sudo wg show
You should see the wg0 interface with your configured peers:
interface: wg0
public key: eMGgw4TDlXSNnF487GBFd2DI7i4OU+dHGLbObf929zU=
private key: (hidden)
listening port: 51820
peer: KUkbLgInSVO5Hg+l3EULMPXbbjOvxuZhLrvy2AJ28kE=
preshared key: (hidden)
allowed ips: 10.49.0.2/32
peer: 3n1kfbVneoSDZfV5YPSkZ0FrNup9p97sHYfZVXMUtl0=
preshared key: (hidden)
allowed ips: 10.49.0.3/32
peer: ksOuXAyqvAQ5UHKMkQCJ4o8eY/53FnITrVw8HH09xWE=
preshared key: (hidden)
allowed ips: 10.49.0.4/32
Each peer corresponds to one of the users defined in config.cfg (phone, laptop, desktop). Verify the service is enabled for boot persistence:
sudo systemctl status wg-quick@wg0 --no-pager
The service should show active (exited) and enabled.
Verify IKEv2 (strongSwan)
Check the IKEv2 daemon status:
sudo ipsec statusall
Look for the strongSwan version and listening addresses:
Status of IKE charon daemon (strongSwan 5.9.13, Linux 6.17.0-1010-aws, x86_64):
uptime: 9 minutes, since Apr 12 15:59:01 2026
loaded plugins: charon aesni aes rc2 sha2 sha1 md5 mgf1 random nonce x509
revocation constraints pubkey pkcs1 pkcs7 pkcs12 pgp dnskey sshkey pem
openssl pkcs8 fips-prf gmp agent xcbc hmac kdf gcm drbg attr
kernel-netlink resolve socket-default connmark stroke updown
eap-mschapv2 xauth-generic counters
Listening IP addresses:
10.0.1.50
10.49.0.1
Security Associations (0 up, 0 connecting):
none
Zero security associations is expected when no client is currently connected. The important part is the daemon running and listening.
Verify Listening Ports
Confirm all VPN ports are bound:
sudo ss -ulnp | grep -E '51820|500|4500'
You should see six listeners (IPv4 + IPv6 for each port):
UNCONN 0 0 0.0.0.0:4500 0.0.0.0:* users:(("charon",pid=8341,fd=15))
UNCONN 0 0 0.0.0.0:500 0.0.0.0:* users:(("charon",pid=8341,fd=14))
UNCONN 0 0 0.0.0.0:51820 0.0.0.0:*
UNCONN 0 0 [::]:4500 [::]:* users:(("charon",pid=8341,fd=13))
UNCONN 0 0 [::]:500 [::]:* users:(("charon",pid=8341,fd=12))
UNCONN 0 0 [::]:51820 [::]:*
Port 51820 (WireGuard) is handled by the kernel module so it shows no process name. Ports 500 and 4500 belong to the strongSwan charon daemon.
Verify DNS and Ad Blocking
If you enabled ad blocking, DNSCrypt-proxy should be running:
sudo systemctl status dnscrypt-proxy --no-pager
The output shows the service running and triggered by its socket:
● dnscrypt-proxy.service - DNSCrypt client proxy
Loaded: loaded (/usr/lib/systemd/system/dnscrypt-proxy.service; enabled)
Drop-In: /etc/systemd/system/dnscrypt-proxy.service.d
└─90-security-hardening.conf, 99-algo.conf
Active: active (running) since Sun 2026-04-12 16:06:16 UTC
Main PID: 16616 (dnscrypt-proxy)
Tasks: 7 (limit: 2200)
Memory: 16.6M
DNS queries from VPN clients go through this encrypted resolver. The ad blocking list (/usr/local/sbin/adblock.sh) updates via a cron job.
Check the Firewall Rules
Algo configures a strict iptables policy. Check it with:
sudo iptables -L -n
The INPUT chain uses a default DROP policy, allowing only established connections, ICMP pings (rate-limited), VPN ports (500, 4500, 51820), and SSH. The FORWARD chain isolates VPN clients from each other and blocks SMB/NetBIOS traffic while allowing internet-bound traffic through NAT:
Chain INPUT (policy DROP)
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT 17 -- 0.0.0.0/0 0.0.0.0/0 multiport dports 500,4500,51820
ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW
Chain FORWARD (policy DROP)
DROP 0 -- 10.49.0.0/16 10.49.0.0/16
ACCEPT 0 -- 10.49.0.0/16 0.0.0.0/0 ctstate NEW
Connecting Clients
Algo generates ready-to-use config files in /opt/algo/configs/<server-ip>/. The directory structure:
configs/10.0.1.50/
├── ipsec/
│ ├── apple/ # .mobileconfig profiles for iOS/macOS (IKEv2)
│ └── manual/ # .p12 certs + .conf for Linux/Windows/Android (IKEv2)
├── wireguard/
│ ├── apple/
│ │ ├── ios/ # .mobileconfig for iOS WireGuard
│ │ └── macos/ # .mobileconfig for macOS WireGuard
│ ├── phone.conf # Standard WireGuard config
│ ├── laptop.conf
│ ├── desktop.conf
│ ├── phone.png # QR code for mobile scanning
│ ├── laptop.png
│ └── desktop.png
└── ssh-tunnel/ # SSH tunnel configs (if enabled)
WireGuard Client (Linux/Android/Windows)
Copy the .conf file for the device. A typical WireGuard client config looks like this:
[Interface]
PrivateKey = (generated-private-key)
Address = 10.49.0.2
DNS = 172.16.x.x
[Peer]
PublicKey = (server-public-key)
PresharedKey = (preshared-key)
AllowedIPs = 0.0.0.0/0,::/0
Endpoint = 10.0.1.50:51820
On a Linux client, install WireGuard and import the config:
sudo apt install wireguard
sudo cp phone.conf /etc/wireguard/wg0.conf
sudo wg-quick up wg0
Verify the tunnel is up:
sudo wg show
curl ifconfig.me
The curl output should show the VPN server’s public IP, not your actual IP. On Android and iOS, use the WireGuard app and scan the QR code PNG that Algo generated.
IKEv2 Client (macOS/iOS)
Apple devices support IKEv2 natively. Double-click the .mobileconfig file from configs/<ip>/ipsec/apple/ and follow the prompts to install the VPN profile. No third-party app needed.
IKEv2 Client (Windows/Linux Manual)
For manual IKEv2 setup on Windows or Linux, use the .p12 certificate and .conf file from configs/<ip>/ipsec/manual/. The p12 password is shown in the deployment output. On Windows, import the p12 into the local machine certificate store, then create a VPN connection using IKEv2 with certificate authentication. On Linux with strongSwan, see our guide on configuring strongSwan IPsec VPN.
Adding New Users After Deployment
To add VPN users after the initial deployment, edit config.cfg and add the new device names to the users list. Then run the user update playbook:
cd /opt/algo
sudo bash -c "export HOME=/root PATH=$HOME/.local/bin:\$PATH && \
uv run ansible-playbook deploy_client.yml \
-e provider=local \
-e server=localhost"
This generates configs for the new users without touching existing ones (unless keys_clean_all is set to true in config.cfg, which regenerates everything).
Algo VPN vs Manual WireGuard Setup
You might wonder why not just set up WireGuard directly. Here’s what Algo adds:
| Feature | Manual WireGuard | Algo VPN |
|---|---|---|
| WireGuard tunnel | Yes | Yes |
| IKEv2 (native Apple/Windows) | No | Yes |
| Encrypted DNS | Manual setup | DNSCrypt-proxy included |
| Ad blocking DNS | Separate tool needed | Built-in with cron updates |
| Firewall hardening | You write the rules | Strict iptables auto-configured |
| Client config generation | Manual per device | Automatic for all users |
| QR codes for mobile | External tool | Generated automatically |
| Apple .mobileconfig | No | Generated for iOS and macOS |
| Privacy hardening | Manual | Log rotation, history clearing |
| SSH tunnel fallback | No | Yes (if enabled) |
If you only need WireGuard and want full control, the manual approach works. Algo is better when you need multi-protocol support, Apple device compatibility, or want everything configured in one shot.
Troubleshooting
Error: “Your cryptography version does not support SECP384R1”
This is the Ubuntu 24.04 compatibility issue described above. Apply the sed patch from the “Fix for Ubuntu 24.04” section. The underlying cause is that community.crypto 3.0.5 uses Python’s __dict__ lookup on the ec module, which doesn’t work with the Rust-backed cryptography library (46.x) that ships on modern Ubuntu. The patch switches to getattr(), which is the correct Python idiom for attribute access.
Error: “Installation aborted by user”
Algo’s local install mode has an interactive confirmation prompt. When running non-interactively (scripted deploys, cloud-init), pass -e local_install_confirmed=true to skip it.
WireGuard connects but no internet traffic
Check that NAT masquerade is active:
sudo iptables -t nat -L POSTROUTING -n
You should see MASQUERADE rules for the VPN subnets (10.48.0.0/16 and 10.49.0.0/16). If they’re missing, re-run the Algo playbook. Also verify that IP forwarding is enabled:
sysctl net.ipv4.ip_forward
The value should be 1.
Cloud provider metadata detection fails
On some EC2 instances, the IMDSv2 token requirement blocks the metadata endpoint. Algo falls back to detecting the IP from the network interface, which gives the private IP instead of the public one. Always pass -e endpoint=YOUR_PUBLIC_IP explicitly to avoid this issue.
What Happened to Streisand?
The original Streisand project (github.com/StreisandEffect/streisand) was archived on GitHub in June 2021. It was built for Ubuntu 16.04, supported a wide range of protocols including OpenVPN, OpenConnect, Shadowsocks, and Tor, and was popular for anti-censorship deployments. The project stopped receiving updates after 2015, and none of its dependencies are compatible with current operating systems. If you find old tutorials recommending Streisand, they will not work on any supported Ubuntu or Debian release. Algo VPN from Trail of Bits is the maintained successor for the same use case.