Back to Articles

Streisand: The Multi-Protocol VPN Arsenal That Automated Anti-Censorship

[ View on GitHub ]

Streisand: The Multi-Protocol VPN Arsenal That Automated Anti-Censorship

Hook

In 2014, a single shell script could deploy more censorship-resistant infrastructure than most Fortune 500 companies run for their entire remote workforce—and hand you a website to share it with your grandmother.

Context

The Great Firewall of China, Turkish Twitter blocks, and government-mandated ISP filtering created a cat-and-mouse game where activists would set up VPNs only to watch them get blocked within weeks. Traditional VPN setup required intimate knowledge of OpenVPN certificates, firewall rules, and client configuration files—expertise that doesn't scale when you're trying to help journalists in repressive regimes connect safely.

Streisand emerged from this problem with a radical thesis: instead of betting on a single protocol, deploy them all. If China blocks OpenVPN, switch to Shadowsocks. If deep packet inspection catches Shadowsocks, fall back to obfuscated SSH tunnels or Tor bridges. The project leveraged Ansible's infrastructure-as-code approach to transform this previously expert-level systems administration task into a single command that even moderately technical users could execute. More importantly, it generated human-readable documentation that made these complex services accessible to the non-technical people who often need them most.

Technical Insight

Creates

Produces

Connection Instructions

Conditional Install

Generates

Configures

Service Installation Roles

WireGuard Role

OpenVPN Role

Shadowsocks Role

Tor/sslh/Stunnel

User Input

Shell Wrapper

Ansible Master Playbook

Cloud Provider Module

Ubuntu 16.04 Server

Configuration Playbook

Certificates & Keys

UFW Rules

Streisand Gateway

Custom HTML Guide

System architecture — auto-generated

Streisand's architecture is built around Ansible's declarative configuration model, with a master playbook that orchestrates provider-specific provisioning followed by service installation. The entry point is deceptively simple—a shell wrapper that collects user input and invokes ansible-playbook with the appropriate variables. But the real engineering cleverness lies in how it manages the complexity of eight different VPN protocols, each with distinct authentication mechanisms, client requirements, and configuration patterns.

The provisioning flow separates infrastructure creation from service configuration. For cloud providers like DigitalOcean or AWS, Streisand uses provider-specific Ansible modules to spawn Ubuntu instances, then hands off to a universal configuration playbook that's provider-agnostic:

# Simplified excerpt showing the service installation pattern
- name: Install WireGuard
  include_role:
    name: wireguard
  when: streisand_wireguard_enabled

- name: Install OpenVPN
  include_role:
    name: openvpn
  when: streisand_openvpn_enabled

- name: Install Shadowsocks
  include_role:
    name: shadowsocks
  when: streisand_shadowsocks_enabled

- name: Generate client documentation
  include_role:
    name: streisand-gateway
  tags: always

Each service role follows a consistent pattern: install dependencies, generate certificates/keys, configure the service with hardened settings, configure firewall rules via ufw, and emit connection details to a fact dictionary. This modular approach means services don't collide—WireGuard runs on UDP 51820, OpenVPN on TCP 443 and UDP 1194, Shadowsocks on port 8388, and so on.

The certificate generation is particularly elegant. Rather than using interactive tools like easy-rsa, Streisand programmatically generates everything:

# OpenVPN certificate generation (simplified)
openssl req -new -newkey rsa:4096 -days 3650 \
  -nodes -x509 \
  -subj "/C=US/O=Streisand/CN={{ streisand_server_name }}" \
  -keyout ca-key.pem -out ca.pem

# Generate unique client certificates for each user
for client in "{{ streisand_openvpn_clients }}"; do
  openssl req -new -newkey rsa:4096 -nodes \
    -subj "/C=US/O=Streisand/CN=$client" \
    -keyout "$client-key.pem" -out "$client.csr"
  openssl x509 -req -in "$client.csr" -CA ca.pem \
    -CAkey ca-key.pem -CAcreateserial \
    -out "$client.pem" -days 3650
done

The crown jewel is the streisand-gateway role, which templates out a complete static HTML website with embedded CSS, QR codes for mobile configuration, downloadable .ovpn files, and step-by-step instructions customized to the exact server configuration. It even generates mirror sites served over different protocols so users can access instructions via Tor if the main IP gets blocked.

Protocol diversity isn't just about redundancy—it's about defense in depth against different censorship techniques. OpenVPN over TCP 443 looks like HTTPS traffic. Shadowsocks with obfuscation plugins resists deep packet inspection. SSH tunnels work through corporate proxies. Tor bridges are distributed through separate channels. WireGuard offers modern cryptography with better mobile performance. This architectural decision anticipated the evolution of censorship technology, where simply encrypting traffic became insufficient.

The sslh multiplexer is a subtle but crucial component that lets multiple protocols share port 443. This allows OpenVPN, SSH, and HTTPS connections to coexist on the standard HTTPS port, making the server appear less suspicious and working through restrictive firewalls that only allow web traffic. The configuration dynamically detects protocol handshakes and routes connections appropriately—a level of sophistication that would take days to configure manually.

Gotcha

The project's Achilles heel is immediately visible in its codebase: hard-coded references to Ubuntu 16.04, which reached end-of-life in April 2021. This isn't just about missing security patches—cloud providers have deprecated 16.04 images, package repositories are in archive mode, and some Ansible modules no longer function with the expected API versions. Attempting to run Streisand today will likely fail at the provisioning stage with cryptic errors about unavailable images or SSL certificate validation failures from outdated root certificates.

The all-in-one server approach, while convenient, creates both operational and security concerns. Running eight VPN services simultaneously on a single $5 DigitalOcean droplet means CPU and bandwidth are shared resources—a dozen users streaming video over different protocols will degrade performance for everyone. More critically, having every protocol on one IP address creates a unique fingerprint. Nation-state censors have begun fingerprinting multi-service VPN servers through timing analysis and port scanning patterns. If they identify the signature, they can block the entire IP rather than playing protocol whack-a-mole. Modern anti-censorship strategies increasingly favor lightweight, single-protocol servers that are cheap to cycle through when blocked. The project also requires cloud provider API credentials and command-line comfort that many activists in high-risk environments lack—the very people who need these tools most urgently.

Verdict

Use Streisand if: you're studying anti-censorship infrastructure architecture and want to understand how protocol diversity and automation intersect, or you're prepared to fork and modernize it (upgrading to Ubuntu 22.04, updating Ansible modules, refreshing service configurations). The architectural patterns—modular service roles, programmatic certificate generation, and automated documentation—remain excellent blueprints for building resilient infrastructure. Skip if: you need production-ready censorship circumvention today without extensive maintenance commitment. The security risks from outdated dependencies outweigh the convenience. Instead, evaluate Algo VPN for personal use with modern WireGuard, or Outline VPN for easy Shadowsocks sharing with non-technical users. Streisand's legacy is as a proof-of-concept that changed how we think about deploying anti-censorship tools, even if the code itself has become a historical artifact.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/streisandeffect-streisand.svg)](https://starlog.is/api/badge-click/developer-tools/streisandeffect-streisand)