Repository: StreisandEffect/streisand
Branch: master
Commit: af5eb7dac157
Files: 377
Total size: 1005.7 KB
Directory structure:
gitextract_p3pz680y/
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── workflows/
│ └── streisand.yml
├── .gitignore
├── Advanced installation.md
├── CONTRIBUTING.md
├── Features.md
├── Installation.md
├── LICENSE
├── README-chs.md
├── README-fr.md
├── README-ru.md
├── README.md
├── Services.md
├── Vagrantfile
├── Vagrantfile.remotetest
├── ansible.cfg
├── deploy/
│ ├── streisand-existing-cloud-server.sh
│ ├── streisand-local.sh
│ └── streisand-new-cloud-server.sh
├── documentation/
│ ├── AWS-fr.md
│ ├── AWS.md
│ ├── AZURE-fr.md
│ ├── AZURE.md
│ ├── SOURCES.md
│ ├── certificates.md
│ ├── localization_howto.md
│ ├── modular_roles.md
│ └── testing.md
├── global_vars/
│ ├── default-site.yml
│ ├── globals.yml
│ ├── integration/
│ │ └── test-site.yml
│ └── noninteractive/
│ ├── amazon-site.yml
│ ├── azure-site.yml
│ ├── digitalocean-site.yml
│ ├── google-site.yml
│ ├── linode-site.yml
│ ├── local-site.yml
│ └── rackspace-site.yml
├── inventories/
│ ├── inventory
│ └── inventory-local-provision
├── library/
│ └── digital_ocean_droplet.py
├── playbooks/
│ ├── amazon.yml
│ ├── azure.yml
│ ├── cloud-status.yml
│ ├── customize.yml
│ ├── digitalocean.yml
│ ├── ec2-metadata-instance.yml
│ ├── existing-server.yml
│ ├── google.yml
│ ├── group_vars/
│ │ └── all
│ ├── lets-encrypt.yml
│ ├── linode.yml
│ ├── localhost.yml
│ ├── provider-detect.yml
│ ├── python.yml
│ ├── rackspace.yml
│ ├── roles/
│ │ ├── ad-blocking/
│ │ │ ├── files/
│ │ │ │ ├── download-blocklists
│ │ │ │ ├── download-blocklists.service
│ │ │ │ ├── download-blocklists.timer
│ │ │ │ ├── transform-domain-list
│ │ │ │ └── transform-host-list
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── azure-security-group/
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── certificates/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── ca-server.yml
│ │ │ │ ├── client.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── pkcs.yml
│ │ │ ├── templates/
│ │ │ │ ├── allowed_vpn_certs.j2
│ │ │ │ └── openssl.cnf.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── cloudflared/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ └── cloudflared.service
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── install_binary.yml
│ │ │ │ ├── install_package.yml
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ └── cloudflared.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── common/
│ │ │ ├── files/
│ │ │ │ ├── english.txt
│ │ │ │ ├── footer.html
│ │ │ │ └── header.html
│ │ │ ├── tasks/
│ │ │ │ ├── detect-public-ip.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── set-default-variables.yml
│ │ │ ├── templates/
│ │ │ │ ├── 20auto-upgrades.j2
│ │ │ │ ├── 50unattended-upgrades.j2
│ │ │ │ └── test-client-inventory.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── diagnostics/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── templates/
│ │ │ └── streisand-diagnostics.md.j2
│ │ ├── dnsmasq/
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ ├── dnsmasq.conf.j2
│ │ │ │ └── dnsmasq.service.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── download-and-verify/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── ec2-security-group/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── gce-network/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── genesis-amazon/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ └── aws-metadata-instance.service
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── genesis-azure/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── genesis-digitalocean/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── genesis-google/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── genesis-linode/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── genesis-rackspace/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── gpg/
│ │ │ ├── files/
│ │ │ │ ├── 2D8330C2.daniel@binaryparadox.net.asc
│ │ │ │ ├── 2F2B01E7.security@openvpn.net.asc
│ │ │ │ ├── 4AE8DA82.putty@projects.tartarus.org.asc
│ │ │ │ ├── 7F343FA7.nmav@redhat.com.asc
│ │ │ │ ├── 93298290.torbrowser@torproject.org.asc
│ │ │ │ ├── 96865171.nmav@gnutls.org.asc
│ │ │ │ ├── A697A56F.corban@raunco.co.asc
│ │ │ │ ├── AF16234E.alimakki@gmail.com.asc
│ │ │ │ ├── CDF6583E.josh@joshlund.com.asc
│ │ │ │ ├── DD3AAAA3.Michal.Trojnara@stunnel.org.asc
│ │ │ │ └── F67DA905.nop@nop.com.asc
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ ├── dirmngr.conf.j2
│ │ │ │ └── streisand-gpg-refresh.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── i18n-docs/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── templates/
│ │ │ └── languages.md.j2
│ │ ├── ip-forwarding/
│ │ │ ├── files/
│ │ │ │ └── streisand-ipforward.sh
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── lets-encrypt/
│ │ │ ├── files/
│ │ │ │ └── 01-reload-nginx.sh
│ │ │ ├── tasks/
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── install.yml
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── nginx/
│ │ │ ├── files/
│ │ │ │ ├── nginx.conf
│ │ │ │ └── nginx_signing.key
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ └── nginx.service.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── openconnect/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ ├── ocserv-pam
│ │ │ │ └── openconnect.conf
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── install.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── mirror.yml
│ │ │ ├── templates/
│ │ │ │ ├── client.mobileconfig.j2
│ │ │ │ ├── config.j2
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ ├── mirror.md.j2
│ │ │ │ ├── ocserv-iptables.service.j2
│ │ │ │ └── ocserv.service.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ └── mirror.yml
│ │ ├── openvpn/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ └── openvpn_signing.key
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── install.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── mirror.yml
│ │ │ ├── templates/
│ │ │ │ ├── client-combined.ovpn.j2
│ │ │ │ ├── client-common.j2
│ │ │ │ ├── client-direct-udp.ovpn.j2
│ │ │ │ ├── client-direct.ovpn.j2
│ │ │ │ ├── client-sslh.ovpn.j2
│ │ │ │ ├── client-stunnel.ovpn.j2
│ │ │ │ ├── etc_openvpn_server.conf.j2
│ │ │ │ ├── etc_openvpn_server_common.j2
│ │ │ │ ├── etc_openvpn_server_udp.conf.j2
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ ├── mirror.md.j2
│ │ │ │ ├── openvpn-iptables.service.j2
│ │ │ │ ├── openvpn.service.j2
│ │ │ │ ├── openvpn_dnsmasq.conf.j2
│ │ │ │ ├── stunnel-instructions-fr.md.j2
│ │ │ │ └── stunnel-instructions.md.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ └── mirror.yml
│ │ ├── service-net/
│ │ │ ├── files/
│ │ │ │ ├── 10-service0.netdev
│ │ │ │ ├── 10-service0.network
│ │ │ │ └── service-net.conf
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── shadowsocks/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── main.yml
│ │ │ │ ├── mirror.yml
│ │ │ │ ├── simple-obfs.yml
│ │ │ │ └── v2ray.yml
│ │ │ ├── templates/
│ │ │ │ ├── config.json.j2
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ ├── mirror.md.j2
│ │ │ │ ├── shadowsocks-libev.default.j2
│ │ │ │ └── shadowsocks-libev.service.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ └── mirror.yml
│ │ ├── ssh/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ └── sshd_config
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── ssh-forward/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── mirror.yml
│ │ │ ├── templates/
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ └── mirror.md.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ └── mirror.yml
│ │ ├── sslh/
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ ├── sslh.cfg.j2
│ │ │ │ ├── sslh.default.j2
│ │ │ │ └── sslh.service.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── streisand-gateway/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── fetch-and-cleanup.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── openssl.yml
│ │ │ ├── templates/
│ │ │ │ ├── firewall-fr.md.j2
│ │ │ │ ├── firewall.md.j2
│ │ │ │ ├── index-fr.md.j2
│ │ │ │ ├── index.md.j2
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── openssl-local.cnf.j2
│ │ │ │ └── vhost.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── streisand-mirror/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ ├── mirror-index-fr.md.j2
│ │ │ │ └── mirror-index.md.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── stunnel/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── main.yml
│ │ │ │ └── mirror.yml
│ │ │ ├── templates/
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ ├── mirror.md.j2
│ │ │ │ ├── stunnel-local.conf.j2
│ │ │ │ ├── stunnel-remote.conf.j2
│ │ │ │ └── stunnel.service.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ └── mirror.yml
│ │ ├── sysctl/
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── test-client/
│ │ │ ├── files/
│ │ │ │ ├── openvpn_signing.key
│ │ │ │ └── shadowsocks-qr-decode.py
│ │ │ ├── tasks/
│ │ │ │ ├── main.yml
│ │ │ │ ├── openconnect-profiletest.yml
│ │ │ │ ├── openconnect.yml
│ │ │ │ ├── openvpn-profileget.yml
│ │ │ │ ├── openvpn-profiletest.yml
│ │ │ │ ├── openvpn-test.yml
│ │ │ │ ├── openvpn.yml
│ │ │ │ ├── shadowsocks.yml
│ │ │ │ ├── ssh-forward.yml
│ │ │ │ ├── stunnel.yml
│ │ │ │ ├── tor.yml
│ │ │ │ ├── wireguard-profiletest.yml
│ │ │ │ └── wireguard.yml
│ │ │ ├── templates/
│ │ │ │ ├── obfs4.relay.client.torrc.j2
│ │ │ │ ├── openvpn-profile-addons.j2
│ │ │ │ ├── ssh-config.j2
│ │ │ │ ├── streisand-gateway-test.sh.j2
│ │ │ │ └── streisand-shadowsocks-forward-test.sh.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── tinyproxy/
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ └── main.yml
│ │ │ ├── templates/
│ │ │ │ ├── tinyproxy.conf.j2
│ │ │ │ ├── tinyproxy.service.j2
│ │ │ │ └── tinyproxytmp.conf.j2
│ │ │ └── vars/
│ │ │ └── main.yml
│ │ ├── tor-bridge/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ ├── files/
│ │ │ │ └── apparmor-local-override
│ │ │ ├── handlers/
│ │ │ │ └── main.yml
│ │ │ ├── meta/
│ │ │ │ └── main.yml
│ │ │ ├── tasks/
│ │ │ │ ├── docs.yml
│ │ │ │ ├── firewall.yml
│ │ │ │ ├── main.yml
│ │ │ │ ├── mirror-common.yml
│ │ │ │ └── mirror.yml
│ │ │ ├── templates/
│ │ │ │ ├── hidden-service-vhost.j2
│ │ │ │ ├── instructions-fr.md.j2
│ │ │ │ ├── instructions.md.j2
│ │ │ │ ├── mirror-fr.md.j2
│ │ │ │ ├── mirror.md.j2
│ │ │ │ └── torrc.j2
│ │ │ └── vars/
│ │ │ ├── main.yml
│ │ │ ├── mirror-common.yml
│ │ │ ├── mirror-download.yml
│ │ │ └── mirror.yml
│ │ ├── ufw/
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── validation/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ ├── main.yml
│ │ │ └── ssh.yml
│ │ └── wireguard/
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ ├── meta/
│ │ │ └── main.yml
│ │ ├── tasks/
│ │ │ ├── docs.yml
│ │ │ ├── firewall.yml
│ │ │ ├── install.yml
│ │ │ └── main.yml
│ │ ├── templates/
│ │ │ ├── client-openwrt.txt.j2
│ │ │ ├── client.conf.j2
│ │ │ ├── instructions-fr.md.j2
│ │ │ ├── instructions.md.j2
│ │ │ ├── server.conf.j2
│ │ │ ├── streisand-wireguard-service.sh.j2
│ │ │ └── wireguard_dnsmasq.conf.j2
│ │ └── vars/
│ │ └── main.yml
│ ├── ssh-setup.yml
│ ├── streisand.yml
│ ├── test-client.yml
│ ├── vagrant.yml
│ └── validate.yml
├── requirements.txt
├── streisand
├── tests/
│ ├── README.md
│ ├── ansible.cfg
│ ├── development-setup.yml
│ ├── group_vars/
│ │ └── all/
│ │ └── all
│ ├── inventory
│ ├── randomize_sitevars.sh
│ ├── remote_test.sh
│ ├── run.yml
│ ├── shellcheck.sh
│ ├── site_vars/
│ │ ├── cloudflared.yml
│ │ ├── openconnect.yml
│ │ ├── openvpn.yml
│ │ ├── random.yml
│ │ ├── shadowsocks.yml
│ │ └── ssh.yml
│ ├── syntax-check.yml
│ ├── tests.sh
│ ├── vars_ci.yml
│ ├── yamlcheck.sh
│ └── yamllint-config.yml
└── util/
├── ansible_check.sh
├── dependencies.txt
├── print-aws-regions.py
├── source_check_and_default_site_vars.sh
├── source_validate_and_deploy.sh
├── ubuntu-dependencies.sh
├── venv-dependencies.sh
└── version_at_least.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
### Expected behavior:
### Actual Behavior:
### Steps to Reproduce:
1.
[ contents of `streisand-diagnostics.md` here ]
### Additional Details:
#### *Log output from Ansible or other relevant services (link to Gist for longer output):*
##### *Target Cloud Provider:*
##### *Operating System of target host:*
##### *Operating System of client:*
##### *Version of Ansible, using `ansible --version` :*
##### *Output from `git rev-parse HEAD` in your Streisand directory :*
================================================
FILE: .github/workflows/streisand.yml
================================================
---
name: Streisand
on: [push, pull_request]
jobs:
deps:
name: Dependencies
runs-on: ubuntu-16.04
env:
ANSIBLE_CONFIG: tests/ansible.cfg
ANSIBLE_NOCOWS: true
#ANSIBLE_VERBOSITY: 5
DEBIAN_FRONTEND: noninteractive
strategy:
#max-parallel: 5
fail-fast: false
matrix:
# 3.5 for older distro's like xenial, and 3.8 to test the latest python
python-version: [3.5, 3.8]
# Test ansible 2.8 and "latest"
ansible-version: [">=2.8,<2.9", ">=2.9"]
env_vars:
- {RUN: "shellcheck yamlcheck syntax ci", SITE: "global_vars/default-site.yml"}
- {RUN: "ci", SITE: "tests/site_vars/openconnect.yml"}
- {RUN: "ci", SITE: "tests/site_vars/openvpn.yml"}
- {RUN: "ci", SITE: "tests/site_vars/shadowsocks.yml"}
- {RUN: "ci", SITE: "tests/site_vars/ssh.yml"}
- {RUN: "ci", SITE: "random"}
steps:
# Removing dotnetdev.list, and microsoft-prod.list for now, as they seem to constantly have issues
# with multiple github issues being opened in response. Removing shellcheck so we can install
# a newer version from snap.
- name: Remove apt lists and packages we dont need
run: |
sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list
sudo rm -rf /var/lib/apt/lists/*
sudo apt-get clean
sudo apt-get update -qq
sudo apt-get purge -yqq shellcheck
sudo dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2) | xargs sudo apt-get -yqq purge
sudo apt-get --purge autoremove -yqq
- name: Update Yarn Debian key
run: |
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
- name: Install additonal deps
run: |
sudo apt-get install ca-certificates
sudo snap install --channel=edge shellcheck
- uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
fetch-depth: 1
python-version: ${{ matrix.python-version }}
- name: Install additional pip dependencies
run: |
python -m pip install --upgrade pip
pip install "ansible${{ matrix.ansible-version }}"
pip install urllib3 yamllint
ansible --version
- name: Run tests
env: ${{ matrix.env_vars }}
run: ./tests/tests.sh
================================================
FILE: .gitignore
================================================
generated-docs
*.retry
*.pyc
*~
*.swp
*.tmp
*.temp
.DS_Store
.vagrant/
ubuntu-xenial-16.04-cloudimg-console.log
# Ignore changes to the existing server inventory to allow users to modify it
inventories/inventory-existing
# Ignore the Streisand diagnostics file we generate each run
streisand-diagnostics.md
# We recommend people use a Python virtualenv, and document this as
# the location.
venv/
================================================
FILE: Advanced installation.md
================================================
# Advanced installation
### Running Streisand to Provision Localhost ###
If you can't run Streisand in the normal manner (running from your client home machine/laptop to configure a remote server) Streisand supports a local provisioning mode for **machines running Ubuntu 16.04**. After following the basic instructions, choose "Localhost (Advanced)" from the menu after running `./streisand`.
**Note:** Running Streisand against localhost can be a destructive action! You will be potentially overwriting configuration files and must be certain that you are affecting the correct machine.
**Note:** The machine must be running Ubuntu 16.04.
**Note:** If you have an external firewall available, see the `generated-docs` directory for a `-firewall-information.html` document with information on which ports need to be opened.
### Running Streisand on Other Providers ###
You can also run Streisand on a new Ubuntu 16.04 server. Dedicated hardware? Great! Esoteric cloud provider? Awesome! To do so, simply choose "Existing Server (Advanced)" from the menu after running `./streisand` and provide the IP address of the existing server when prompted.
The server must be accessible using the `$HOME/.ssh/id_rsa` SSH Key, and **root** is used as the connecting user by default. If your provider requires you to SSH with a different user than root (e.g. `ubuntu`) specify the `ANSIBLE_SSH_USER` environmental variable (e.g. `ANSIBLE_SSH_USER=ubuntu`) when you run `./streisand`.
**Note:** Running Streisand against an existing server can be a destructive action! You will be potentially overwriting configuration files and must be certain that you are affecting the correct machine.
**Note:** The machine must be running Ubuntu 16.04.
**Note:** If you have an external firewall available, see the `generated-docs` directory for a `-firewall-information.html` document with information on which ports need to be opened.
### Noninteractive Deployment ###
Alternative scripts and configuration file examples are provided for
noninteractive deployment, in which all of the required information is passed
on the command line or in a configuration file.
Example configuration files are found under `global_vars/noninteractive`. Copy
and edit the desired parameters, such as providing API tokens and other choices,
and then run the appropriate script.
To deploy a new Streisand server:
deploy/streisand-new-cloud-server.sh \
--provider digitalocean \
--site-config global_vars/noninteractive/digitalocean-site.yml
To run the Streisand provisioning on the local machine:
deploy/streisand-local.sh \
--site-config global_vars/noninteractive/local-site.yml
To run the Streisand provisioning against an existing server:
deploy/streisand-existing-cloud-server.sh \
--ip-address 10.10.10.10 \
--ssh-user root \
--site-config global_vars/noninteractive/digitalocean-site.yml
================================================
FILE: CONTRIBUTING.md
================================================
## Contributing Issues and Bug Reports
Thanks for your interest in helping improve Streisand! This documentation page
has some helpful tips and things to keep in mind to make your
contributions to Streisand as great as they can be.
### Keep it Positive/Empathetic
Encountering bugs is a frustrating experience! Missing features speak to
unaddressed needs. We understand that and want to help.
Please also remember that Streisand is 100% a volunteer effort. Nobody is paid
to work on Streisand, and nobody does it as their full time job.
Where possible try to keep discussion tone positive and remember that the folks
working on Streisand fit it into their spare time between other real life
commitments (family, vacation, jobs, hobbies, relaxation!).
### Which Repository?
If your issue is a question or you need help with setting up / configuring Streisand, then please ask on the [streisand-discussions](https://github.com/StreisandEffect/streisand-discussions/) Github repository.
Similarly, if you are requesting a new feature we prefer it be done on the [streisand-discussions](https://github.com/StreisandEffect/streisand-discussions) Github repository.
### Before Submitting an Issue
Before submitting new issues please do a search in [open issues](https://github.com/StreisandEffect/streisand/issues) to see if the issue or refinement you have in mind has already been suggested. For features/questions search [the streisand-discussions open issues](https://github.com/StreisandEffect/streisand-discussions/issues).
If you find your issue already exists, feel free to add constructive comments such as new information, additional insights on how to reproduce, etc. If you're only interested in sharing that the feature is important to you, or that the bug affects you then add a [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Using reactions in place of a "+1" or "me too!" comments helps keeps the conversation clear and concise.
👍 - upvote
👎 - downvote
If you cannot find an existing issue that describes your bug or feature, submit a new issue using the guidelines below.
## Writing Good Bug Reports and Feature Requests
Describe a single problem or feature request per issue. Do not include multiple bugs or feature requests in the same issue.
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
#Take advantage of Github Markdown styling to make your issue easier to read. For example, Wrap single line code statements or logs in single backticks: \` code here \`. Wrap multi-line in triple backticks: \``` multi-line code here \```.
#### Streisand Diagnostics File
Streisand automatically creates a markdown file in the project directory called
`streisand-diagnostics.md`. Every time you run Streisand this file is populated
with some basic diagnostic information about your system & Streisand options
that are enabled.
Sharing the contents of this file in new issues is a great way to answer a lot
of required questions without having to do any work besides copy & pasting!
#### What Other Information to Include in Your Issue
Please try your best to answer all of the questions in [the Streisand Issue template](https://github.com/StreisandEffect/streisand/blob/master/.github/ISSUE_TEMPLATE.md). Answering these questions help us skip a lot of "Github telephone tag" that takes up time that could be used fixing the bug.
When describing your issue focus on:
* Reproducible steps (1... 2... 3...) and what you expected versus what you actually saw.
* Log output from Ansible or other relevant services, ideally linking to a Gist for longer log output.
* Information about your system (OS, version, etc)
* Information about the target Streisand server (cloud provider, etc)
Don't feel bad if we can't reproduce the issue and ask for more information.
It's impossible to know what questions will be most relevant for every potential
bug!
#### Why Was My Issue Closed???
Issues are generally closed for one of three reasons:
1. There wasn't enough information or nobody has been replying to questions
asked.
2. The issue was created on the wrong repository and should have been created as
a [streisand-discussions](https://github.com/StreisandEffect/streisand-discussions)
issue or vice-versa.
3. After discussion and evaluation it was determined the problem was fixed or
wasn't appropriate for Streisand
We try very hard to keep the issue list clean. Don't feel bad if your issue
was closed, it can always be reopened if there are disagreements to discuss
or the situation has changed.
## Contributing Fixes
If you are interested in fixing issues and contributing directly to the code
base please feel free to submit a PR. We're excited to help! If there is an
existing issue for the problem you are interested in fixing please leave a quick
comment indicating that you'd like to start working on a solution. That way we
can avoid duplicating work. Similarly, talking about how you plan to implement
a fix or a new feature ahead of starting gives folks a chance to give early
design input which will save time later during code review!
#### CI Testing
Streisand uses [Travis CI](https://travis-ci.org/jlund/streisand) for continuous
integration testing. Make sure to read
[testing.md](https://github.com/StreisandEffect/streisand/blob/master/documentation/testing.md)
where we describe the tests that are run, how to work around breakages for
features unsupported by LXC, and tips for developing on localhost with Vagrant.
All PRs will have to pass CI to be merged. Feel free to submit a PR with broken
CI if you need help getting the tests to pass.
#### Code Reviews
All PRs need at least one approved code review from a maintainer in order to be
merged. Maintainers may not review their own pull requests.
Streisand is a volunteer effort. Please allow at least 7 days to pass before
following up on missing reviews. If more than 7 days have elapsed and you are
still waiting on a review or a reply from a maintainer please leave a friendly
"bump" message and "@ mention" their username.
#### Modularity
We've recently begun working on modularizing Streisand so that installations can
be customized to include/not include certain VPN services. Additions to
Streisand should endeavour to fit into this model. We describe the philosophy
and design patterns used in this approach in
[modular_roles.md](https://github.com/StreisandEffect/streisand/blob/master/documentation/modular_roles.md)
================================================
FILE: Features.md
================================================
# Features
* A single command sets up a brand new Ubuntu 16.04 server running a [wide variety of anti-censorship software](#services-provided) that can completely mask and encrypt all of your Internet traffic.
* Streisand natively supports the creation of new servers at [Amazon EC2](https://aws.amazon.com/ec2/), [Azure](https://azure.microsoft.com), [DigitalOcean](https://www.digitalocean.com/), [Google Compute Engine](https://cloud.google.com/compute/), [Linode](https://www.linode.com/), and [Rackspace](https://www.rackspace.com/)—with more providers coming soon! It also runs on any Ubuntu 16.04 server regardless of provider, and **hundreds** of instances can be configured simultaneously using this method.
* The process is completely automated and only takes about ten minutes, which is pretty awesome when you consider that it would require the average system administrator several days of frustration to set up even a small subset of what Streisand offers in its out-of-the-box configuration.
* Once your Streisand server is running, you can give the custom connection instructions to friends, family members, and fellow activists. The connection instructions contain an embedded copy of the server's unique SSL certificate, so you only have to send them a single file.
* Each server is entirely self-contained and comes with absolutely everything that users need to get started, including cryptographically verified mirrors of all common clients. This renders any attempted censorship of default download locations completely ineffective.
* But wait, there's more...
More Features
-------------
* Nginx powers a password-protected and encrypted Gateway that serves as the starting point for new users. The Gateway is accessible over SSL, or as a Tor [hidden service](https://www.torproject.org/docs/hidden-services.html.en).
* Beautiful, custom, step-by-step client configuration instructions are generated for each new server that Streisand creates. Users can quickly access these instructions through any web browser. The instructions are responsive and look fantastic on mobile phones.
* The integrity of mirrored software is ensured using SHA-256 checksums, or by verifying GPG signatures if the project provides them. This protects users from downloading corrupted files.
* All ancillary files, such as OpenVPN configuration profiles, are also available via the Gateway.
* Current Tor users can take advantage of the additional services Streisand sets up in order to transfer large files or to handle other traffic (e.g. BitTorrent) that isn't appropriate for the Tor network.
* A unique password, SSL certificate, and SSL private key are generated for each Streisand Gateway. The Gateway instructions and certificate are transferred via SSH at the conclusion of Streisand's execution.
* Distinct services and multiple daemons provide an enormous amount of flexibility. If one connection method gets blocked there are numerous options available, most of which are resistant to Deep Packet Inspection.
* All of the connection methods (including direct OpenVPN connections) are effective against the type of blocking Turkey has been experimenting with.
* OpenConnect/AnyConnect, OpenSSH, OpenVPN (wrapped in stunnel), Shadowsocks, Tor (with obfsproxy and the obfs4 pluggable transport), and WireGuard are all currently effective against China's Great Firewall.
* Every task has been thoroughly documented and given a detailed description. Streisand is simultaneously the most complete HOWTO in existence for the setup of all of the software it installs, and also the antidote for ever having to do any of this by hand again.
* All software runs on ports that have been deliberately chosen to make simplistic port blocking unrealistic without causing massive collateral damage. OpenVPN, for example, does not run on its default port of 1194, but instead uses port 636, the standard port for LDAP/SSL connections that are beloved by companies worldwide.
================================================
FILE: Installation.md
================================================
# Installation
Please read all installation instructions **carefully** before proceeding.
If you're an expert, and installing on a cloud provider Streisand doesn't support, make sure to read [the advanced installation instructions](Advanced%20installation.md).
## Important: definitions ##
Streisand is based on [Ansible](https://www.ansible.com/), an automation tool that is typically used to provision and configure files and packages on remote servers. Streisand automatically sets up **another server** with the VPN packages and configuration. We call the machine that sets up the Streisand server the *builder*. Think of the builder as "a place to stand."
* If you don't have a suitable builder machine, you could set up another cloud server to use as your builder. That means you'd have two cloud servers at the end — the builder, and your fresh new Streisand *server*. When you're done with the builder, make sure you download the *builder's* `streisand` directory — very important to keep the contents of that directory! — you could delete the *builder* cloud server.)
* Although it's not recommended, sometimes you can use a fresh server as both the builder and the server. See the [the advanced installation instructions](Advanced%20installation.md).
## Prerequisites ##
The Streisand builder requires a Linux, macOS, or BSD system.
* Using native Windows as a builder is not supported, but Ubuntu on the [Windows Subsystem For Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/faq) should work. ([Ubuntu install link on Microsoft Store](https://www.microsoft.com/en-us/p/ubuntu-1804-lts/9n9tngvndl3q))
Complete all of these tasks on your local machine. All of the commands should be run inside a command-line session.
### SSH key
Make sure an SSH public key is present in `~/.ssh/id_rsa.pub`.
* SSH keys are a more secure alternative to passwords that allow you to prove your identity to a server or service built on public key cryptography. The public key is something that you can give to others, whereas the private key should be kept secret (like a password).
To check if you already have an SSH public key, enter the following command at a command prompt:
```
ls ~/.ssh
```
If you see an `id_rsa.pub` file, then you have an SSH public key. If you do not have an SSH key pair, you can generate one by using this command and following the defaults:
```
ssh-keygen
```
If you'd like to use an SSH key with a different name or from a non-standard location, please enter *yes* when asked if you'd like to customize your instance during installation.
* **Please note**: You will need these keys to access your Streisand instance over SSH. Please keep `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub` for the lifetime of the Streisand server.
## Bootstrap ##
Install the bootstrap packages: Git, and Python 3.5 or later. Some environments need additional packages.
Here's how to set up these packages:
* On Debian and Ubuntu:
```
sudo apt-get install git python3 python3-venv
```
* On Fedora 30, some additional packages are needed later:
```
dnf install git python3 gcc python3-devel python3-crypto \
python3-pycurl libcurl-devel
```
* On CentOS 7, `python36` is available from the EPEL repository; some additional packages are needed later:
```
sudo yum -y update && sudo yum install -y epel-release
sudo yum -y update && sudo yum install -y \
git gcc python36-devel python36-crypto python36-pycurl \
libcurl-devel
```
* On macOS, `git` is part of the Developer Tools, and it will be installed the first time you run it. Python 3.5 or later is required. Either use [Homebrew](https://brew.sh/) and run `brew install python3`, or see [the Python.org Mac download site](https://www.python.org/downloads/mac-osx/); the package you want to download is the "macOS 64-bit installer".
## Execution ##
1. Clone the Streisand repository and enter the directory.
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
1. Run the installer for Ansible and its dependencies. The installer will detect missing packages, and print the commands needed to install them. (Ignore the Python 2.7 `DEPRECATION` warning; ignore the warning from python-novaclient that pbr 5.1.3 is incompatible.)
./util/venv-dependencies.sh ./venv
1. Activate the Ansible packages that were installed.
source ./venv/bin/activate
1. Execute the Streisand script.
./streisand
1. Follow the prompts to choose your provider, the physical region for the server, and its name. You will also be asked to enter API information.
1. Once login information and API keys are entered, Streisand will begin spinning up a new remote server.
1. Wait for the setup to complete (this usually takes around ten minutes) and look for the corresponding files in the `generated-docs` folder in the Streisand repository directory. The HTML file will explain how to connect to the Gateway over SSL, or via the Tor hidden service. All instructions, files, mirrored clients, and keys for the new server can then be found on the Gateway. You are all done!
## Keep the results!
You should keep a copy of the `generated-docs` directory for the life of the server.
Remember to save your `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub` SSH keys too. You'll need them in case you want to troubleshoot or perform maintenance on your server later.
================================================
FILE: LICENSE
================================================
Copyright 2014-2017 Joshua Lund
OpenVPN role courtesy of Sovereign (https://github.com/al3x/sovereign)
Copyright 2013-2014 Luke Cyca, Ben Ford, Greg Karékinian, Joshua Lund,
and Alex Payne.
L2TP/IPsec configuration files courtesy of Lin Song
(https://github.com/hwdsl2/setup-ipsec-vpn).
Copyright 2014-2017 Lin Song, and based on the work of
Thomas Sarlandie (Copyright 2012).
Modifications to the L2TP/IPsec configuration files are licensed
under CC Attribution-ShareAlike 3.0 Unported
(http://creativecommons.org/licenses/by-sa/3.0/).
Cloudflared DNS-over-HTTPS role courtesy of Steven Foerster
(https://github.com/sfoerster/ansible-cloudflared).
Copyright 2019 Steven Foerster, and based on the work of
Ben Dews (Copyright 2018).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
================================================
FILE: README-chs.md
================================================
- - -
[English](README.md), [Français](README-fr.md), [简体中文](README-chs.md), [Русский](README-ru.md) | [Mirror](https://gitlab.com/alimakki/streisand)
- - -
[](https://github.com/StreisandEffect/streisand/actions)
[](https://twitter.com/StreisandVPN)
Streisand
=========
**欲盖弥彰的[Streisand效应](https://zh.wikipedia.org/wiki/%E5%8F%B2%E7%BF%A0%E7%8F%8A%E6%95%88%E5%BA%94).**
互联网对我们并不公平。ISP、通信、政治家,他们串通一气封锁那些我们感兴趣和关注的网站和信息。或许是时候*打破枷锁*,来场正面较量了。
Streisand介绍
---------------------
* 只需要一个简单的脚本,就能在全新的 Ubuntu 16.04 服务器上运行[多个不同的科学上网工具](#提供的服务),它们能够让你匿名并且加密所有的网络流量。
* Streisand 原生支持多个 VPS 供应商,其中包括[亚马逊EC2](https://aws.amazon.com/ec2/),[微软云服务](https://azure.microsoft.com),[DigitalOcean](https://www.digitalocean.com/),[Google云计算](https://cloud.google.com/compute/),[Linode](https://www.linode.com/)和[Rackspace](https://www.rackspace.com/);随着软件的开发还将支持更多云和VPS——只要运行的是 Ubuntu 16.04 ,不论提供商是谁还是有**成百个**实例都能用这个方法部署。
* 整个部署过程顺利的话大概在10分钟左右搞定。试想一个没有系统管理能力的人可能要花数天来完成其中一项工作,而我们用 Streisand 让你获得获得开箱既得的畅快体验。
* 一旦部署完成,你可以将使用指南发送给你的朋友,家人和你觉得对你重要的人**(译者注:原文是社会活动家)**。在这个指南中包含唯一的一个 SSL 证书,这也意味着你发送给他们的只是一个简单的文件而已。
* 部署好网关中包含了用户需要的一切内容,例如设置向导,所支持操作系统需要的客户端。即使无法下载到官方客户端的朋友都可以在网关中的镜像里下载到需要的最新版本客户端。
* 这才是开始,来来来,看看后面更精彩...
更多特性
-------------
* 新用户登录时,使用 Nginx 提供密码保护和网关加密。加密网关通过 SSL 证书,或者通过 [Tor](https://www.torproject.org/docs/hidden-services.html.en)隐藏服务进行加密。
* 网关将自动生成客户端配置说明,架设在轻量级的 http 服务器 Nginx 上。而您可以用电脑或是手机的浏览器轻松阅读,只需按部就班就能轻松配置客户端了。
* 所有科学上网需要的客户端软件都进行了 SHA-256 检查,并且通过 GPG 进行了签名认证。确保那些无法通过官方渠道下载客户端的用户同样能够从镜像放心下载。
* 所有客户端需要的额外文件,比如:OpenVPN 的配置文件,都可以通过网关下载到。
* 目前 Tor 用户可以借助 Streisand 所提供的优秀特性传输大文件或者控制 Tor 服务其他流量(比如BT,传统的 Tor 并不适合进行BT这样的数据传输)。
* 网关会自动生成一个唯一的密码、一个 SSL 证书和一个 SSL 私钥。在Streisand部署后,网关说明和证书都通过 SSH 进行传输。
* 不同的服务和多个守护进程带来了巨大的灵活性。如果其中一个连接方式遭到封锁,还有其他方式可以尝试使用。它们大多数都能够避免深度包检测。
* OpenConnect/AnyConnect, OpenSSH(没有测试), OpenVPN (stunnel加持的), Shadowsocks, and Tor (obfs4进行混淆传输)都可以在中国使用
* 每一个科学上网工具都提供了文档和详细的描述。 Streisand 或许是迄今为止最为全面的指南,帮助你安装和配置客户端。在必要的时候也能够再次通过手动完成任何相关操作。
* 为了避免科学上网工具被大面积破坏,端口在设计上也是有讲究的。比方说 OpenVPN ,并没有运行在默认的1194端口,而是636端口,这个是很多跨国公司使用的标准 LDAP/SSL 连接端口。
提供的服务
-----------------
* [OpenSSH](https://www.openssh.com/)
* 支持 Windows 和 Android 的 SSH 隧道, 并且需要使用 PuTTY 将默认的密钥对导出成 .ppk 的格式;
* [Tinyproxy](https://banu.com/tinyproxy/) 默认安装并绑定到主机,它作为一个 http(s) 代理提供给那些原生不支持 SOCKS 代理的软件通过 SSH 隧道访问网络,比如说 Android 上的鸟嘀咕。
* 针对 [sshuttle](https://github.com/sshuttle/sshuttle) 的一个无特权转发用户和产生的 SSH 密钥对,同样也兼容 SOCKS;
* [OpenConnect](https://ocserv.gitlab.io/www/index.html) / [Cisco AnyConnect](https://www.cisco.com/c/en/us/products/security/anyconnect-secure-mobility-client/index.html)
* oepnConnect (ocserv) 是一个非常强劲、轻巧的 VPN 服务器,并且完全兼容思科的 AnyConnect 客户端;
* 其中包涵了很多顶级的标准[协议](https://ocserv.gitlab.io/www/technical.html),比如:HTTP, TLS 和 DTLS, 当然还有很多被跨国公司广泛使用的且流行的技术;
* 这就意味着 OpenConnect 非常易用且高速,而且经得住审查的考验,几乎从未被封锁。
* [OpenVPN](https://openvpn.net/index.php/open-source.html)
* 从自带的 .ovpn 配置文件生成一个简单的客户端配置文件;
* 同时支持 TCP 和 UDP 连接;
* 客户端的 DNS 解析由 [Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) 负责,避免 DNS 泄露;
* 启用 TLS 认证,有助于防止主动探测攻击。错误的 HMAC 流量并不会被轻易丢弃。
* [Shadowsocks](https://shadowsocks.org/en/index.html)
* 安装的是高性能的 libev 版本,这个版本能够处理数以千计的并发连接;
* Android 和 iOS 只需要扫描一个二维码就能完成自动配置。DNS 可以设置为 8.8.8.8,或者将配置一一复制粘贴到客户端上;
* 采用 ChaCha20 和 Poly1305 对 [AEAD](https://shadowsocks.org/en/spec/AEAD-Ciphers.html) 进行加密,增强了安全性并提升了穿透性;
* 使用 [simple-obfs](https://github.com/shadowsocks/simple-obfs) 插件提供流量混淆以便于从审查的网络中脱逃(尤其是QOS节流中)。
* [sslh](https://www.rutschle.net/tech/sslh/README.html)
* sslh 是一个协议解复用器(这个我不了解,如果有更好的翻译请request),在一个高度限制的网络环境下(只能访问 http 端口的网络为例),它作为一种备选方案,仍然可以通过 OpenSSH 和 OpenVPN 进行连接,因为通过 sslh 让二者共享了 443 端口。
* [Stunnel](https://www.stunnel.org/index.html)
* 监听并且将 OpenVPN 的流量进行封装,让 OpenVPN 的流量伪装成标注的 SSL 流量,从而可以让 OpenVPN 客户端成功通过隧道进行连接,躲避深度包检测。
* 通过隧道连接的 OpenVPN 的配置文件和直接连接 OpenVPN 的配置文件是一起生成的,详细的说明也一同生成。
* stunnel 证书和密钥是 PKCS #12 格式,SSL 隧道程序能够很好的兼容,尤其 [OpenVPN Android](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) 版本也能够通过 [SSLDroid](https://play.google.com/store/apps/details?id=hu.blint.ssldroid) 传输。在中国的移动设备上使用 OpenVPN 成为可能*(据译者所知,大陆 OpenVPN 以前完全阵亡)*。
* [Tor](https://www.torproject.org/)
* 桥接的名字是随即生成的;
* [Obfsproxy](https://www.torproject.org/projects/obfsproxy.html.en) 默认安装并且配置支持 obfs4 传输;
* Android 手机使用 [Orbot](https://play.google.com/store/apps/details?id=org.torproject.android) 扫描二维码即可获取桥接信息并完成自动配置。
* [UFW](https://wiki.ubuntu.com/UncomplicatedFirewall)
* 防火墙根据不同的服务完全配置好,任何未经授权的流量都将被阻止。
* [系统无人值守安全更新](https://help.ubuntu.com/community/AutomaticSecurityUpdates)
* Streisand 所在的服务器自动配置成无人值守更新,自动更新级别为*安全更新*。
* [WireGuard](https://www.wireguard.com/)
* Linux 用户可以使用下一代更加简化,基于内核的黑科技 VPN ,速度快,而且使用了很多之前 VPN 所没有加密类型。
安装
------------
在你搞事情之前,认真阅读
### 重要说明 ###
Streisand 基于 [Ansible](https://www.ansible.com/) ,它可以在远程服务器完成自动配置、打包等工作,Streisand 是将远程服务器自动配置成为多个 VPN 服务及科学上网的工具。
Streisand 运行在**你自己的计算机上时(或者你电脑的虚拟机上时)**,它将把网关部署到你 VPS 提供商的**另一个服务器**上(通过你自己的API自动生成)。另外,如果 Streisand 运行在 VPS 上,它将会把网关部署到**另一个 VPS 上**,所以说原先你运行 Streisand 的那个 VPS 就多余了,记得部署完成并获得文档后把它删掉,而部署出来的那个 VPS 你是无法使用 SSH 连接进去的,除非你有公钥(当然这是不可能的,因为整个配置过程都没有提供公钥给你下载或者你想办法把它搞出来)。
在某些情况下,你可能需要运行 Streisand/Ansible 在 VPS 上并将其自身配置为 Streisand 服务器,这种模式适合当你无法在你自己的计算机上运行和安装 Streisand/Ansible 时,或本地与 VPS 之间的 SSH 连接不稳定时。
### 准备工作 ###
在本地计算机完成以下所有步骤(也可以在 VPS 上运行)。
* Streisand 运行在 BSD,Linux,或者 macOS 上,Windows 上是无法运行的。所有的指令都需要在终端下运行。
* 需要 Python 2.7 ,一般在 macOS 、Linux 及 BSD 系统上都是标配,如果你使用的发行版标配是 Python 3,你需要安装 Python 2.7 来运行 Streisand。
* 确定你的 SSH key 储存在 ~/.ssh/id\_rsa.pub 。
* 如果不曾有过 SSH key,你需要用下面的命令生成一个:
ssh-keygen
* 安装 Git 。
* 基于 Debian 和 Ubuntu 的 Linux 发行版
sudo apt install git
* 在 Fedora
sudo dnf install git
* 在 macOS 上 (需要通过 [Homebrew](https://brew.sh/) 进行安装)
brew install git
* 利用 Python 安装 [pip](https://pip.pypa.io/en/latest/) 包管理
* 基于 Debian 和 Ubuntu 的 Linux 发行版
sudo apt install python-paramiko python-pip python-pycurl python-dev build-essential
* 在 Fedora
sudo dnf install python-pip
* 在 macOS 上
sudo easy_install pip
sudo pip install pycurl
* 安装 [Ansible](https://www.ansible.com/) 。
* 在 macOS 上
brew install ansible
* 在 Linux 和 其他 BSD 上
sudo pip install ansible markupsafe
* 以下使用 pip 安装的 Python 库根据你所使用的 VPS 供应商不同而不同。如果你准备将目前使用的 VPS 变成网关,可以跳过此步。
* 亚马逊 EC2
sudo pip install boto boto3
* 微软云服务
sudo pip install ansible[azure]
* Google
sudo pip install "apache-libcloud>=1.17.0"
* Linode
sudo pip install linode-api4
* Rackspace 云
sudo pip install pyrax
* **特别需要注意的是如果你使用 Python** 是通过 Homebrew 安装的,还需要运行以下命令来确定找到必要的库文件
mkdir -p ~/Library/Python/2.7/lib/python/site-packages
echo '/usr/local/lib/python2.7/site-packages' > ~/Library/Python/2.7/lib/python/site-packages/homebrew.pth
### 执行 ###
1. 从 Streisand 抓取源码
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
2. 执行 Streisand 脚本。
./streisand
3. 根据实际情况从弹出的问题中填写或选择选项,比如服务器的物理位置,它的名字。还有最重要的是 API 信息(可以从问题提示中找到如何提供 API 信息)。
4. 一旦登录信息和 API key 正确无误完成,Streisand 就开始安装到另一个 VPS 上了(或者把你目前的 VPS 变成网关)。
5. 整个配置完成大概需要10分钟左右的样子,完成后,在 Streisand 目录下会生成一个 'generated-docs' 文件夹,里面储存了4个 html 文件,其中包含了网关的 SSL 证书和如何连接的详细说明。当你使用这些方法连接上网关以后,网关里详细描述了设置客户端的方法、需要额外下载的文件,客户端镜像,密钥,只要耐心配置客户端就一切搞定了。
**译者注:到这里官方英文配置就告一段落了。译者在自己配置的过程中还遇到一些小麻烦,需要各位朋友注意。**
* 从本地用 Streisand 安装到网关的模式,如果能用这种模式最好,就不要选择其他的模式了,因为这样他生成的 generated-docs 就在本地,你用浏览器打开就能直接下载到证书文件,不折腾。
* 在 VPS 上用 Streisand 安装到新的 VPS 模式还有后面介绍的将正在运行的 VPS 转变为网关这种模式,你会发现你很难在 VPS 上阅读 generated-docs 文件夹中的4个 html 文档,这个时候有几种方法可选:
* 使用 sftp 下载文件;
* 在目前的 VPS 上安装一个 apache2 ,然后 cp -r generated-doc /var/www/html/ ,然后从浏览器输入 VPS 的地址直接浏览并下载密钥(严格地说,这不安全,因为不是 https 连接,如果截获了数据便可以知道如何登录你科学上网的那个网关了。**如果是使用转化那个模式,就不要用这种方法了**)。
* 在 VPS 上使用 scp 将 generated-docs 目录全部推送到你本地暴露在公网下的 Linux, Unix 或者 macOS 里,或者另一个 VPS 里也可以。命令大概是 scp -r generated-docs user@×××.×××.×××.×××:/home/user/
### 将正在使用中的 VPS 变成 Streisand 服务器 (高级使用) ###
如果你本地使用的计算机无法运行 Streisand ,你可以将正在运行的 VPS 转变为网关。只需要在 VPS 上运行 ./streisand 并在菜单中选择 "Localhost (Advanced)" 就可以了。
**但是需要注意的是**这个操作是无法挽回的,它将把你正在使用的 VPS 完全转变为网关后,之前如果你在上面搭建博客或者用于测试某些软件,那完成这个操作后,它们将不复存在。
### 在其他的 VPS 供应商上运行 (高级使用)###
你同样可以将 Streisand 运行在其他 VPS 供应商(提供更好的硬件也没问题,奇葩的 VPS 供应商也行)的 16.04 Ubuntu 上,只需要你在运行 ./streisand 的时候选择菜单中的 "Existing Server (Advanced)" 就可以。你需要提供这个 VPS 的 IP 地址。
这个 VPS 必须使用 `$HOME/.ssh/id_rsa` 来储存 SSH key,并且可以使用 **root** 作为默认用户登录 VPS,如果提供商没有给你 root 用户作为默认用户登录,而是别的用户名,比如:`ubuntu` ,那么在运行 `./streisand` 之前需要额外配置 `ANSIBLE_SSH_USER` 环境变量,比如修改为:`ANSIBLE_SSH_USER=ubuntu` 。
### 非交互式部署 (高级使用)###
如果你想做非交互式部署, 你可以在 `global_vars/noninteractive`找到配置文件和脚本文件。你需要在配置文件或命令行录入必要信息。
将 Streisand 在 VPS 供应商上运行:
deploy/streisand-new-cloud-server.sh \
--provider digitalocean \
--site-config global_vars/noninteractive/digitalocean-site.yml
将 Streisand 在正在使用中的服务器上运行:
deploy/streisand-local.sh \
--site-config global_vars/noninteractive/local-site.yml
将 Streisand 在已现有的服务器上运行 :
deploy/streisand-existing-cloud-server.sh \
--ip-address 10.10.10.10 \
--ssh-user root \
--site-config global_vars/noninteractive/digitalocean-site.yml
未来特性
-----------------
* 更简便的设置
如果你对 Streisand 有任何期待和想法,或者你找到 BUG ,请联系我们并且发 [Issue Tracker](https://github.com/StreisandEffect/streisand/issues) 。
核心的贡献者们
----------------
* Jay Carlson (@nopdotcom)
* Nick Clarke (@nickolasclarke)
* Joshua Lund (@jlund)
* Ali Makki (@alimakki)
* Daniel McCarney (@cpu)
* Corban Raun (@CorbanR)
相关知识
----------------
[Jason A. Donenfeld](https://www.zx2c4.com/) 凭借他的智慧和果敢重新设计一个现代的 VPN,就像我们看到的 [WireGuard](https://www.wireguard.com/) 。他非常耐心和认真的给予帮助并提供了优质的反馈,在此,向他表示我由衷的感谢。
对 [Trevor Smith](https://github.com/trevorsmith) 在项目上的付出,简直无法形容,非常感谢他,正是他提出了网关的提案,提供了数不胜数反馈,在公布前灵机一动,创建了 html 模板,让现在的**一切看上去那么屌**。
非常感谢 [Paul Wouters](https://nohats.ca/) 的 [The Libreswan Project](https://libreswan.org/) ,正是他的耐心调试和设置,才让 L2TP/IPsec 工作的那么好。
另外,[Joshua Lund](https://github.com/jlund)开始这个项目工作的时候,他差不多把 [Starcadian's](https://www.starcadian.com/) 的 'Sunset Blood' 听了300遍(译者:这张专辑节奏感不错)。
================================================
FILE: README-fr.md
================================================
- - -
[English](README.md), [Français](README-fr.md), [简体中文](README-chs.md), [Русский](README-ru.md) | [Miroir](https://gitlab.com/alimakki/streisand)
- - -
[](https://github.com/StreisandEffect/streisand/actions)
[](https://twitter.com/StreisandVPN)
Streisand
=========
**Silence la censure. Automatiser [l'effet](https://fr.wikipedia.org/wiki/Effet_Streisand).**
L'Internet peut être un peu injuste. Il est trop facile pour les fournisseurs de services Internet, les télécoms, les politiciens et les entreprises de bloquer l'accès aux sites et aux informations qui vous intéressent. Mais briser ces restrictions est *difficile*. Ou est-ce?
Présentation de Streisand
-------------------------
* Une seule commande configure un tout nouveau serveur Ubuntu 16.04 exécutant une [grande variété de logiciels anti-censure](#services-provided) qui peuvent masquer et chiffrer totalement votre trafic Internet.
* Streisand supporte nativement la création de nouveaux serveurs chez [Amazon EC2](https://aws.amazon.com/ec2/), [Azure](https://azure.microsoft.com/fr-fr/), [DigitalOcean](https://www.digitalocean.com/), [Google Compute Engine](Https://cloud.google.com/compute/), [Linode](https://www.linode.com/) et [Rackspace](https://www.rackspace.com/)— et plus de fournisseurs à venir! Il fonctionne également sur n'importe quel serveur Ubuntu 16.04 quel que soit le fournisseur, et des **centaines** d'instances peuvent être configurés simultanément en utilisant cette méthode.
* Le processus est entièrement automatisé et ne prend que quelques dizaines de minutes, ce qui est assez remarquable si vous considérez qu'il faudrait un administrateur système au moins plusieurs jours de contrainte pour mettre en place un petit sous-ensemble de ce que Streisand offre dans sa configuration.
* Une fois que votre serveur Streisand est en cours d'exécution, vous pouvez donner les instructions de connexion personnalisée à vos amis, membres de la famille et activistes. Les instructions de connexion contiennent une copie intégrée du certificat SSL unique du serveur, il vous suffit de leur envoyer un seul fichier.
* Chaque serveur est entièrement autonome et comprend tout ce dont les utilisateurs ont besoin pour démarrer, y compris les miroirs cryptographiquement vérifiés de tous les clients communs. Cela rend toute tentative de censure des emplacements de téléchargement par défaut complètement inefficace.
* Mais attendez, il y a plus..
Plus de fonctionnalités
-----------------------
* Nginx alimente la passerelle protégée par mot de passe et chiffrée qui sert de point de départ pour les nouveaux utilisateurs. La passerelle est accessible via SSL, ou comme [service caché](https://www.torproject.org/docs/hidden-services.html.en) Tor.
* Instructions belles, personnalisées, et étape par étape, les configurations du client sont générées pour chaque nouveau serveur que Streisand crée. Les utilisateurs peuvent accéder rapidement à ces instructions via n'importe quel navigateur Web. Les instructions sont réactives et fantastiques sur les téléphones mobiles.
* L'intégrité du logiciel mis en miroir est assurée en utilisant les sommes de contrôle SHA-256 ou en vérifiant les signatures GPG si le projet les fournit. Cela protège les utilisateurs contre le téléchargement de fichiers corrompus.
* Tous les fichiers auxiliaires, tels que les profils de configuration OpenVPN, sont également disponibles via la passerelle.
* Les utilisateurs actuels de Tor peuvent profiter des services supplémentaires que Streisand met en place pour transférer des fichiers volumineux ou pour traiter d'autres types de trafic (par exemple BitTorrent) qui ne sont pas appropriés pour le réseau Tor.
* Un mot de passe unique, un certificat SSL et une clé privée SSL sont générés pour chaque passerelle Streisand. Les instructions de la passerelle et le certificat sont transférés via SSH à la fin de l'exécution de Streisand.
* Des services distincts et des daemons multiples offrent une énorme flexibilité. Si une méthode de connexion est bloquée, il existe de nombreuses options disponibles, dont la plupart sont résistantes à l'inspection des paquets en profondeur.
* Toutes les méthodes de connexion (y compris les connexions directes OpenVPN) sont efficaces contre le type de blocage avec lequel la Turquie a expérimenté.
* OpenConnect/AnyConnect, OpenSSH, OpenVPN (enveloppé dans stunnel), Shadowsocks, Tor (avec obfsproxy et obfs4 transports enfichables), et WireGuard sont tous actuellement efficace contre le grand pare-feu de la Chine.
* Chaque tâche a été bien documentée et a donné une description détaillée. Streisand est simultanément le HOWTO le plus complet en existance pour l'installation de tous les logiciels qu'il installe, et aussi l'antidote pour avoir à faire jamais tout cela à la main de nouveau.
* Tous les logiciels fonctionnent sur des ports qui ont été délibérément choisis pour rendre le blocage de ports simpliste irréaliste sans causer de dommages collatéraux massifs. OpenVPN, par exemple, ne fonctionne pas sur le port défaut de 1194, mais utilise le port standard 636 pour les connexions LDAP/SSL qui sont aimés par des entreprises du monde entier.
Services fournis
----------------
* [OpenSSH](https://www.openssh.com/)
* Les tunnels Windows et Android SSH sont également pris en charge et une copie des clés sont exportée dans le format .ppk que PuTTY requiert.
* [Tinyproxy](https://banu.com/tinyproxy/) est installé et lié à localhost. Il peut être accédé sur un tunnel SSH par des programmes qui ne prennent pas en charge nativement SOCKS et qui nécessitent un proxy HTTP, comme Twitter pour Android.
* Un utilisateur de transfert non privilégié et une paire paire de clés asymétriques SSH sont générés pour les fonctionnalités [sshuttle](https://github.com/sshuttle/sshuttle) et SOCKS.
* [OpenConnect](https://ocserv.gitlab.io/www/index.html)/[Cisco AnyConnect](https://www.cisco.com/c/en/us/products/security/anyconnect-secure-mobility-client/index.html)
* OpenConnect (ocserv) est un serveur VPN extrêmement performant et léger qui offre également une compatibilité totale avec les clients officiels Cisco AnyConnect.
* Le [protocole](https://ocserv.gitlab.io/www/technical.html) est bâti sur des standards comme HTTP, TLS et DTLS, et c'est l'une des technologies VPN les plus populaires et largement utilisées parmi des grands entreprises multi-nationales.
* Cela signifie qu'en plus de sa facilité d'utilisation et de sa rapidité, OpenConnect est également très résistant à la censure et presque jamais bloqué.
* [OpenVPN](https://openvpn.net/index.php/open-source.html)
* Des profils autonome "unifiés" .ovpn sont générés pour une configuration de client facile en utilisant un seul fichier.
* Les connexions TCP et UDP sont prises en charge.
* La résolution DNS du client est gérée via [Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) pour empêcher les fuites DNS.
* L'authentification TLS est activée, ce qui permet de vous protéger contre les attaques actives. Le trafic qui n'a pas de HMAC approprié est simplement abandonné.
* [Shadowsocks](https://shadowsocks.org/en/index.html)
* La [variante libev](https://github.com/shadowsocks/shadowsocks-libev) haute performance est installée. Cette version est capable de gérer des milliers de connexions simultanées.
* Un code QR est généré qui peut être utilisé pour configurer automatiquement les clients Android et iOS en prenant simplement une photo. Vous pouvez étiqueter "8.8.8.8" sur ce mur de béton, ou vous pouvez coller les instructions de Shadowsocks et quelques codes QR à la place!
* [AEAD](https://shadowsocks.org/fr/spec/AEAD-Ciphers.html) est activé avec ChaCha20 et Poly1305 pour un contournement plus efficace du GFW.
* Le plugin [simple-obfs](https://github.com/shadowsocks/simple-obfs) est installé afin de fournir une techique d'évasion du votre trafic sur des réseaux hostiles (en particulier ceux qui appliquent la limitation de la qualité de service (QOS)).
* [sslh](https://www.rutschle.net/tech/sslh/README.html)
* Sslh est un démultiplexeur de protocole qui permet à Nginx, OpenSSH et OpenVPN de partager le port 443. Cela fournit une autre option de connexion et signifie que vous pouvez toujours acheminer le trafic via OpenSSH et OpenVPN même si vous êtes sur un réseau restrictif qui bloque tout accès à des ports non HTTP.
* [Stunnel](https://www.stunnel.org/index.html)
* Écoute et enveloppe les connexions OpenVPN. Cela les fait ressembler au trafic SSL standard et permet aux clients OpenVPN d'établir avec succès des tunnels même en présence d'une inspection approfondie des paquets.
* Des profils unifiés pour les connexions OpenVPN enveloppées de stunnel sont générés à côté des profils de connexion directe. Des instructions détaillées sont également générées.
* Le certificat stunnel et la clé sont exportés au format PKCS # 12 afin qu'ils soient compatibles avec d'autres applications de tunneling SSL. Notamment, cela permet à [OpenVPN pour Android](https://play.google.com/store/apps/details?id=de.blinkt.openvpn&hl=fr) de tunneliser son trafic via [SSLDroid](https://play.google .com / store / apps / details? Id = hu.blint.ssldroid). OpenVPN en Chine sur un appareil mobile? Oui!
* [Tor](https://www.torproject.org/)
* Un [pont relais](https://www.torproject.org/docs/bridges) est mis en place avec un surnom aléatoire.
* [Obfsproxy](https://www.torproject.org/projects/obfsproxy.html.en) est installé et configuré avec le support pour le transport enfichable obfs4.
* Un code BridgeQR est généré et peut être utilisé pour configurer automatiquement [Orbot](https://play.google.com/store/apps/details?id=org.torproject.android&hl=fr) pour Android.
* [UFW](https://wiki.ubuntu.com/UncomplicatedFirewall)
* Les règles de pare-feu sont configurées pour chaque service et tout trafic qui est envoyé vers un port non autorisé sera bloqué.
* [unattended-upgrades](https://help.ubuntu.com/community/AutomaticSecurityUpdates)
* Votre serveur Streisand est configuré pour installer automatiquement de nouvelles mises à jour de sécurité.
* [WireGuard](https://www.wireguard.com/)
* Les utilisateurs Linux peuvent profiter d'un VPN de nouvelle génération qui est simple mais à la même fois moderne, basé dans le noyau, et utilise des principes cryptographiques modernes que toutes les autres solutions VPN ne fournissent pas.
Installation
------------
Veuillez lire *attentivement* toutes les instructions d'installation avant de poursuivre.
### Clarification importante ###
Streisand est basé sur [Ansible](https://www.ansible.com/), un outil d'automatisation qui est généralement utilisé pour fournir et configurer des fichiers et des paquets sur des serveurs distants. Cela signifie que lorsque vous exécutez Streisand, il configure automatiquement **un autre serveur distant** avec les paquets VPN et ses configurations.
Streisand va déployer **un autre serveur** sur votre fournisseur d'hébergement choisi lorsque vous exécutez **sur votre ordinateur local** (par exemple, votre ordinateur portable). Habituellement, vous **n'utilisez pas Streisand sur le serveur distant** car, par défaut, cela entraînerait le déploiement d'un autre serveur à partir de votre serveur et rendrait le premier serveur redondant (Ouf!).
Dans certains cas, les utilisateurs avancés peuvent opter pour le mode de provisionnement local pour que le système fonctionne avec Streisand/Ansible se configure comme un serveur Streisand. Il s'agit d'un mode de configuration mieux réservé quand ce n'est pas possible d'installer Ansible sur votre ordinateur local ou lorsque votre connexion à un fournisseur de cloud est peu fiable pour les connexions SSH requis par Ansible.
### Prérequis ###
Effectuez toutes ces tâches sur votre machine locale.
* Streisand nécessite un système BSD, Linux ou macOS. À partir de maintenant, Windows n'est pas soutenu. Toutes les commandes suivantes doivent être exécutées à l'intérieur d'une session Terminal.
* Python 2.7 est nécessaire. Cela est standard sur macOS, et est la valeur par défaut sur presque toutes les distributions Linux et BSD. Si votre distribution emploie Python 3 à la place, vous devrez installer la version 2.7 pour que Streisand fonctionne correctement.
* Assurez-vous qu'une clé publique SSH est présente dans ~/.ssh/id\_rsa.pub.
* Les clés SSH constituent une alternative plus sécurisé aux mots de passe qui vous permettent de prouver votre identité à un serveur ou à un service basé sur la cryptographie à clé publique. Fondamentalement, la clé publique est quelque chose que vous pouvez partager aux autres, alors que la clé privée doit être gardée secrète (comme un mot de passe).
* Pour vérifier si vous avez déjà une clé publique SSH, entrez la commande suivante à l'invite de commande.
ls ~/.ssh
* Si vous voyez un fichier id_rsa.pub, vous avez une clé publique SSH.
* Si vous n'avez pas de paire de clés SSH, vous pouvez en générer une en utilisant cette commande et en suivant les valeurs par défaut:
ssh-keygen
* Si vous souhaitez utiliser une clé SSH avec un nom différent ou dans un emplacement non standard, veuillez entrer 'oui' lorsqu'on vous demande si vous souhaitez personnaliser votre instance lors de l'installation.
* **Notez**: Vous aurez besoin de ces clés pour accéder à votre instance Streisand via SSH. Conservez-les pour la durée de vie de votre serveur Streisand.
* Installez Git.
* Sur Debian et Ubuntu
sudo apt-get install git
* Sur Fedora 27, certains progiciels sont nécessaires plus tard
sudo dnf install git python2-pip gcc python2-devel python2-crypto python2-pycurl libcurl-devel
* Sur CentOS 7, `pip` est disponible dans le dépôt EPEL; certains progiciels supplémentaires sont nécessaires plus tard.
sudo yum -y update && sudo yum install -y epel-release
sudo yum -y update && sudo yum install -y git gcc python-devel python-crypto python-pycurl python-pip libcurl-devel
* Sur macOS, `git` fait partie des outils de développement et sera installé la première fois que vous l'exécuterez. S'il n'y a pas déjà une commande `pip` installée, installez-la avec:
sudo python2.7 -m ensurepip
### Exécution ###
1. Clonez le répertoire Streisand et entrez dans le répertoire.
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
2. Exécutez le programme d'installation pour Ansible et ses dépendances.
./util/venv-dependencies.sh ./venv
* Le programme d'installation détectera les progiciels manquants et imprimera les commandes nécessaires pour les installer.
3. Activez les progciels Ansible installés.
source ./venv/bin/activate
4. Exécutez le script Streisand.
./streisand
5. Suivez les instructions pour choisir votre fournisseur, la région physique du serveur, et son nom. Vous serez également invité à entrer les informations de l'API.
6. Une fois les informations de connexion et les clés d'API saisies, Streisand commencera à faire tourner un nouveau serveur distant.
5. Attendez que l'installation soit terminée (cela prend habituellement environ dix minutes) et recherchez les fichiers correspondants dans le dossier 'generated-docs' dans le répertoire du dépôt Streisand. Le fichier HTML expliquera comment se connecter à la passerelle via SSL ou via le service caché Tor. Toutes les instructions, les fichiers, les clients en miroir et les clés du nouveau serveur se trouvent alors sur la passerelle. Vous avez fini!
### Installation de Streisand sur localhost (Avancé) ###
Si vous ne pouvez pas exécuter Streisand de la manière normale (à partir de votre ordinateur client/ordinateur portable pour configurer un serveur distant), Streisand prend en charge un mode de provisionnement local. Choisissez simplement "Localhost (Advanced)" dans le menu après avoir exécuté `./streisand`.
**Note:** L'installation de Streisand sur localhost peut être une action destructive! Vous pourriez potentiellement écraser des fichiers de configuration; vous devez être certain que vous affectez la machine correcte.
### Exécution de Streisand sur d'autres fournisseurs (Avancé) ###
Vous pouvez également exécuter Streisand sur un nouveau serveur Ubuntu 16.04. Serveur dédié? Génial! Fournisseur de cloud ésotérique? Fantastique! Pour ce faire, choisissez simplement `Existing server (Advanced)` dans le menu après avoir exécuté `./streisand` et fournissez l'adresse IP du serveur existant lorsque vous y êtes invité.
Le serveur doit être accessible en utilisant la clé SSH `$HOME/.ssh/id_rsa`, avec **root** comme utilisateur de connexion par défaut. Si votre fournisseur vous demande un utilisateur SSH au lieu de `root` (par exemple, `ubuntu`), spécifiez la variable environnementale `ANSIBLE_SSH_USER` (par exemple `ANSIBLE_SSH_USER=ubuntu`) lorsque vous exécutez `./streisand`.
**Note:** L'installation de Streisand sur localhost peut être une action destructive! Vous pourriez potentiellement écraser des fichiers de configuration; vous devez être certain que vous affectez la machine correcte.
### Déploiement non interactif (Avancé) ###
Des scripts alternatifs et des exemples de fichiers de configuration sont fournis pour les déploiements non interactifs, dans lequel toutes les informations requises sont transmises sur la ligne de commande ou dans un fichier de configuration.
Des exemples de fichiers de configuration se trouvent sous `global_vars/noninteractive`. Copiez et modifiez les paramètres souhaités, tels que la fourniture de jetons d'API et d'autres choix, puis exécutez le script.
Pour déployer un nouveau serveur Streisand:
deploy/streisand-new-cloud-server.sh \
--provider digitalocean \
--site-config global_vars/noninteractive/digitalocean-site.yml
Pour exécuter l'approvisionnement Streisand sur la machine locale:
deploy/streisand-local.sh \
--site-config global_vars/noninteractive/local-site.yml
Pour exécuter l'approvisionnement Streisand contre un serveur existant:
deploy/streisand-existing-cloud-server.sh \
--ip-address 10.10.10.10 \
--ssh-user root \
--site-config global_vars/noninteractive/digitalocean-site.yml
Nouvelles fonctionnalités à venir
---------------------------------
* Configuration simplifiée.
S'il ya quelque chose que vous pensez que Streisand devrait faire, ou si vous trouviez un bug dans sa documentation ou son exécution, s'il vous plaît déposer un rapport sur le [Issue Tracker](https://github.com/StreisandEffect/streisand/issues).
Contributeurs principaux
------------------------
* Jay Carlson (@nopdotcom)
* Nick Clarke (@nickolasclarke)
* Joshua Lund (@jlund)
* Ali Makki (@alimakki)
* Daniel McCarney (@cpu)
* Corban Raun (@CorbanR)
Remerciements
-------------
[Jason A. Donenfeld](https://www.zx2c4.com/) mérite beaucoup de crédit pour être assez courageux à réimaginer ce qu'est un VPN moderne devrait ressembler et pour mettre au monde quelque chose aussi épatant que [WireGuard](https://www.wireguard.com/). Il a nos sincères remerciements pour toute son aide, patience et ses commentaires.
[Corban Raun](https://github.com/CorbanR) à eu la gentillesse de me prêter un ordinateur portable Windows qui m'a permi de tester et d'affiner les instructions pour cette plate-forme, aussi bien qu'il était un grand partisan du projet dès le début.
Nous sommes reconnaissants à [Trevor Smith](https://github.com/trevorsmith) pour ses contributions massives au projet. Il a suggéré l'approche passerelle, fourni des tonnes de commentaires inestimable, a fait *tout* pour apparaître mieux, et développé le modèle HTML qui a servi d'inspiration pour faire passer les choses au niveau suivant avant la diffusion publique de Streisand. J'ai également apprécié l'utilisation fréquente de son iPhone tout en testant des clients divers.
Un grand merci à [Paul Wouters](https://nohats.ca/) de [The Libreswan Projet](https://libreswan.org/) à son aide généreuse pour le débogage des configurations d'L2TP/IPsec.
L'album 'Sunset Blood' de [Starcadian](https://starcadian.com/) a été répété environ 300 fois au cours des premiers mois de travail sur le projet au début de 2014.
================================================
FILE: README-ru.md
================================================
- - -
[English](README.md), [Français](README-fr.md), [简体中文](README-chs.md), [Русский](README-ru.md) | [Зеркало](https://gitlab.com/alimakki/streisand)
- - -
[](https://github.com/StreisandEffect/streisand/actions)
[](https://twitter.com/StreisandVPN)
Стрейзанд
=========
**Заставьте цензуру замолчать. Автоматизируйте [эффект Стрейзанд](https://ru.wikipedia.org/wiki/Эффект_Стрейзанд).**
Интернет может быть немножечко несправедливым. Провайдерам, телекоммуникационным гигантам, политикам и корпорациям слишком просто блокировать доступ к сайтам и информации, которая важна для вас. Но преодолеть эти ограничения сложно. Или нет?
Представляем Стрейзанд
---------------------
* Одна-единственная команда настраивает с нуля сервер под операционной системой Ubuntu 16.04 с большим набором [ПО для противодействия цензуре](#services-provided), который может полностью скрыть и зашифровать весь ваш трафик.
* Стрейзанд поддерживает создание новых серверов в [Amazon EC2](https://aws.amazon.com/ec2/), [Azure](https://azure.microsoft.com), [DigitalOcean](https://www.digitalocean.com/), [Google Compute Engine](https://cloud.google.com/compute/), [Linode](https://www.linode.com/), и [Rackspace](https://www.rackspace.com/). В скором времени ожидается поддержка также и других облачных хостеров. Стрейзанд также можно запускать на любом сервере с операционной системой Ubuntu 16.04 вне зависимости от хостера, и **сотни** серверов могут быть одновременно сконфигурированы с применением этого метода.
* Процесс полностью автоматизирован и занимает примерно десять минут, что довольно круто, учитывая что среднему системному администратору требуется несколько дней возни, для того, чтобы настроить малую часть того, что Стрейзанд предлагает "из коробки".
* После того, как ваш сервер Стрейзанд запущен, вы можете раздать инструкции по подключению друзьям, членам семьи и соратникам. Инструкции по подключению содержат в себе копию SSL-сертификата, уникального для каждого сервера, так что вам нужно послать им всего один файл.
* Каждый сервер полностью самодостаточен и содержит абсолютно всё, что нужно для того, чтобы начать использовать Стрейзанд, включая криптографически верифицированные копии основного клиентского ПО. Это позволяет обойти попытки подвергнуть цензуре соответствующее ПО.
* Но это еще не всё...
Дополнительные особенности
-------------
* Nginx поддерживает защищённый паролем и зашифрованный Портал, который служит отправной точкой для новых пользователей. Портал доступен с ипользованием SSL или через [скрытые сервисы](https://www.torproject.org/docs/hidden-services.html.en) Tor.
* Стрейзанд генерирует замечательные, персонализированные пошаговые инструкции по подключению для пользователей. Пользователи могут легко получить доступ к этим инструкциям через любой веб браузер. Инструкции также отлично выглядят на мобильных телефонах.
* Неизменность копий программного обеспечения подтверждена с помощью контрольных сумм SHA-256 или с использованием криптографических подписей GPG, если конкретный проект их предоставляет. Это предотвращает загрузку испорченных файлов.
* Все дополнительные файлы, такие как конфигурационные профили OpenVPN также доступны через Портал.
* Пользователи Tor могут также пользоваться дополнительными сервисами, устанавливаемыми Стрейзанд, для передачи больших файлов или для использования видов трафика (например BitTorrent), для которых Tor изначально не предназначен.
* Для каждого шлюза Стрейзанд создается уникальный пароль, SSL-сертификат и приватный ключ SSL. Инструкции и сертификат передаются через SSH в конце выполнения Стрейзанд.
* Отдельные сервисы и множество демонов предоставляют впечатляющую гибкость. Если один из методов будет заблокирован, множество других остается доступными и большая часть из них устойчива к Deep Packet Inspection (DPI).
* Все методы подключения (включая прямые соединения OpenVPN) эффективны против методов блокировки, с которыми экспериментирует Турция.
* OpenConnect/AnyConnect, OpenSSH, OpenVPN (завернутый в stunnel), Shadowsocks, Tor (с obfsproxy и подключаемым транспортом obfs4 ) и WireGuard эффективны против Великого Китайского Файрволла.
* Каждая задача тщательно документирована и снабжена детальным описанием. Стрейзанд одновременно является самым полным HOWTO об установке всего ПО, которое он включается и является страховкой от установки всего этого руками.
* Всё ПО сознательно использует порты так, чтобы сделать простое блокирование портов невозможным без нанесения блокирующей стороной значительного сопутствующего ущерба. К примеру, OpenVPN использует не порт по умолчанию 1194, а 636, стандартный порт для LDAP/SSL соединений, часто используемый компаниями во всем мире.
Предоставляемые сервисы
-----------------
* [OpenSSH](https://www.openssh.com/)
* Создается непривилегированный пользователь и пара ключей для [sshuttle](https://github.com/sshuttle/sshuttle) и SOCKS.
* Поддерживаются также SSH-туннели Windows и Android, создается копия пары ключей в .ppk формате для PuTTY
* Установлен [Tinyproxy](https://banu.com/tinyproxy/) и подключен к localhost. Программы, которые не поддерживают SOCKS и требуют наличия HTTP proxy, такие как Twitter для Android, могу подключиться к нему через SSH-туннель.
* [OpenConnect](https://ocserv.gitlab.io/www/index.html) / [Cisco AnyConnect](https://www.cisco.com/c/en/us/products/security/anyconnect-secure-mobility-client/index.html)
* OpenConnect (ocserv) - высокопроизводительный и легковесный VPN-сервер полностью совместимый с официальными клиентами Cisco AnyConnect.
* Его [протокол](https://ocserv.gitlab.io/www/technical.html) построен на классических стандартах, таких как HTTP, TLS и DTLS и является одним из самых популярных и широко используемых мультинациональными корпорациями VPN технологий.
* Это означает, что кроме своей простоты и скорости, OpenConnect также устойчив к цензуре и практически никогда не блокируется.
* [OpenVPN](https://openvpn.net/index.php/open-source.html)
* Для каждого клиента создаются унифицированные .ovpn профили для простой настройки клиента с использованием только одного файла.
* Поддерживаются соединения TCP и UDP.
* Определение адресов для клиента исползует [Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) для предотвращения утечек DNS-запросов.
* Включена TLS Authentication для защиты от зондирующих атак. Трафик не имеющий корректного HMAC будет попросту проигнорирован.
* [Shadowsocks](https://shadowsocks.org/en/index.html)
* Установлен высокопроизводительный [вариант libev](https://github.com/shadowsocks/shadowsocks-libev). Эта версия обрабатывает тысячи одновременных соединений.
* Создается QR код который можно использовать для автоматической настройки Android и iOS клиентов. Вы можете написать '8.8.8.8' на бетонной стене, или вы можете наклеить инструкции для Shadowsocks и QR коды на ту же стену.
* Включена поддержка [AEAD](https://shadowsocks.org/en/spec/AEAD-Ciphers.html) с ChaCha20 и Poly1305 для усиленной безопасности и уклонения от GFW.
* [sslh](https://www.rutschle.net/tech/sslh/README.html)
* Sslh - демультиплексор протоколов, позволяющий Nginx, OpenSSH и OpenVPN совместно использовать порт 443. Это предоставляет альтернативный метод подключения и означает, что вы можете перенаправлять трафик через OpenSSH и OpenVPN даже если вы находитесь в сети с очень строгими правилами, которая блокирует все соединения не с HTTP.
* [Stunnel](https://www.stunnel.org/index.html)
* Слушает и упаковывает соединения OpenVPN. Это заставляет их выглядеть как стандартный SSL трафик и позволяет OpenVPN клиентам устанавливать туннели даже в случае использования Deep Packet Inspection.
* Создаются как профили для прямых соединений, так и унифицированные профили для соединений OpenVPN через stunnel. И подробные инструкции тоже.
* Сертификат stunnel и ключ экспортируются в формате PKCS #12 для совместимости с другими приложениями для туннелирования SSL. В частности , это позволяет [OpenVPN for Android](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) туннелировать свой трафик через [SSLDroid](https://play.google.com/store/apps/details?id=hu.blint.ssldroid). OpenVPN в Китае на мобильном устройстве? Да!
* [Tor](https://www.torproject.org/)
* Настроен [bridge relay](https://www.torproject.org/docs/bridges) со случайно сгенерированным именем.
* Установлен [Obfsproxy](https://www.torproject.org/projects/obfsproxy.html.en) и настроен с поддержкой подключаемого транспорта obfs4.
* Сгенерирован код BridgeQR для автоматического конфигурирования [Orbot](https://play.google.com/store/apps/details?id=org.torproject.android) для Android.
* [UFW](https://wiki.ubuntu.com/UncomplicatedFirewall)
* Для каждого сервиса настроены правила файрвола, так что любой трафик отправленный на запрещенный порт будет заблокирован.
* [unattended-upgrades](https://help.ubuntu.com/community/AutomaticSecurityUpdates)
* Ваш Стрейзанд сервер настроен для автоматической установки обновлений, связанных с безопасностью.
* [WireGuard](https://www.wireguard.io/)
* Пользователи Linux могут насладиться простым и прекрасным VPN, который также является сказочно быстрым и использует современные криптографические принципы, отсутствующие в других высокоскоростных VPN решениях
Установка
------------
Пожалуйста, **внимательно** прочитайте инструкции по установке перед тем, как продолжать.
### Важное разъяснение ###
Стрейзанд основан на [Ansible](https://www.ansible.com/), инструменте автоматизации, который обычно используется для установки и настройки файлов и пакетов на удалённых серверах. Стрейзанд автоматически создает **новый удалённый сервер** с пакетами и конфигурационными файлами VPN.
Когда вы запустите Стрейзанд **на вашей домашней машине** (например на вашем лэптопе), он создаст и запустит **новый отдельный сервер** у хостера по вашему выбору. Обычно, вам **не надо запускать Стрейзанд на удалённом сервере** , так как по умолчанию это приведет к созданию нового сервера с вашего текущего сервера и первый сервер будет излишним. (фух!).
При некоторых обстоятельствах продвинутые пользователи могут воспользоваться локальным методом настройки чтобы настроить сервер Стрейзанд на той же машине, где запущен Стрейзанд/Ansible. Этот способ конфигурации стоит использовать для ситуаций когда вы не можете установить Ansible на вашем домашнем компьютере или когда ваше соединение с облачным хостером слишком ненадежно для работы Ansible.
### Необходимые условия ###
Выполните все указанные ниже шаги на вашем домашнем компьютере.
* Стрейзанд требует BSD, Linux или macOS. На текущий момент Windows не поддерживается. Все указанные ниже команды должны выполняться в терминале.
* Требуется наличие Python 2.7. Он присутствует в стандартной поставке macOS и практически во всех Linux и BSD дистрибутивах. Если в вашем дистрибутиве установлен Python 3, вам потребуется также установить Python 2.7 , чтобы Стрейзанд работал нормально.
* Убедитесь, что открытый SSH ключ присутствует в файле ~/.ssh/id\_rsa.pub.
* SSH ключи - это более защищенная альтернатива паролям, позволяющая подтвердить вашу личность на сервере или службе, построенной на криптографии с открытым ключом. Открытый ключ вы можете передавать другим, в то время как закрытый ключ должен храниться в тайне (так же как пароль).
* Для того, чтобы проверить, есть ли у вас открытый SSH ключ, введите следущую комманду:
ls ~/.ssh
* Если вы видите файл id\_rsa.pub, значит у вас есть открытый SSH ключ.
* Если у вас нет пары SSH ключей, вы можете ее сгенерировать с использованием следующей команды и выбирая значения по умолчанию:
ssh-keygen
* Если вы хотите использовать SSH ключи с другим именем или в другом местоположении, введите 'yes' когда установщик спросит хотите ли вы настроить сервер.
* **Обратите внимание**: Эти ключи будут вам нужны для доступа к серверу Стрейзанд по SSH. Пожалуйста, сохраняйте их на протяжении всей жизни сервера.
* Установите Git.
* На Debian и Ubuntu
sudo apt-get install git
* На Fedora
sudo dnf install git
* На macOS (с использованием [Homebrew](https://brew.sh/))
brew install git
* Установите [pip](https://pip.pypa.io/en/latest/) - систему управления пакетами для Python.
* На Debian и Ubuntu (также устанавливает зависимости. необходимые для сборки Ansible и работы некоторых других модулей)
sudo apt-get install python-paramiko python-pip python-pycurl python-dev build-essential
* На Fedora
sudo dnf install python-pip
* На macOS
sudo easy_install pip
sudo pip install pycurl
* Установите [Ansible](https://www.ansible.com/).
* На macOS (с использованием [Homebrew](http://brew.sh/))
brew install ansible
* На BSD или Linux (с использованием pip)
sudo pip install ansible markupsafe
* Установите необходимые библиотеки Python для вашего облачного хостера. Если вы настраиваете локальный или существующий сервер, вы можете пропустить этот шаг.
* Amazon EC2
sudo pip install boto boto3
* Azure
sudo pip install ansible[azure]
* Google
sudo pip install "apache-libcloud>=1.17.0"
* Linode
sudo pip install linode-api4
* Rackspace Cloud
sudo pip install pyrax
* **Важное замечание: если вы используете Python , установленный через Homebrew** то вы должны также выполнить следующие команды чтобы быть уверенным, что Python сможет найти необходимые библиотеки:
mkdir -p ~/Library/Python/2.7/lib/python/site-packages
echo '/usr/local/lib/python2.7/site-packages' > ~/Library/Python/2.7/lib/python/site-packages/homebrew.pth
### Выполнение ###
1. Склонируйте репозиторий Стрейзанд и перейдите в директорию
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
2. Запустите скрипт Стрейзанд.
./streisand
3. Следуйте инструкциям для выбора вашего хостера, региона, где будет запущен сервер и его имени. Вам также потребуется ввести информацию об API.
4. После того, как логины и API ключи предоставлены, Стрейзанд начинает создавать новый удалённый сервер.
5. Подождите, пока установка будет завершена (это обычно занимает примерно десять минут) и вы найдете файл в папке 'generated-docs' в директории репозитория Стрейзанд. HTML файл содержит инструкции как подключиться к шлюзу через SSL или через Tor. Все инструкции, файлы, копии клиентского ПО и ключ для нового сервера расположены на портале. Всё готово!
### Использование Стрейзанд для настройки локального сервера (Для продвинутых) ###
Для случаев, когда вы не можете запустить Стрейзанд как обычно (с вашего домашнего компьютера или лэптопа), с тем, чтобы сконфигурировать удалённый сервер, Стрейзанд поддерживает локальный метод настройки. Просто выберите "Localhost (Advanced)" из меню, после того, как запустили `./streisand`.
**Замечание:** Запуск Стрейзанд для настройки локального сервера может что-нибудь испортить. Возможно, вы перезапишете конфигурационные файлы, поэтому будьте уверены, что вы настраиваете правильный сервер.
### Использование Стрейзанд для других хостеров (Для продвинутых) ###
Вы также можете запустить Стрейзанд на любом сервере Ubuntu 16.04. Выделенный сервер? Отлично! Странный облачный хостер? Замечательно! Чтобы это сделать, просто выберите
"Existing Server (Advanced)" из меню после запуска `./streisand` и введите IP адрес существующего сервера , когда скрипт запросит эти данные.
Этот сервер должен разрешать подключение с SSH-ключом `$HOME/.ssh/id_rsa` и по умолчанию для подключения будет использоваться пользователь **root**. Если ваш хостер требует, чтобы для подключения использовался какой-то другой пользователь (например `ubuntu`), установите переменную среды `ANSIBLE_SSH_USER` (например `ANSIBLE_SSH_USER=ubuntu` ) перед запуском `./streisand`.
**Замечание:** Запуск Стрейзанд для настройки существующего сервера может что-нибудь испортить. Возможно, вы перезапишете конфигурационные файлы, поэтому будьте уверены, что вы настраиваете правильный сервер.
Будущие возможности
-------------------
* Более простая установка.
Если у вас есть идея, что ещё может делать Стрейзанд или вы нашли баг в документации или коде, пожалуйста, оставьте сообщение в [Issue Tracker](https://github.com/StreisandEffect/streisand/issues).
Ключевые разработчики
---------------------
* Jay Carlson (@nopdotcom)
* Nick Clarke (@nickolasclarke)
* Joshua Lund (@jlund)
* Ali Makki (@alimakki)
* Daniel McCarney (@cpu)
* Corban Raun (@CorbanR)
Благодарности
-------------
[Jason A. Donenfeld](https://www.zx2c4.com/) заслуживает множество благодарностей за смелое представление о том, как может выглядеть современный VPN и за то, что он создал такую отличную штуку как [WireGuard](https://www.wireguard.io/). Искреннее спасибо за его терпеливую помощь и отличную обратную связь.
Мы благодарны [Trevor Smith](https://github.com/trevorsmith) за его огромный вклад в проект. Он предложил подход с использованием портала, дал множество бесценных комментариев. С его помощью *всё* стало выглядеть лучше, он создал шаблон HTML, который вдохновил меня поднять всё на новый уровень перед официальным запуском.
Огромное спасибо [Paul Wouters](https://nohats.ca/) из [The Libreswan Project](https://libreswan.org/) за его великодушную помощь в отладке инсталляции L2TP/IPsec.
Альбом 'Sunset Blood' группы [Starcadian's](https://www.starcadian.com/) был прослушан примерно 300 раз в цикле в течение первых месяцев работы над этим проектом в начале 2014 года.
================================================
FILE: README.md
================================================
# Streisand
- - -
[English](README.md), [Français](README-fr.md), [简体中文](README-chs.md), [Русский](README-ru.md) | [Mirror](https://gitlab.com/alimakki/streisand)
- - -
[](https://github.com/StreisandEffect/streisand/actions)
[](https://twitter.com/StreisandVPN)
Streisand
=========
**Silence censorship. Automate the [effect](https://en.wikipedia.org/wiki/Streisand_effect).**
The Internet can be a little unfair. It's way too easy for ISPs, telecoms, politicians, and corporations to block access to the sites and information that you care about. But breaking through these restrictions is *tough*. Or is it?
If you have an account with a cloud computing provider, Streisand can set up a new node with many censorship-resistant VPN services nearly automatically. You'll need a little experience with a Unix command-line. (But without Streisand, it could take days for a skilled Unix administrator to configure these services securely!) At the end, you'll have a private website with software and instructions.
Here's what **[a sample Streisand server](http://streisandeffect-demo.s3-website.us-east-2.amazonaws.com/)** looks like.
There's a [list of supported cloud providers](#cloud-providers); experts may be able to use Streisand to install on many other cloud providers.
## VPN services
One type of tool that people use to avoid network censorship is a Virtual Private Network (VPN). There are many kinds of VPNs.
Not all network censorship is alike; in some places, it changes from day to day. Streisand provides many different VPN services to try. (You don't have to install them all, though.)
Some Streisand services include add-ons for further censorship and throttling resistance:
* [OpenSSH](https://www.openssh.com/)
* [Tinyproxy](https://banu.com/tinyproxy/) may be used as an HTTP proxy.
* [OpenConnect](https://ocserv.gitlab.io/www/index.html) / [Cisco AnyConnect](https://www.cisco.com/c/en/us/products/security/anyconnect-secure-mobility-client/index.html)
* This protocol is widely used by multi-national corporations, and might not be blocked.
* [OpenVPN](https://openvpn.net/index.php/open-source.html)
* [Stunnel](https://www.stunnel.org/index.html) add-on available.
* [Shadowsocks](https://shadowsocks.org/en/index.html),
* The [V2ray-plugin](https://github.com/shadowsocks/v2ray-plugin) is installed to provide robust traffic evasion on hostile networks (especially those implementing quality of service (QOS) throttling).
* A private [Tor](https://www.torproject.org/) bridge relay
* [Obfsproxy](https://www.torproject.org/projects/obfsproxy.html.en) with obfs4 available as an add-on.
* [WireGuard](https://www.wireguard.com/), a modern high-performance protocol.
See also:
* A [more technical list of features](Features.md)
* A [more technical list of services](Services.md)
## Cloud providers
* Amazon Web Services (AWS)
* Microsoft Azure
* Digital Ocean
* Google Compute Engine (GCE)
* Linode
* Rackspace
#### Other providers
We recommend using one of the above providers. If you are an expert and can set up a *fresh Ubuntu 16.04 server* elsewhere, there are "localhost" and "existing remote server" installation methods. For more information, see [the advanced installation instructions](Advanced%20installation.md).
## Installation
You need command-line access to a Unix system. You can use Linux, BSD, or macOS; on Windows 10, the Windows Subsystem for Linux (WSL) counts as Linux.
Once you're ready, see the [full installation instructions](Installation.md).
## Things we want to do better
Aside from a good deal of cleanup, we could really use:
* Easier setup.
* Faster adoption of new censorship-avoidance tools
We're looking for help with both.
If there is something that you think Streisand should do, or if you find a bug in its documentation or execution, please file a report on the [Issue Tracker](https://github.com/StreisandEffect/streisand/issues).
Core Contributors
----------------
* Jay Carlson (@nopdotcom)
* Nick Clarke (@nickolasclarke)
* Joshua Lund (@jlund)
* Ali Makki (@alimakki)
* Daniel McCarney (@cpu)
* Corban Raun (@CorbanR)
Acknowledgements
----------------
[Jason A. Donenfeld](https://www.zx2c4.com/) deserves a lot of credit for being brave enough to reimagine what a modern VPN should look like and for coming up with something as good as [WireGuard](https://www.wireguard.com/). He has our sincere thanks for all of his patient help and high-quality feedback.
We are grateful to [Trevor Smith](https://github.com/trevorsmith) for his massive contributions. He suggested the Gateway approach, provided tons of invaluable feedback, made *everything* look better, and developed the HTML template that served as the inspiration to take things to the next level before Streisand's public release.
Huge thanks to [Paul Wouters](https://nohats.ca/) of [The Libreswan Project](https://libreswan.org/) for his generous help troubleshooting the L2TP/IPsec setup.
[Starcadian's](https://www.starcadian.com/) 'Sunset Blood' album was played on repeat approximately 300 times during the first few months of work on the project in early 2014.
================================================
FILE: Services.md
================================================
# Services
Services Provided
-----------------
* [OpenSSH](https://www.openssh.com/)
* Windows and Android SSH tunnels are also supported, and a copy of the keypair is exported in the `.ppk` format that PuTTY requires.
* [Tinyproxy](https://tinyproxy.github.io/) can be installed and bound to localhost. It can be accessed over an SSH tunnel by programs that do not natively support SOCKS and that require an HTTP proxy, such as Twitter for Android.
* An unprivileged forwarding user and SSH keypair can be generated for [sshuttle](https://github.com/sshuttle/sshuttle) and SOCKS capabilities.
* [OpenConnect](https://ocserv.gitlab.io/www/index.html) / [Cisco AnyConnect](https://www.cisco.com/c/en/us/products/security/anyconnect-secure-mobility-client/index.html)
* OpenConnect (ocserv) is an extremely high-performance and lightweight VPN server that also features full compatibility with the official Cisco AnyConnect clients.
* The [protocol](https://ocserv.gitlab.io/www/technical.html) is built on top of standards like HTTP, TLS, and DTLS, and it's one of the most popular and widely used VPN technologies among large multi-national corporations.
* This means that in addition to its ease-of-use and speed, OpenConnect is also highly resistant to censorship and is almost never blocked.
* [OpenVPN](https://openvpn.net/index.php/open-source.html)
* When enabled, self-contained "unified" .ovpn profiles are generated for easy client configuration using only a single file.
* Both TCP and UDP connections are supported.
* Client DNS resolution is handled via [Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) to prevent DNS leaks.
* TLS Authentication is enabled which helps protect against active probing attacks. Traffic that does not have the proper HMAC is simply dropped.
* [Shadowsocks](https://shadowsocks.org/en/index.html)
* When enabled, the high-performance [libev variant](https://github.com/shadowsocks/shadowsocks-libev) is installed. This version is capable of handling thousands of simultaneous connections.
* A QR code is generated that can be used to automatically configure the Android and iOS clients by simply taking a picture. You can tag '8.8.8.8' on that concrete wall, or you can glue the Shadowsocks instructions and some QR codes to it instead!
* [AEAD](https://shadowsocks.org/en/spec/AEAD-Ciphers.html) support is enabled using ChaCha20 and Poly1305 for enhanced security and improved GFW evasion.
* The [v2ray-plugin](https://github.com/shadowsocks/v2ray-plugin) plugin is installed to provide robust traffic evasion on hostile networks (especially those implementing quality of service (QOS) throttling).
* [sslh](https://www.rutschle.net/tech/sslh/README.html)
* Sslh is a protocol demultiplexer that allows Nginx, OpenSSH, and OpenVPN to share port 443. This provides an alternative connection option and means that you can still route traffic via OpenSSH and OpenVPN even if you are on a restrictive network that blocks all access to non-HTTP ports.
* [Stunnel](https://www.stunnel.org/index.html)
* When enabled, listens for and wraps OpenVPN connections. This makes them look like standard SSL traffic and allows OpenVPN clients to successfully establish tunnels even in the presence of Deep Packet Inspection.
* Unified profiles for stunnel-wrapped OpenVPN connections are generated alongside the direct connection profiles. Detailed instructions are also generated.
* The stunnel certificate and key are exported in PKCS #12 format so they are compatible with other SSL tunneling applications. Notably, this enables [OpenVPN for Android](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) to tunnel its traffic through [SSLDroid](https://play.google.com/store/apps/details?id=hu.blint.ssldroid). OpenVPN in China on a mobile device? Yes!
* [Tor](https://www.torproject.org/)
* If chosen by the user a [bridge relay](https://www.torproject.org/docs/bridges) is set up with a random nickname.
* [Obfsproxy](https://www.torproject.org/projects/obfsproxy.html.en) is installed and configured with support for the obfs4 pluggable transport.
* A BridgeQR code is generated that can be used to automatically configure [Orbot](https://play.google.com/store/apps/details?id=org.torproject.android) for Android.
* [UFW](https://wiki.ubuntu.com/UncomplicatedFirewall)
* Firewall rules are configured for every service, and any traffic that is sent to an unauthorized port will be blocked.
* [unattended-upgrades](https://help.ubuntu.com/community/AutomaticSecurityUpdates)
* Your Streisand server is configured to automatically install new security updates.
* [WireGuard](https://www.wireguard.com/)
* Users can take advantage of this next-gen, simple, kernel-based or user-space-based, state-of-the-art VPN that also happens to be ridiculously fast and uses modern cryptographic principles that all other highspeed VPN solutions lack. It is noticeably more performant and enery-saving, and is highly advantageous in roaming network-to-network environments, like mobile phones. A connection can be made as simply as scanning a QR code, which makes it perfect for sharing with friends and family members. It currently offers an official client for macOS, iOS, Android, Windows, a variety of Linux distibutions, OpenBSD and FreeBSD.
* [Cloudflared DNS-over-HTTPS](https://developers.cloudflare.com/1.1.1.1/dns-over-https/)
* Even when you are visiting a site using HTTPS, by default your DNS query is sent over an unencrypted connection (between the Streisand server and upstream DNS servers). With Streisand's DNS-over-HTTPS service provided by the cloudflared client enabled, your DNS queries are blocked from view by the cloud provider hosting your Streisand server and everyone in between them and the upstream DNS server. The DNS reply from the upstream server is also protected from both view and tampering on its way back to your Streisand server.
================================================
FILE: Vagrantfile
================================================
# See documentation/testing.md for instructions on using this Vagrantfile
#
Vagrant.require_version ">= 1.9.0"
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.define "streisand-host", primary: true do |streisand|
streisand.vm.hostname = "streisand-host"
streisand.vm.network :private_network, ip: "10.0.0.10"
streisand.vm.provision "ansible" do |ansible|
# NOTE: Uncomment the below line for verbose Ansible output
# ansible.verbose = "v"
ansible.playbook = "playbooks/vagrant.yml"
ansible.host_vars = {
"streisand-host" => {
"streisand_ipv4_address" => "10.0.0.10"
}
}
ansible.raw_arguments = [
"--extra-vars=@global_vars/globals.yml",
"--extra-vars=@global_vars/default-site.yml",
"--extra-vars=@global_vars/integration/test-site.yml"
]
end
end
config.vm.define "streisand-client" do |client|
client.vm.hostname = "streisand-client"
client.vm.network :private_network, ip: "10.0.0.11"
client.vm.provision "ansible" do |ansible|
# NOTE: Uncomment the below line for verbose Ansible output
# ansible.verbose = "v"
ansible.playbook = "playbooks/test-client.yml"
ansible.host_vars = {
"streisand-client" => {
"streisand_ip" => "10.0.0.10",
}
}
end
end
end
================================================
FILE: Vagrantfile.remotetest
================================================
# See documentation/testing.md for instructions on using this Vagrantfile
#
# NOTE: You *MUST* replace the "REMOTE_IP_HERE" value in the `host_vars` section
# with the IP address of the Streisand server you wish to test
#
Vagrant.require_version ">= 1.9.0"
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.define "streisand-client" do |client|
client.vm.hostname = "streisand-client"
client.vm.network :private_network, ip: "10.0.0.11"
client.vm.provision "ansible" do |ansible|
# NOTE: Uncomment the below line for verbose Ansible output
#ansible.verbose = "v"
ansible.playbook = "playbooks/test-client.yml"
ansible.host_vars = {
"streisand-client" => {
"streisand_ip" => "REMOTE_IP_HERE",
}
}
end
end
end
================================================
FILE: ansible.cfg
================================================
[defaults]
inventory = inventories/inventory
nocows = 1
# This is a convenient setting for a brand-new Streisand server that
# you are connecting to for the first time. However, this line should be
# commented out if you are connecting to an existing server where a
# known_hosts entry has already been created. Host key checking happens
# by default in Ansible.
host_key_checking = False
# Workaround for an Ansible issue with temporary paths:
# https://github.com/ansible/ansible/issues/21562
remote_tmp = $HOME/.ansible/tmp
local_tmp = $HOME/.ansible/tmp
# Some providers take a long time to actually begin accepting
# connections even after the OpenSSH daemon has started.
timeout = 100
library=library
[ssh_connection]
# Enables multiplexing (lets ansible reuse opened SSH connections)
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
================================================
FILE: deploy/streisand-existing-cloud-server.sh
================================================
#!/usr/bin/env bash
#
# Provision an existing cloud server.
#
# This requires an expanded extra-vars file specific to the provider type that
# sets all of the values gathered by prompts in the interactive installation.
# See the contents of global_vars/noninteractive for examples that can be copied
# and modified.
#
# Usage:
#
# streisand-existing-cloud-server \
# --ssh-user root \
# --ip-address 10.10.10.10 \
# --site-config path/to/digitalocean-site.yml
#
set -o errexit
set -o nounset
DIR="$( cd "$( dirname "$0" )" && pwd)"
PROJECT_DIR="${DIR}/.."
export DEFAULT_SITE_VARS="${PROJECT_DIR}/global_vars/default-site.yml"
export GLOBAL_VARS="${PROJECT_DIR}/global_vars/globals.yml"
# Include the check_ansible function from ansible_check.sh.
# shellcheck source=util/source_validate_and_deploy.sh
source "${PROJECT_DIR}/util/ansible_check.sh"
check_ansible
# --------------------------------------------------------------------------
# Reading options.
# --------------------------------------------------------------------------
function usage () {
cat < "${INVENTORY}" <
Installation
------------
* Créer une application ( [guide visuel](https://docs.microsoft.com/fr-fr/azure/azure-resource-manager/resource-group-create-service-principal-portal#create-an-active-directory-application) )
Rechercher **Inscriptions d’applications** dans la barre de recherche et sélectionnez le premier résultat.
Sélectionnez **Inscriptions d’applications**.
Remplissez le formulaire:
Name: StreisandAuth
Application type: Web app / API
Sign-on URL: http://StreisandAuth
* Assurez que l'application peut créer des instances Azure ( [guide visuel](https://docs.microsoft.com/fr-fr/azure/azure-resource-manager/resource-group-create-service-principal-portal#assign-application-to-role) )
Rechercher **Abonnements** dans la barre de recherche et sélectionnez le premier résultat.
Choisissez l'abonnement souhaité.
Sélectionnez **Access control (IAM)** à partir du menu nouvellement ouvert.
Ajouter:
Role: Contributor
Select: StreisandAuth
Autorisations
-------------
Emplacement du fichier:
~/.azure/credentials
Format du fichier ( [source](https://docs.ansible.com/ansible/guide_azure.html#storing-in-a-file) ).
[default]
subscription_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
secret=xxxxxxxxxxxxxxxxx
tenant=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Remplacez le motif **xxxxx** par les valeurs obtenues en suivant les étapes ci-dessous.
* Obtenir le **subscription_id**
Rechercher pour **Subscriptions** à partir du menu nouvellement ouvert.
L'ID de l'abonnement sera dans la deuxième colonne du tableau des abonnements.
* Obtenir le **client_id** ( [guide visuel](https://docs.microsoft.com/fr-fr/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-application-id-and-authentication-key) )
Rechercher pour **App registrations** à partir du menu nouvellement ouvert.
Sélectionnez votre application dans la liste: **StreisandAuth**.
Le client_id est le [Guid](https://en.wikipedia.org/wiki/Universally_unique_identifier) sous **Application ID**.
* Obtenir le **secret** ( [guide visuel](https://docs.microsoft.com/fr-fr/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-application-id-and-authentication-key) )
Rechercher pour **App registrations** à partir du menu nouvellement ouvert.
Sélectionnez votre application dans la liste: **StreisandAuth**.
Sélectionnez **Keys** à partir du menu nouvellement ouvert à droite.
Créer une nouvelle clé:
Key description: streisand
Duration: Never expires
La clé secrète sera générée après la sauvegarde.
* Obtenir le **tenant** ( [guide visuel](https://docs.microsoft.com/fr-fr/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-tenant-id) )
Rechercher pour **Azure Active Directory** à partir du menu nouvellement ouvert.
Faites défiler vers le bas et sélectionnez **Properties** à partir du menu nouvellement ouvert à gauche.
Le locataire est le Guid sous **Directory ID**.
Problèmes possibles et dépannage
--------------------------------
* You cannot register an application (Vous ne pouvez pas enregistrer une application)
Rechercher pour **Azure Active Directory** à partir du menu nouvellement ouvert.
Dans le menu gauche résultant, sélectionnez "User settings".
Assurez-vous que **App registrations** sont réglés sur **Yes**.
================================================
FILE: documentation/AZURE.md
================================================
Azure credential and setup
==========================
- - -
[English](AZURE.md), [Français](AZURE-fr.md)
- - -
Setup
-----
* Create an application ( [visual guide](https://docs.microsoft.com/en-in/azure/azure-resource-manager/resource-group-create-service-principal-portal#create-an-active-directory-application) )
Search for **App registrations** in the top search bar and select the first result.
Select **New application registration**.
Fill in the application form:
Name: StreisandAuth
Application type: Web app / API
Sign-on URL: http://StreisandAuth
* Ensure that the application can create Azure instances ( [visual guide](https://docs.microsoft.com/en-in/azure/azure-resource-manager/resource-group-create-service-principal-portal#assign-application-to-role) )
Search for **Subscriptions** in the top search bar and select the first result.
Choose the desired subscription.
Select **Access control (IAM)** from the newly opened menu.
Add:
Role: Contributor
Select: StreisandAuth
Credentials
-----------
File location:
~/.azure/credentials
File format ( [source](https://docs.ansible.com/ansible/guide_azure.html#storing-in-a-file) ).
[default]
subscription_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
secret=xxxxxxxxxxxxxxxxx
tenant=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Replace the **xxxxx** pattern with the values obtained by following the below steps.
* Get the **subscription_id**
Search for **Subscriptions** in the top search bar and select the first result.
The subscription ID will be in the second column of the subscriptions table.
* Get the **client_id** ( [visual guide](https://docs.microsoft.com/en-in/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-application-id-and-authentication-key) )
Search for **App registrations** in the top search bar and select the first result.
Select your application from the list: **StreisandAuth**.
The client_id is the [Guid](https://en.wikipedia.org/wiki/Universally_unique_identifier) under **Application ID**.
* Get the **secret** ( [visual guide](https://docs.microsoft.com/en-in/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-application-id-and-authentication-key) )
Search for **App registrations** in the top search bar and select the first result.
Select your application from the list: **StreisandAuth**.
Select **Certificates & secrets** from the newly opened menu on the left.
Select **New client secret** under **Client secrets**.
Create a new key:
Key description: streisand
Duration: Never expires
The secret key will be generated after saving.
* Get the **tenant** ( [visual guide](https://docs.microsoft.com/en-in/azure/azure-resource-manager/resource-group-create-service-principal-portal#get-tenant-id) )
Search for **Azure Active Directory** in the top search bar and select the first result.
Scroll down and select **Properties** from the newly opened left menu.
The tenant is the Guid under **Directory ID**.
Possible issues and troubleshooting
-----------------------------------
* You cannot register an application
Search for **Azure Active Directory** in the top search bar and select the first result.
In the resulting left menu select "User settings".
Ensure that **App registrations** is set to **Yes**.
================================================
FILE: documentation/SOURCES.md
================================================
# Source of packages installed
## From APT
- Ubuntu standard repositories
- [Streisand Common Packages](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/common/vars/main.yml)
- [`bind`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/dnsmasq/tasks/main.yml)
- [`dnsmasq`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/dnsmasq/tasks/main.yml)
- [Libreswan Compilation Dependencies](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/l2tp-ipsec/vars/main.yml)
- [OpenConnect Dependencies](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/openconnect/vars/main.yml)
- [Shadowsocks Dependencies](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/vars/main.yml)
- [`sslh`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/sslh/tasks/main.yml)
- [`stunnel4`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/stunnel/tasks/main.yml)
- [`tinyproxy`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/tinyproxy/tasks/main.yml)
- [`ufw`](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/ufw/tasks/main.yml)
- from 3rd party repositories:
- [`nginx` (from nginx.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/nginx/tasks/main.yml)
- [`obbfs4proxy` (from deb.torproject.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/tor-bridge/tasks/main.yml)
- [Wireguard Packages (from wireguard PPA)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/wireguard/tasks/install.yml)
- [Acmetool (from PPA)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/lets-encrypt/tasks/install.yml)
## Source
- [Libreswan](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/l2tp-ipsec/vars/main.yml)
- [OpenConnect](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/openconnect/vars/main.yml)
- [OpenVPN (from build.openvpn.net)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/openvpn/vars/mirror.yml)
- [Shadowsocks (from github.com/shadowsocks)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/tasks/main.yml)
- [Shadowsocks Simple-obfs (from github.com/shadowsocks-simpleobfs)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/tasks/simple-obfs.yml)
# Source of all clients mirrored
- Android
- [Shadowsocks (from github.com/shadowsocks)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/vars/mirror.yml)
- Linux
- [Shadowsocks (from github.com/shadowsocks)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/vars/mirror.yml)
- [Tor Browser (from dist.torproject.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/tor-bridge/vars/mirror-common.yml)
- macOS
- [Tunnelblick (from tunnelblick.net)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/openvpn/vars/mirror.yml)
- [Shadowsocks (from github.com/shadowsocks)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/vars/mirror.yml)
- [Tor Browser (from dist.torproject.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/tor-bridge/vars/mirror-common.yml)
- Windows
- [OpenVPN (from build.openvpn.net)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/openvpn/vars/mirror.yml)
- [Shadowsocks (from github.com/shadowsocks)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/shadowsocks/vars/mirror.yml)
- [Shuttle (from github.com/sshuttle)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/streisand-mirror/vars/ssh.yml)
- [Stunnel (from stunnel.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/stunnel/vars/mirror.yml)
- [Putty (from the.earth.li)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/streisand-mirror/vars/ssh.yml)
- [Tor Browser (from dist.torproject.org)](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/tor-bridge/vars/mirror-common.yml)
================================================
FILE: documentation/certificates.md
================================================
Streisand PKI
=============
Streisand includes a role responsible for PKI certificate generation,
separated into three heirarchical tasks:
```
CA/Server
\__ CA Certificate
\__ Server certificate
\__ Client (1..n)
\__ Client PKCS (1..n)
```
CA/Server
---------
Guarded by `generate_ca_server: yes`
Generate a certificate authority, and a server
certificate signed by the newly minted certificate authority.
Client
------
Generate client certificates using the CA from `generate_ca_server: yes`.
These client certificates can be used by VPN clients to authenticate with
VPN services on the server.
Client (PKCS#11 format)
-----------------------
Guarded by `generate_pkcs: yes`
Also convert client certificates into PKCS#12 format.
Infrastructure
--------------
Note: Each VPN service that invokes the certificates role will generate it's own
distinct public key infrastructure.
The overall Streisand PKI infrastructure assumes the following structure:
```
Web Root CA:
\__ gateway HTTPS cert (unless Let's Encrypt; see below)
OpenConnect CA:
\__ OpenConnect server cert
\__ OpenConnect client 1
\__ OpenConnect client ...
\__ OpenConnect client n
OpenVPN CA:
\__ OpenVPN server cert
\__ OpenVPN client 1
\__ OpenVPN client ...
\__ OpenVPN client n
ISRG X1:
\__ Let's Encrypt Authority X3
\__ streisand.example.com HTTPS cert
```
Usage
-----
The `certificates` role can be invoked as follows (using OpenVPN as an example, with variables expanded for brevity):
```
- include_role:
name: certificates
vars:
ca_path: "/etc/openvpn"
tls_ca: "/etc/openvpn/ca"
tls_client_path: "/etc/openvpn"
generate_ca_server: yes
generate_client: yes
tls_request_subject: "/C=US/ST=California/L=Beverly Hills/O=ACME CORPORATION/OU=Anvil Department"
tls_server_common_name_file: "/etc/openvpn/openvpn-common-name.txt"
tls_sans: # sets the Subject Alternative Name(s) attribute(s)
- "1.2.3.4"
- "5.6.7.8"
```
Note the following flags:
- `generate_ca_server: yes`
- `generate_client: yes`
- `generate_pkcs: yes`
These must be made explicit, as the default value is `no`; certificates should not be generated unless
they have to be.
The certificates role makes certain assumptions with regards to default values,
all of which can be inspected [here](https://github.com/StreisandEffect/streisand/blob/master/playbooks/roles/certificates/defaults/main.yml).
================================================
FILE: documentation/localization_howto.md
================================================
Localizing Streisand in your language
=====================================
One of the most unique aspects of the Streisand project are the
detailed and customized instructions that it generates for each
of the VPN services it provides. The instructions are hosted
on a password protected website allowing them to be easily shared
among fellow users. This can help in removing ambiguity in how
certain services need to be set up and can be easily updated as
Streisand evolves.
Scope
-----
The best place to focus localization efforts is on user facing
content, as opposed to developer content.
For example, documentation that can help a user navigate the particularities of certain
cloud providers (account setup, permissions, etc...) are good candidates for localization.
On the other hand, translation of developer oriented texts, such as Ansible
task names isn't needed at this time.
Language codes
--------------
For simplicity, it is preferable to use 2 character language codes (fr -> French, ar -> Arabic),
as defined by [ISO 631-1](https://en.wikipedia.org/wiki/ISO_639). For certain locales such as
Chinese vs Simplified Chinese, 3 character codes are also acceptable.
Filename conventions
--------------------
In order to differentiate a localized file, append the lowercase language code after the
filename with a 'dash' symbol (e.x. README-fr.md for a README localized in French).
Point of reference
------------------
When translating, English should be considered the point of reference to translate *from*.
READMEs and Documentation
-------------------------
The interaction with Streisand for an end user would be first visiting the project README,
where all the necessary steps one would need to set up their computing environment are
detailed, as well as a listing of all the VPN services provided by Streisand.
Unlike Streisand's instructions markdown template files, READMEs and documentation are
orthogonal to Streisand being able to successfully build. As a consequences, it is possible
to have READMEs and documentation in more languages than Streisand builds documentation with.
Defining locales
----------------
In order to define a locale for Streisand, a new entry defining your language must be
added to the `streisand_languages` dict object in the `playbooks/roles/common/vars/main.yml` file,
where the 2 letter code is considered the key, and a list of key-value pairs with additional data
as its value.
For example:
```
streisand_languages:
en:
file_suffix: ""
language_name: "English"
tor_locale: "en-US"
fr:
file_suffix: "-fr" # appends to the end of a file name
language_name: "Français" # name of the language in the language itself
tor_locale: "fr" # edge case for Tor
```
Localizing gateway instructions
-------------------------------
The following roles contain user instructions that will require translation:
- `playbooks/roles/openconnect/templates`
1. `instructions.md.j2`
1. `mirror.md.j2`
- `playbooks/roles/openvpn/templates`
1. `instructions.md.j2`
1. `stunnel-insructions.md.j2`
1. `mirror.md.j2`
- `playbooks/roles/shadowsocks/templates`
1. `instructions.md.j2`
1. `mirror.md.j2`
- `playbooks/roles/ssh-forward/templates`
1. `instructions.md.j2`
1. `mirror.md.j2`
- `playbooks/roles/streisand-gateway/templates`
1. `index.md.j2`
1. `instructions.md.j2`
1. `firewall.md.j2`
- `playbooks/roles/streisand-mirror/templates`
1. `mirror-index.md.j2`
- `playbooks/roles/stunnel/templates`
1. `mirror.md.j2`
- `playbooks/roles/tor/templates`
1. `instructions.md.j2`
1. `mirror.md.j2`
- `playbooks/roles/wireguard/templates`
1. `instructions.md.j2`
Language selection in generated pages
-------------------------------------
By default, Streisand's common header file contains language selection links
(generated using the `streisand_languages` dict). For most pages the header with
language selection links will be included automatically. Certain edge cases
do exist where a jinja2 code block is explicitly needed with the generated html filename.
These edge case files maybe all reside with the `streisand-gateway` role:
- `firewall.md.j2`
- `index.md.j2`
- `instructions.md.j2`
```
- - -
{% for key, value in streisand_languages.items() %}
[{{ value.language_name }}]({{ streisand_server_name }}-*generated-html-file-name*{{ value.file_suffix }}.html)
{% endfor %}
- - -
```
The HTML filename can be recovered by looking at the relevant Ansible task that generates the
template.
End user considerations
-----------------------
While we aim to have as-close-to-the-original-source translations, linguistic differences in
expressions should be taken into consideration when it makes sense.
A non-technical example would be a the following
expression in English: "the straw that broke the camel's back".
A literal translation into French
would give: "la paille qui a cassé le dos du chameau", however contextually
a similar expression exists in French: "C'est la goutte d'eau qui fait déborder le vase"
(it's the drop of water that made the vase overflow). Different translations,
same meaning. In this case, the latter would be the 'ideal' translation, as it makes more sense
to a native speaker of that language.
Another aspect to consider is what language an end-user's device is set to.
It is best to have a device nearby set in the same language, where you can see exactly what is
displayed in particular menus and use those same exactly what is displayed.
It's worth noting that not all software available in app stores or otherwise are localized
in your language of choice, and many are English only. In this case, it would be sufficient to use
the same English texts, and should you choose, adjacent to it between parenthesis a translation of
the aforementioned text.
In the case where you aren't in possession of a particular device, a best-effort
approach is also acceptable.
================================================
FILE: documentation/modular_roles.md
================================================
Modular Roles
===============
Streisand includes many services in an out-of-box install. This helps make
censorship resistance as easy as possible. In a hostile network environment the
protocols/services that are blocked can vary & change overnight. With many
choices available for connecting through a Streisand instance to clear Internet
there is likely always a choice that will work!
For use cases less focused on censorship resistance this "kitchen sink of
services" approach has two large downsides: many moving parts & a very large
externally facing attack surface.
The solution: Allowing users to selectively disable Streisand services they
don't require, creating custom profiles that suits their needs.
The challenge: Streisand was initially designed as a monolithic deploy. That is,
the Ansible roles responsible for each service inter-depend on one another. To
enable picking and choosing Streisand services while minimizing spaghetti
complexity it's necessary to eliminate cross-role dependencies.
This document aims to be a roadmap for converting roles to be stand-alone and
suitable for the goal of modularizing included services. As a concrete example
this document will discuss the Shadowsocks role, the first role that has been
converted to this style.
Rough Plan
----------
**Note**: _This is all subject to change as discussion/experience unfolds!_
1. One role at a time, convert it to be stand alone (e.g. create its own
firewall rules, do its own client mirroring, etc).
2. Add an enable flag variable for the role, default to on (e.g. Streisand by
default remains ship-it-all-by-default).
3. Once all roles are converted, add infrastructure for selecting roles (helper
script modifications).
4. Discuss which roles should be enabled by default to perhaps pare down the
base install.
5. Update this documentation.
Implementation
--------------
Each service has an enable bool variable defined in `playbooks/group_vars/all` to
control whether the service is going to be included or not. E.g.
`streisand_shadowsocks_enabled: yes` would include Shadowsocks when provisioning
a server.
Every Streisand service has to handle the following responsibilities:
* Installing & setting up server software/configurations.
* Updating firewall rules/access controls.
* Generating client connection instructions & config files.
* Mirroring client software.
For the purpose of connection instructions & client software each service has
two directories it must create & populate:
* One in `/var/www/streisand/` for connection instructions.
* One in `var/www/streisand/mirror/` for client mirroring.
Both directories should contain an `index.html` for the available Streisand
languages.
Since responsibilities between services are similar, the self-contained roles
should have roughly the same structure (minimized for brevity):
```
service/
├── meta
│ └── main.yml
├── tasks
│ ├── main.yml
│ ├── docs.yml
│ ├── firewall.yml
│ └── mirror.yml
└── vars
├── main.yml
└── mirror.yml
```
* `meta/main.yml` is used for declaring dependencies (e.g. on `ufw` for
firewall rules). Nothing special there!
* `tasks/main.yml` handles the base responsibilities of installing
software/configs etc. and includes the subtask files: `docs.yml`,
`firewall.yml` and `mirror.yml`.
* `tasks/docs.yml` handles generating connection instructions for the service
under its documentation root.
* `tasks/firewall.yml` handles adding `ufw`/`iptables` rules as required by the
service.
* `tasks/mirror.yml` handles downloading client software to the service's mirror
root and generating any required client install documentation.
* `vars/main.yml` are the variables required for the service's configuration/etc.
* `vars/mirror.yml` are mirror-specific variables (client software versions,
download URLs, expected hashes/signatures, etc)
For Shadowsocks, initially the `ufw` role was responsible for adding a firewall
rule for the `shadowsocks-libev` port. This created a cross-role dependency
where if the `shadowsocks` role was disabled the `ufw` role would open a port
unnecessarily, or reference a variable that didn't exist.
To remove this cross-dependency the `shadowsocks` role was updated to declare
a meta dependency on the generic firewall role (to ensure the package is
installed and ready) in `meta/main.yml`. Then a `tasks/firewall.yml` subtask
file was added that uses `ufw` to add the required rules.
Similarly, the initial `streisand-mirror` role downloaded all of the
Shadowsocks clients for the mirror using a distinct tasks `.yml` with its own
variables `.yml`. This made it fairly easy to move the mirror subtasks from
`streisand-mirror/tasks/shadowsocks.yml` to
`shadowsocks/tasks/mirror.yml` and `streisand-mirror/vars/shadowsocks.yml` to
`shadowsocks/vars/mirror.yml`. Now the `shadowsocks` role can be responsible for
preparing its own client mirror.
Gateway & Mirror Indices
------------------------------
While the Gateway & Mirror documentation can be largely agnostic of which
services are included in a given build by outsourcing the management of
subfolders of `/var/www/streisand` and `/var/www/streisand/mirror` eventually
a consistent set of docs to navigate must be created based on the included
services. This is done by conditionally adding links to the connection
instruction & mirror indices of each subservice using the enable bool variables
in the docs and mirror index files. This is the one place where the "if
spaghetti" is required in order to stitch things together.
As a concrete example, consider the `shadowsocks` role. Previously the
`streisand-gateway` and `streisand-mirror` roles were responsible for all
aspects of the Shadowsocks documentation & mirroring.
Now, the `shadowsocks` role creates a `/var/www/streisand/shadowsocks/`
directory and generates an `index.html` in there with connection instructions.
Similarly, the client software is mirrored to
`/var/www/streisand/mirror/shadowsocks/` and an `index.html` is generated in
there to list the available clients & their installation instructions.
The `playbooks/roles/streisand-gateway/templates/index.md.j2` index template can
conditionally generate a link to the installation instructions:
```
{% if streisand_shadowsocks_enabled %}
* [Shadowsocks](/shadowsocks/)
{% endif %}
```
Similarly, the index can conditionally generate a link to the service client mirror:
```
{% if streisand_shadowsocks_enabled %}
* [Shadowsocks](/mirror/shadowsocks/)
{% endif %}
```
The same approach is taken in the mirror index template:
`playbooks/roles/streisand-mirror/templates/mirror-index.md.j2`.
Common Daemon Config
------------------------
Some Streisand services have to modify base daemon configurations in order to
provide services like DNS/DHCP to interfaces they create. Where possible we
should strive to avoid having centralized "monolith" configurations and instead
use the "config.d/" approach to allow modular configuration of these shared
daemons. The [original usecase](https://lists.debian.org/debian-devel/2010/04/msg00352.html)
for these directories closely matches the situation Streisand is in:
Once upon a time, most UNIX software was controlled by a single
configuration file per software package, and all the configuration details
for that package went into that file. This worked reasonably well when
that file was hand-crafted by the system administrator for local needs.
When distribution packaging became more and more common, it became clear
that we needed better ways of forming such configuration files out of
multiple fragments, often provided by multiple independent packages. Each
package that needs to configure some shared service should be able to
manage only its configuration without having to edit a shared
configuration file used by other packages.
The most common convention adopted was to permit including a directory
full of configuration files, where anything dropped into that directory
would become active and part of that configuration.
A concrete example of this common daemon problem is the `dnsmasq` service/role
and its interactions with the `wireguard` and `openvpn` roles. Prior to
modularization the `dnsmasq` role made sure the daemon listened on all required
intefaces by having one `/etc/dnsmasq.conf` config file generated by the
`dnsmasq` role's `dnsmasq.conf.j2` template. The template had one
`listen-address` configuration parameter that listed all of the interface
addresses in a comma-separated form:
```
listen-address=127.0.0.1,{{ dnsmasq_openvpn_tcp_ip }},{{ dnsmasq_openvpn_udp_ip }},{{ dnsmasq_wireguard_ip }}
```
This meant that if the `openvpn` or `wireguard` roles were disabled/removed the
template for the `dnsmasq` config would fail due to the missing variables.
The approach used to fix this was to have the base `/etc/dnsmasq.conf` file
specify only `listen-address=127.0.0.1` and update the `openvpn` and `wireguard`
roles to write their own `listen-address` fragments from a template to their own
config files in `/etc/dnsmasq.d/`. Now the `dnsmasq` role is decoupled from the
`openvpn` and `wireguard` roles that can be added/removed at will.
================================================
FILE: documentation/testing.md
================================================
CI Testing
==========================
Streisand has a `.travis.yml` file that powers [continuous integration
tests](https://travis-ci.org/jlund/streisand). It works by installing required
test tools (e.g. shellcheck) and an Ansible environment on a Ubuntu Trusty
(14.04) machine.
The `test.sh` wrapper script
--------------------------------
The `test/test.sh` wrapper script is invoked to perform tests and supports
an argument for specifying what actions should be taken. The following are
supported arguments:
* **"setup"** prepares the local environment for running a Streisand
[LXC](https://linuxcontainers.org/lxc/introduction/) instance. The instance
is managed via [LXD](https://linuxcontainers.org/lxd/).
* **"syntax"** checks the Streisand playbooks for Ansible syntax errors.
* **"run"** runs the CI tests. It assumes the local environment is already
prepared from a previous "setup" run.
* **"ci"** combines "setup" and "run".
* **"full"** performs the same as "ci" but additionally adds verbose output to
the Ansible run. This is very verbose but can be useful for diagnosing
tricky broken builds.
* By **default** the wrapper will run "syntax".
Working around things that won't work in Travis
-----------------------------------------------
Some playbooks/tasks can't be run in CI because of limitations imposed by the
containerization or Travis. One example of this is installing a Tor relay. To
work around this playbooks/tasks that break in CI can be gated on the
`streisand_ci` variable, which is `true` only for CI runs. Where possible it's
best to minimize the use of this variable for conditional execution because we
want as much code to be tested as possible!
Kernel Modules
---------------------
By design LXC containers share the Linux kernel they use with the host machine.
This means playbooks/services that require a kernel module (e.g. Libreswan) must
build the kernel module on the host machine.
Local Testing
==========================
For local testing Streisand includes a `Vagrantfile` that creates two virtual
machines: `streisand-host` and `streisand-client`.
The `streisand-host` machine is provisioned with the standard Streisand
playbooks and replicates a Streisand server created with a cloud provider, but
running on your local computer.
Note that a throwaway SSH key pair is created in the `streisand-host` virtual
machine in the location specified in the Anisible variable
`streisand_ssh_private_key`. This is not needed to SSH into the virtual machine
using `vagrant ssh streisand-host` and is only used by the provisioning process.
The `streisand-client` machine is provisioned specifically to act as a client of
the `streisand-host`. It connects to the `streiand-host`'s HTTPS gateway to
download client configuration files that are used by test scripts to ensure that
services work "end-to-end".
Using Vagrant for Local Testing
-------------------------------
1. [Install Vagrant](https://www.vagrantup.com/docs/installation/)
2. Clone the Streisand repository and enter the directory.
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
3. If this is your first time following these steps, create & start the
`streisand-host` and `streisand-client` virtual machines with:
`vagrant up`
4. To re-run the Streisand playbooks, the virtual machines can be re-provisioned
with:
`vagrant up --provision`
Remote Testing
==========================
For testing an existing Streisand server there is a `Vagrantfile.remotetest`
Vagrantifle. As compared to the stock `Vagrantfile` for local testing the
`Vagrantfile.remotetest` Vagrantfile does not include a `streisand-host`
machine. This remotetest variant is useful to "smoke test" an existing
Streisand server, or to provide end-to-end testing of a cloud provisioner.
Using Vagrant for Remote Testing (Easy Way)
--------------------------------------------
1. [Install Vagrant](https://www.vagrantup.com/docs/installation/)
2. Clone the Streisand repository and enter the directory.
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
3. Run the `remote_test.sh` helper script and give it the remote server IP
& gateway password when prompted:
./tests/remote_test.sh
Using Vagrant for Remote Testing (Hard Way)
--------------------------------------------
1. [Install Vagrant](https://www.vagrantup.com/docs/installation/)
2. Clone the Streisand repository and enter the directory.
git clone https://github.com/StreisandEffect/streisand.git && cd streisand
3. Edit `Vagrantfile.remotetest` and replace the `streisand_ip` host variable
with the IP of the remote server.
4. Create the `generated-docs/gateway-password.txt` file with the gateway
password of the Streisand server
5. If this is your first time following these steps, create & start the
`streisand-client` virtual machine with:
VAGRANT_VAGRANTFILE=Vagrantfile.remotetest vagrant up
4. To re-run the Streisand playbooks, the virtual machines can be re-provisioned
with:
VAGRANT_VAGRANTFILE=Vagrantfile.remotetest vagrant up --provision
Misc Tricks
==========================
* Uncomment the lines setting the `ansible.verbose` value in the Vagrantfiles to
increase the verbosity of the Ansible playbook runs.
* Skip the `./tests/remote_test.sh` prompts using `printf`:
STREISAND_SERVER_IP=XX.XX.XX.XX; STREISAND_PASSWORD='gateway-password-goes-here'; printf "$STREISAND_SERVER_IP\n$STREISAND_PASSWORD\n" | ./tests/remote_test.sh
================================================
FILE: global_vars/default-site.yml
================================================
---
# Site specific Streisand configuration.
#
# This file is mutated by the playbooks/customize.yml tasks when a user chooses
# to customize which Streisand services are installed.
# The SSH private key that Ansible will use to connect to the Streisand node.
# The associated public key will be used if required when provisioning cloud
# nodes for the authorized_keys file.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_shadowsocks_v2ray_enabled: no
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
streisand_cloudflared_enabled: no
================================================
FILE: global_vars/globals.yml
================================================
---
# If using regular cleartext DNS then dnsmasq will set these upstream DNS servers
upstream_dns_servers:
- 1.1.1.1
- 1.0.0.1
# If using DNS-over-HTTPS with cloudflared then the upstream servers and queries can be set in:
# playbooks/roles/cloudflared/defaults/main.yml
streisand_client_test: no
streisand_site_vars: "{{ lookup('env','HOME') }}/.streisand/site.yml"
================================================
FILE: global_vars/integration/test-site.yml
================================================
---
# Test site configuration for the end-to-end integration tests.
# Don't ask questions
streisand_noninteractive: true
confirmation: true
streisand_domain_var: ""
streisand_admin_email_var: ""
# Take a few extra steps during server provisioning to make the client tests work
streisand_client_test: true
# Only services with corresponding tests are enabled.
streisand_ad_blocking_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
streisand_openvpn_enabled: yes
streisand_wireguard_enabled: yes
streisand_openconnect_enabled: yes
streisand_tor_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
# TODO(@cpu): The services below need some manner of integration test written
streisand_sshuttle_enabled: no
================================================
FILE: global_vars/noninteractive/amazon-site.yml
================================================
---
# Example site specific configuration for a noninteractive AWS deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
#
# This will be added to the AWS console and given the name streisand-ssh.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# The AWS region number.
#
# See ./playbooks/amazon.yml for numbering.
#
# Note: aws_region_var must be a number in quotes, e.g. "3" not 3.
aws_region_var: "16"
# The VPC and subnet IDs to use. They can be empty strings to indicate that a
# VPC will not be used.
aws_vpc_id_var: ""
aws_vpc_subnet_id_var: ""
aws_instance_name: streisand
# The AWS credentials to use.
aws_access_key: ""
aws_secret_key: ""
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/azure-site.yml
================================================
---
# Example site specific configuration for a noninteractive Azure deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
# Ensure that you have the azure credentials file set up at ~/.azure/credentials
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# The region to deploy into.
#
# North America:
# 1: East US (Virginia)
# 2: East US 2 (Virginia)
# 3: Central US (Iowa)
# 4: North Central US (Illinois)
# 5: South Central US (Texas)
# 6: West Central US (West Central US)
# 7: West US (California)
# 8: West US 2 (West US 2)
# 9: US Gov Virginia (Virginia)
# 10: US Gov Iowa (Iowa)
# 11: US DoD East (US DoD East)
# 12: US DoD Central (US DoD Central)
# 13: Canada East (Quebec City)
# 14: Canada Central (Toronto)
#
# South America:
# 15: Brazil South (Sao Paulo State)
#
# Asia:
# 16: Southeast Asia (Singapore)
# 17: East Asia (Hong Kong)
# 18: China East (Shanghai)
# 19: China North (Beijing)
# 20: Japan East (Tokyo, Saitama)
# 21: Japan West (Osaka)
# 22: Korea Central (Seoul)
# 23: Korea South (Busan)
# 24: Central India (Pune)
# 25: West India (Mumbai)
# 26: South India (Chennai)
#
# Australia:
# 27: Australia East (New South Wales)
# 28: Australia Southeast (Victoria)
#
# Europe:
# 29: North Europe (Ireland)
# 30: West Europe (Netherlands)
# 31: Germany Central (Frankfurt)
# 32: Germany Northeast (Magdeburg)
# 33: UK West (Cardiff)
# 34: UK South (London)
#
# Note: azure_region_var must be a number in quotes, e.g. "1" not 1.
azure_region_var: "1"
azure_instance_name_var: streisand
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/digitalocean-site.yml
================================================
---
# Example site specific configuration for a noninteractive Digital Ocean
# deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
#
# The corresponding public key must be added to the Digital Ocean control panel
# and the name given to it referenced below in the do_ssh_name variable.
# The corresponding public key must be uploaded to Digital Ocean and the name
# given to it referenced below in the do_ssh_name variable.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# The Digital Ocean region number.
#
# 1. Amsterdam (Datacenter 2)
# 2. Amsterdam (Datacenter 3)
# 3. Bangalore
# 4. Frankfurt
# 5. London
# 6. New York (Datacenter 1)
# 7. New York (Datacenter 2)
# 8. New York (Datacenter 3)
# 9. San Francisco (Datacenter 1)
# 10. San Francisco (Datacenter 2)
# 11. Singapore
# 12. Toronto
#
# Note: do_region must be a number in quotes, e.g. "2" not 2.
do_region: "2"
do_server_name: streisand
# Add the Digital Ocean access token here.
do_access_token_entry: ""
# The name given to the key in the DigitalOcean control panel.
do_ssh_name: streisand
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/google-site.yml
================================================
---
# Example site specific configuration for a noninteractive Google Compute Engine
# deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# Server location:
#
# 1. Central US "us-central1-a"
# 2. Central US "us-central1-b"
# 3. Central US "us-central1-c"
# 4. Central US "us-central1-f"
# 5. Eastern US "us-east4-a"
# 6. Eastern US "us-east4-b"
# 7. Eastern US "us-east4-c"
# 8. Eastern US "us-east1-b"
# 9. Eastern US "us-east1-c"
# 10. Eastern US "us-east1-d"
# 11. Western US "us-west1-a"
# 12. Western US "us-west1-b"
# 13. Western US "us-west1-c"
# 14. Western Europe "europe-west1-b"
# 15. Western Europe "europe-west1-c"
# 16. Western Europe "europe-west1-d"
# 17. Western Europe "europe-west2-a"
# 18. Western Europe "europe-west2-b"
# 19. Western Europe "europe-west2-c"
# 20. Western Europe "europe-west3-a"
# 21. Western Europe "europe-west3-b"
# 22. Western Europe "europe-west3-c"
# 23. Western Europe "europe-west4-a"
# 24. Western Europe "europe-west4-b"
# 25. Western Europe "europe-west4-c"
# 26. East Asia "asia-east1-a"
# 27. East Asia "asia-east1-b"
# 28. East Asia "asia-east1-c"
# 29. Northeast Asia "asia-northeast1-a"
# 30. Northeast Asia "asia-northeast1-b"
# 31. Northeast Asia "asia-northeast1-c"
# 32. South Asia "asia-south1-a"
# 33. South Asia "asia-south1-b"
# 34. South Asia "asia-south1-c"
# 35. Southeast Asia "asia-southeast1-a"
# 36. Southeast Asia "asia-southeast1-b"
# 37. Southeast Australia "australia-southeast1-a"
# 38. Southeast Australia "australia-southeast1-b"
# 39. Southeast Australia "australia-southeast1-c"
#
# Named zones are more robust if you use non-interactive deployments. You can still use
# the numbered index, however the number can change, whereas the name will stay the same.
# Keep the idx variable non-empty if you use named zones.
gce_zone_idx: "do not remove this var if you have defined gce_zone"
gce_zone: us-central1-c
gce_server_name: streisand
# The full path of your unique service account credentials file. See:
# https://docs.ansible.com/ansible/guide_gce.html#credentials
# https://support.google.com/cloud/answer/6158849?hl=en&ref_topic=6262490#serviceaccounts
gce_json_file_location: ""
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/linode-site.yml
================================================
---
# Example site specific configuration for a noninteractive Linode deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# Choose the server location.
# 1. Atlanta
# 2. Dallas
# 3. Frankfurt
# 4. Fremont
# 5. London
# 6. Newark
# 7. Singapore
# 8. Tokyo
# 9. Tokyo 2
#
# Note: linode_datacenter must be a number in quotes, e.g. "7" not 7.
linode_datacenter: "7"
linode_server_name: streisand
# Obtain the API key from the Linode Manager console.
linode_api_key: ""
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/local-site.yml
================================================
---
# Example site specific configuration for a noninteractive local machine
# deployment.
#
# Copy this and edit it as needed before running streisand-local.
#
streisand_noninteractive: true
confirmation: true
# Change this to the location of a key on the local system.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: global_vars/noninteractive/rackspace-site.yml
================================================
---
# Example site specific configuration for a noninteractive Rackspace deployment.
#
# Copy this and edit it as needed before running streisand-new-cloud-server.
#
streisand_noninteractive: true
confirmation: true
# The SSH private key that Ansible will use to connect to the Streisand node.
streisand_ssh_private_key: "~/.ssh/id_rsa"
vpn_clients: 10
streisand_ad_blocking_enabled: no
streisand_openconnect_enabled: yes
streisand_openvpn_enabled: yes
streisand_shadowsocks_enabled: yes
streisand_ssh_forward_enabled: yes
# By default sshuttle is disabled because it creates a `sshuttle` user that has
# full shell privileges on the Streisand host
streisand_sshuttle_enabled: no
streisand_stunnel_enabled: yes
streisand_tinyproxy_enabled: yes
streisand_tor_enabled: no
streisand_wireguard_enabled: yes
# Choose the region to deploy into.
#
# 1. Chicago
# 2. Dallas
# 3. Hong Kong
# 4. Northern Virginia
# 5. Sydney
#
# Note: rackspace_region must be a number in quotes, e.g. "1" not 1.
rackspace_region: "1"
rackspace_server_name: streisand
# Obtain these credentials from the Rackspace Cloud Control Panel.
rackspace_username: ""
rackspace_api_key: ""
# Definitions needed for Let's Encrypt HTTPS (or TLS) certificate setup.
#
# If these are both left as empty strings, Let's Encrypt will not be set up and
# a self-signed certificate will be used instead.
#
# The domain to use for Let's Encrypt certificate.
streisand_domain_var: ""
# The admin email address for Let's Encrypt certificate registration.
streisand_admin_email_var: ""
================================================
FILE: inventories/inventory
================================================
[localhost]
localhost ansible_connection=local ansible_python_interpreter=python3
# Uncomment the following lines and update the IP address if you would
# like to use Streisand to configure a server that is already running
# (e.g. a server at a provider not natively supported by Streisand).
#
# Multiple servers can be configured simultaneously if multiple IP
# addresses are defined.
#
# If you already have SSH fingerprints for the hosts you are configuring
# (e.g. using `ssh-keyscan`) then you should also comment out the
# 'host_key_checking = False' line in the ansible.cfg file. That setting
# is only sensible and convenient when connecting to a brand-new host.
#
# [streisand-host]
# 255.255.255.255
#
# If the SSH user to be used to login is not "root", specify it here with
# the ansible_user directive. Streisand will sudo automatically. If sudo
# requires a password, use the --ask-become-pass command line option.
#
# [streisand-host]
# 255.255.255.255 ansible_user=ubuntu
================================================
FILE: inventories/inventory-local-provision
================================================
# inventory-local-provision is a pre-built inventory file useful for doing an
# advanced local install of Streisand where the server running Ansible is the
# server that will be configured.
# Settings for the provisioning process
[localhost]
# This must specify the Python interpreter when provisioning, because
# "python" may be in, for example, a virtualenv without python-apt.
localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python
# Settings for the Streisand host that will be provisioned
[streisand-host]
# If you need to override the name of the server (e.g. because the system
# hostname is not the desired server name for documentation/etc) then add a host
# var named "streisand_server_name" with the desired value.
localhost ansible_connection=local streisand_noninteractive=true
================================================
FILE: library/digital_ocean_droplet.py
================================================
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Origin: @jackivanov's PR#61643 for ansible:
# https://github.com/ansible/ansible/blob/b8b416d30282d6aef4b3ffb7fcb01a0dd2da9f59/lib/ansible/modules/cloud/digital_ocean/digital_ocean_droplet.py
# This will be removed on fix to upstream
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: digital_ocean_droplet
short_description: Create and delete a DigitalOcean droplet
description:
- Create and delete a droplet in DigitalOcean and optionally wait for it to be active.
version_added: "2.8"
author: "Gurchet Rai (@gurch101)"
options:
state:
description:
- Indicate desired state of the target.
default: present
choices: ['present', 'absent']
id:
description:
- Numeric, the droplet id you want to operate on.
aliases: ['droplet_id']
name:
description:
- String, this is the name of the droplet - must be formatted by hostname rules.
unique_name:
description:
- require unique hostnames. By default, DigitalOcean allows multiple hosts with the same name. Setting this to "yes" allows only one host
per name. Useful for idempotence.
default: False
type: bool
size:
description:
- This is the slug of the size you would like the droplet created with.
aliases: ['size_id']
image:
description:
- This is the slug of the image you would like the droplet created with.
aliases: ['image_id']
region:
description:
- This is the slug of the region you would like your server to be created in.
aliases: ['region_id']
ssh_keys:
description:
- array of SSH key (numeric) ID that you would like to be added to the server.
required: False
private_networking:
description:
- add an additional, private network interface to droplet for inter-droplet communication.
default: False
type: bool
user_data:
description:
- opaque blob of data which is made available to the droplet
required: False
ipv6:
description:
- enable IPv6 for your droplet.
required: False
default: False
type: bool
wait:
description:
- Wait for the droplet to be active before returning. If wait is "no" an ip_address may not be returned.
required: False
default: True
type: bool
wait_timeout:
description:
- How long before wait gives up, in seconds, when creating a droplet.
default: 120
backups:
description:
- indicates whether automated backups should be enabled.
required: False
default: False
type: bool
monitoring:
description:
- indicates whether to install the DigitalOcean agent for monitoring.
required: False
default: False
type: bool
tags:
description:
- List, A list of tag names as strings to apply to the Droplet after it is created. Tag names can either be existing or new tags.
required: False
volumes:
description:
- List, A list including the unique string identifier for each Block Storage volume to be attached to the Droplet.
required: False
oauth_token:
description:
- DigitalOcean OAuth token. Can be specified in C(DO_API_KEY), C(DO_API_TOKEN), or C(DO_OAUTH_TOKEN) environment variables
aliases: ['API_TOKEN']
required: True
requirements:
- "python >= 2.6"
'''
EXAMPLES = '''
- name: create a new droplet
digital_ocean_droplet:
state: present
name: mydroplet
oauth_token: XXX
size: 2gb
region: sfo1
image: ubuntu-16-04-x64
wait_timeout: 500
register: my_droplet
- debug:
msg: "ID is {{ my_droplet.data.droplet.id }}, IP is {{ my_droplet.data.ip_address }}"
- name: ensure a droplet is present
digital_ocean_droplet:
state: present
id: 123
name: mydroplet
oauth_token: XXX
size: 2gb
region: sfo1
image: ubuntu-16-04-x64
wait_timeout: 500
'''
RETURN = '''
# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#droplets
data:
description: a DigitalOcean Droplet
returned: changed
type: dict
sample: {
"ip_address": "104.248.118.172",
"ipv6_address": "2604:a880:400:d1::90a:6001",
"private_ipv4_address": "10.136.122.141",
"droplet": {
"id": 3164494,
"name": "example.com",
"memory": 512,
"vcpus": 1,
"disk": 20,
"locked": true,
"status": "new",
"kernel": {
"id": 2233,
"name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic",
"version": "3.13.0-37-generic"
},
"created_at": "2014-11-14T16:36:31Z",
"features": ["virtio"],
"backup_ids": [],
"snapshot_ids": [],
"image": {},
"volume_ids": [],
"size": {},
"size_slug": "512mb",
"networks": {},
"region": {},
"tags": ["web"]
}
}
'''
import time
import json
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.digital_ocean import DigitalOceanHelper
class DODroplet(object):
def __init__(self, module):
self.rest = DigitalOceanHelper(module)
self.module = module
self.wait = self.module.params.pop('wait', True)
self.wait_timeout = self.module.params.pop('wait_timeout', 120)
self.unique_name = self.module.params.pop('unique_name', False)
# pop the oauth token so we don't include it in the POST data
self.module.params.pop('oauth_token')
def get_by_id(self, droplet_id):
if not droplet_id:
return None
response = self.rest.get('droplets/{0}'.format(droplet_id))
json_data = response.json
if response.status_code == 200:
return json_data
return None
def get_by_name(self, droplet_name):
if not droplet_name:
return None
page = 1
while page is not None:
response = self.rest.get('droplets?page={0}'.format(page))
json_data = response.json
if response.status_code == 200:
for droplet in json_data['droplets']:
if droplet['name'] == droplet_name:
return {'droplet': droplet}
if 'links' in json_data and 'pages' in json_data['links'] and 'next' in json_data['links']['pages']:
page += 1
else:
page = None
return None
def get_addresses(self, data):
"""
Expose IP addresses as their own property allowing users extend to additional tasks
"""
_data = data
for k, v in data.items():
setattr(self, k, v)
networks = _data['droplet']['networks']
for network in networks.get('v4', []):
if network['type'] == 'public':
_data['ip_address'] = network['ip_address']
else:
_data['private_ipv4_address'] = network['ip_address']
for network in networks.get('v6', []):
if network['type'] == 'public':
_data['ipv6_address'] = network['ip_address']
else:
_data['private_ipv6_address'] = network['ip_address']
return _data
def get_droplet(self):
json_data = self.get_by_id(self.module.params['id'])
if not json_data and self.unique_name:
json_data = self.get_by_name(self.module.params['name'])
return json_data
def create(self):
json_data = self.get_droplet()
droplet_data = None
if json_data:
droplet_data = self.get_addresses(json_data)
self.module.exit_json(changed=False, data=droplet_data)
if self.module.check_mode:
self.module.exit_json(changed=True)
data = self.module.params
try:
del data['id']
except KeyError:
pass
response = self.rest.post('droplets', data=data)
json_data = response.json
if response.status_code >= 400:
self.module.fail_json(changed=False, msg=json_data['message'])
if self.wait:
json_data = self.ensure_power_on(json_data['droplet']['id'])
droplet_data = self.get_addresses(json_data)
self.module.exit_json(changed=True, data=droplet_data)
def delete(self):
json_data = self.get_droplet()
if json_data:
if self.module.check_mode:
self.module.exit_json(changed=True)
response = self.rest.delete('droplets/{0}'.format(json_data['droplet']['id']))
json_data = response.json
if response.status_code == 204:
self.module.exit_json(changed=True, msg='Droplet deleted')
self.module.fail_json(changed=False, msg='Failed to delete droplet')
else:
self.module.exit_json(changed=False, msg='Droplet not found')
def ensure_power_on(self, droplet_id):
end_time = time.time() + self.wait_timeout
while time.time() < end_time:
response = self.rest.get('droplets/{0}'.format(droplet_id))
json_data = response.json
if json_data['droplet']['status'] == 'active':
return json_data
time.sleep(min(2, end_time - time.time()))
self.module.fail_json(msg='Wait for droplet powering on timeout')
def core(module):
state = module.params.pop('state')
droplet = DODroplet(module)
if state == 'present':
droplet.create()
elif state == 'absent':
droplet.delete()
def main():
module = AnsibleModule(
argument_spec=dict(
state=dict(choices=['present', 'absent'], default='present'),
oauth_token=dict(
aliases=['API_TOKEN'],
no_log=True,
fallback=(env_fallback, ['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN'])
),
name=dict(type='str'),
size=dict(aliases=['size_id']),
image=dict(aliases=['image_id']),
region=dict(aliases=['region_id']),
ssh_keys=dict(type='list'),
private_networking=dict(type='bool', default=False),
backups=dict(type='bool', default=False),
monitoring=dict(type='bool', default=False),
id=dict(aliases=['droplet_id'], type='int'),
user_data=dict(default=None),
ipv6=dict(type='bool', default=False),
volumes=dict(type='list'),
tags=dict(type='list'),
wait=dict(type='bool', default=True),
wait_timeout=dict(default=120, type='int'),
unique_name=dict(type='bool', default=False),
),
required_one_of=(
['id', 'name'],
),
required_if=([
('state', 'present', ['name', 'size', 'image', 'region']),
]),
supports_check_mode=True,
)
core(module)
if __name__ == '__main__':
main()
================================================
FILE: playbooks/amazon.yml
================================================
---
- name: Provision the EC2 Server
# ==============================
hosts: localhost
connection: local
gather_facts: yes
vars:
# The region dict is generated from ./util/print-aws-regions.py
regions:
"1": "ap-east-1"
"2": "ap-northeast-1"
"3": "ap-northeast-2"
"4": "ap-northeast-3"
"5": "ap-south-1"
"6": "ap-southeast-1"
"7": "ap-southeast-2"
"8": "ca-central-1"
"9": "eu-central-1"
"10": "eu-north-1"
"11": "eu-west-1"
"12": "eu-west-2"
"13": "eu-west-3"
"14": "sa-east-1"
"15": "us-east-1"
"16": "us-east-2"
"17": "us-west-1"
"18": "us-west-2"
# These variable files are included so the ec2-security-group role
# knows which ports to open
vars_files:
- roles/openconnect/defaults/main.yml
- roles/openvpn/defaults/main.yml
- roles/shadowsocks/defaults/main.yml
- roles/ssh/defaults/main.yml
- roles/lets-encrypt/vars/main.yml
- roles/streisand-gateway/defaults/main.yml
- roles/stunnel/defaults/main.yml
- roles/tor-bridge/defaults/main.yml
- roles/wireguard/defaults/main.yml
vars_prompt:
# The region prompt is generated from ./util/print-aws-regions.py
# Don't forget to update the default if it changes.
- name: "aws_region_var"
prompt: |
In what region should the server be located?
1. ap-east-1 Asia Pacific (Hong Kong)
2. ap-northeast-1 Asia Pacific (Tokyo)
3. ap-northeast-2 Asia Pacific (Seoul)
4. ap-northeast-3 Asia Pacific (Osaka-Local)
5. ap-south-1 Asia Pacific (Mumbai)
6. ap-southeast-1 Asia Pacific (Singapore)
7. ap-southeast-2 Asia Pacific (Sydney)
8. ca-central-1 Canada (Central)
9. eu-central-1 EU (Frankfurt)
10. eu-north-1 EU (Stockholm)
11. eu-west-1 EU (Ireland)
12. eu-west-2 EU (London)
13. eu-west-3 EU (Paris)
14. sa-east-1 South America (São Paulo)
15. us-east-1 US East (N. Virginia)
16. us-east-2 US East (Ohio)
17. us-west-1 US West (N. California)
18. us-west-2 US West (Oregon)
Please choose the number of your region. Press enter for default (#16) region.
default: "16"
private: no
- name: "aws_vpc_id_var"
prompt: |
In which VPC would you like to create the server and security group
(e.g. vpc-89d740ee)?
Press enter to use the default VPC.
private: no
- name: "aws_vpc_subnet_id_var"
prompt: |
From which subnet should the server receive an address (e.g. subnet-78d9a232)?
Press enter to use the default subnet.
private: no
- name: "aws_instance_name"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
default: "streisand"
private: no
- name: "aws_access_key"
prompt: "\n\nThe following information can be found in the IAM Management Console.\nhttps://console.aws.amazon.com/iam/home?#security_credential\n\nWhat is your AWS Access Key ID?\n"
private: no
- name: "aws_secret_key"
prompt: "\nWhat is your AWS Secret Access Key?\n"
private: no
- name: "confirmation"
prompt: "\nStreisand will now set up your server. This process usually takes around ten minutes. Press Enter to begin setup...\n"
pre_tasks:
- name: Set the AWS Region fact
set_fact:
aws_region: "{{ regions[aws_region_var] }}"
- name: Set the AWS VPC ID fact
set_fact:
aws_vpc_id: "{{ aws_vpc_id_var }}"
when: aws_vpc_id_var != ""
- name: Set the AWS VPC Subnet ID fact
set_fact:
aws_vpc_subnet_id: "{{ aws_vpc_subnet_id_var }}"
when: aws_vpc_subnet_id_var != ""
roles:
- genesis-amazon
- import_playbook: ssh-setup.yml
- import_playbook: cloud-status.yml
- import_playbook: python.yml
- import_playbook: ec2-metadata-instance.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/azure.yml
================================================
---
- name: Provision the Azure Server (Resource Manager mode)
# ========================================================
hosts: localhost
connection: local
gather_facts: yes
vars:
regions:
"1": "eastus"
"2": "eastus2"
"3": "centralus"
"4": "northcentralus"
"5": "southcentralus"
"6": "westcentralus"
"7": "westus"
"8": "westus2"
"9": "usgovvirginia"
"10": "usgoviowa"
"11": "usdodeast"
"12": "usdodcentral"
"13": "canadaeast"
"14": "canadacentral"
"15": "brazilsouth"
"16": "southeastasia"
"17": "eastasia"
"18": "chinaeast"
"19": "chinanorth"
"20": "japaneast"
"21": "japanwest"
"22": "koreacentral"
"23": "koreasouth"
"24": "centralindia"
"25": "westindia"
"26": "southindia"
"27": "australiaeast"
"28": "australiasoutheast"
"29": "australiacentral"
"30": "australiacentral2"
"31": "northeurope"
"32": "westeurope"
"33": "germanycentral"
"34": "germanynortheast"
"35": "ukwest"
"36": "uksouth"
"37": "francecentral"
"38": "francesouth"
# These variable files are included so the azure-security-group role
# knows which ports to open
vars_files:
- roles/openconnect/defaults/main.yml
- roles/openvpn/defaults/main.yml
- roles/shadowsocks/defaults/main.yml
- roles/ssh/defaults/main.yml
- roles/lets-encrypt/vars/main.yml
- roles/streisand-gateway/defaults/main.yml
- roles/stunnel/defaults/main.yml
- roles/tor-bridge/defaults/main.yml
- roles/wireguard/defaults/main.yml
vars_prompt:
- name: "azure_region_var"
prompt: >
What region should the server be located in?
North America:
1: East US (Virginia)
2: East US 2 (Virginia)
3: Central US (Iowa)
4: North Central US (Illinois)
5: South Central US (Texas)
6: West Central US (West Central US)
7: West US (California)
8: West US 2 (West US 2)
9: US Gov Virginia (Virginia)
10: US Gov Iowa (Iowa)
11: US DoD East (US DoD East)
12: US DoD Central (US DoD Central)
13: Canada East (Quebec City)
14: Canada Central (Toronto)
South America:
15: Brazil South (Sao Paulo State)
Asia:
16: Southeast Asia (Singapore)
17: East Asia (Hong Kong)
18: China East (Shanghai)
19: China North (Beijing)
20: Japan East (Tokyo, Saitama)
21: Japan West (Osaka)
22: Korea Central (Seoul)
23: Korea South (Busan)
24: Central India (Pune)
25: West India (Mumbai)
26: South India (Chennai)
Australia:
27: Australia East (New South Wales)
28: Australia Southeast (Victoria)
29: Austrailia Central (Canberra)
30: Austrailia Central 2 (Canberra)
Europe:
31: North Europe (Ireland)
32: West Europe (Netherlands)
33: Germany Central (Frankfurt)
34: Germany Northeast (Magdeburg)
35: UK West (Cardiff)
36: UK South (London)
37: France Central (Paris)
38: France South (Marseille)
Please choose the number of your region: Press enter for default (#1) region.
default: "1"
private: no
- name: "azure_instance_name_var"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
default: "streisand"
private: no
- name: "confirmation_credentials"
prompt: "\nEnsure that you have the azure credentials file: ~/.azure/credentials \nDetails on generating this can be found at https://github.com/StreisandEffect/streisand/blob/master/documentation/AZURE.md"
- name: "confirmation"
prompt: "\nStreisand will now set up your server: This process usually takes around ten minutes: Press Enter to begin setup...\n"
pre_tasks:
- name: Set the Azure Region fact
set_fact:
azure_region: "{{ regions[azure_region_var] }}"
- name: Set the Azure Instance Name fact
set_fact:
azure_instance_name: "{{ azure_instance_name_var | regex_replace('\\s', '_') }}"
roles:
- genesis-azure
- import_playbook: ssh-setup.yml
- import_playbook: cloud-status.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/cloud-status.yml
================================================
---
- name: Checking instance status
# =========================================
hosts: streisand-host
gather_facts: no
remote_user: "root"
become: true
tasks:
- name: Wait for cloud-init to complete
raw: bash -c "for i in {1..30}; do if [ -f /var/lib/cloud/instance/boot-finished ]; then exit 0; fi; sleep 1; done; exit 1;"
register: result
changed_when: False
failed_when: result.rc != 0
...
================================================
FILE: playbooks/customize.yml
================================================
---
- name: Customize enabled Streisand services
hosts: localhost
gather_facts: no
vars_prompt:
- name: streisand_ssh_private_key
prompt: "Enter the path to your SSH private key, or press enter for default "
default: "~/.ssh/id_rsa"
private: no
- name: vpn_clients
prompt: "How many VPN client profiles should be generated per-service (min: 1 max: 20)? Press enter for default "
default: 10
private: no
- name: streisand_ad_blocking_enabled
prompt: "Enable DNS-based ad-blocking? Press enter for default "
default: "no"
private: no
- name: streisand_openconnect_enabled
prompt: "Enable OpenConnect? Press enter for default "
default: "yes"
private: no
- name: streisand_openvpn_enabled
prompt: "Enable OpenVPN? Press enter for default "
default: "yes"
private: no
- name: streisand_stunnel_enabled
prompt: "Enable stunnel service (only allowed for OpenVPN)? Press enter for default "
default: "yes"
private: no
- name: streisand_shadowsocks_enabled
prompt: "Enable Shadowsocks? Press enter for default "
default: "yes"
private: no
- name: streisand_shadowsocks_v2ray_enabled
prompt: "Enable v2ray-plugin for Shadowsocks? Press enter for default "
default: "no"
private: no
- name: streisand_ssh_forward_enabled
prompt: "Enable SSH Forward User? (Note: A SOCKS proxy only user will be added, no shell). Press enter for default "
default: "yes"
private: no
- name: streisand_sshuttle_enabled
prompt: "Enable sshuttle? (Note: A full shell access user will be added) Press enter for default "
default: "no"
private: no
- name: streisand_tinyproxy_enabled
prompt: "Enable tinyproxy? Press enter for default "
default: "yes"
private: no
- name: streisand_tor_enabled
prompt: "Enable Tor? Press enter for default "
default: "no"
private: no
- name: streisand_wireguard_enabled
prompt: "Enable WireGuard? Press enter for default "
default: "yes"
private: no
- name: streisand_cloudflared_enabled
prompt: "[BROKEN ON SOME PROVIDERS, including AWS] Enable DNS-over-HTTPS (cloudflared)? Press enter for default "
default: "no"
private: no
tasks:
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_ssh_private_key: .*$"
line: "streisand_ssh_private_key: {{ streisand_ssh_private_key }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^vpn_clients: [\\d]+$"
line: "vpn_clients: {{ vpn_clients }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_ad_blocking_enabled: (?:yes|no|True|False)$"
line: "streisand_ad_blocking_enabled: {{ streisand_ad_blocking_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_openconnect_enabled: (?:yes|no|True|False)$"
line: "streisand_openconnect_enabled: {{ streisand_openconnect_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_openvpn_enabled: (?:yes|no|True|False)$"
line: "streisand_openvpn_enabled: {{ streisand_openvpn_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_shadowsocks_enabled: (?:yes|no|True|False)$"
line: "streisand_shadowsocks_enabled: {{ streisand_shadowsocks_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_shadowsocks_v2ray_enabled: (?:yes|no|True|False)$"
line: "streisand_shadowsocks_v2ray_enabled: {{ streisand_shadowsocks_v2ray_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_ssh_forward_enabled: (?:yes|no|True|False)$"
line: "streisand_ssh_forward_enabled: {{ streisand_ssh_forward_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_sshuttle_enabled: (?:yes|no|True|False)$"
line: "streisand_sshuttle_enabled: {{ streisand_sshuttle_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_stunnel_enabled: (?:yes|no|True|False)$"
line: "streisand_stunnel_enabled: {{ streisand_stunnel_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_tinyproxy_enabled: (?:yes|no|True|False)$"
line: "streisand_tinyproxy_enabled: {{ streisand_tinyproxy_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_tor_enabled: (?:yes|no|True|False)$"
line: "streisand_tor_enabled: {{ streisand_tor_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_wireguard_enabled: (?:yes|no|True|False)$"
line: "streisand_wireguard_enabled: {{ streisand_wireguard_enabled|bool }}"
- lineinfile:
path: "{{ streisand_site_vars }}"
regexp: "^streisand_cloudflared_enabled: (?:yes|no|True|False)$"
line: "streisand_cloudflared_enabled: {{ streisand_cloudflared_enabled|bool }}"
================================================
FILE: playbooks/digitalocean.yml
================================================
---
- name: Provision the DigitalOcean Server
# =======================================
hosts: localhost
connection: local
gather_facts: yes
vars:
regions:
"1": "ams2"
"2": "ams3"
"3": "blr1"
"4": "fra1"
"5": "lon1"
"6": "nyc1"
"7": "nyc2"
"8": "nyc3"
"9": "sfo1"
"10": "sfo2"
"11": "sgp1"
"12": "tor1"
vars_prompt:
- name: "do_region"
prompt: >
What region should the server be located in?
1. Amsterdam (Datacenter 2)
2. Amsterdam (Datacenter 3)
3. Bangalore
4. Frankfurt
5. London
6. New York (Datacenter 1)
7. New York (Datacenter 2)
8. New York (Datacenter 3)
9. San Francisco (Datacenter 1)
10. San Francisco (Datacenter 2)
11. Singapore
12. Toronto
Please choose the number of your region. Press enter for default (#2) region.
default: "2"
private: no
- name: "do_server_name"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
default: "streisand"
private: no
- name: "do_access_token_entry"
prompt: |
Personal Access Tokens allow Streisand to create a droplet for you.
New Personal Access Tokens can be generated in the DigitalOcean control panel.
To generate a new token please do the following:
* Go to https://cloud.digitalocean.com/settings/applications
* Click 'Generate New Token'
* Give the token a name (it is arbitrary)
* Be sure to select the 'Write' scope as well (this is not optional)
* Click 'Generate Token'
* Copy the long string that is generated and paste it below.
If this field is left blank, the environment variable DO_API_KEY will be used.
What is your DigitalOcean Personal Access Token?
private: no
- name: "do_ssh_name"
prompt: "\n\nThe following information can be found on your DigitalOcean control panel.\nhttps://cloud.digitalocean.com/settings/security\n\nWhat is the name of the DigitalOcean SSH key that you would like to use?\n * If you have never uploaded an SSH key to DigitalOcean then the default\n value will work!\n * This key should match your Streisand SSH key file (default: ~/.ssh/id_rsa.pub).\n\ * DigitalOcean requires SSH keys to be unique. You cannot upload multiple\n keys that have the same value under different names.\n\n If you see an error that says 'SSH Key failed to be created' once the setup\n process starts, then this is the problem. You can retry the setup process\n using the name of the existing SSH key from the DigitalOcean control panel\n that matches the contents of your RSA public key.\n"
default: "streisand"
private: no
- name: "confirmation"
prompt: "\nStreisand will now set up your server. This process usually takes around ten minutes. Press Enter to begin setup...\n"
roles:
- genesis-digitalocean
- import_playbook: ssh-setup.yml
- import_playbook: cloud-status.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/ec2-metadata-instance.yml
================================================
---
- name: Drop packets to the Amazon EC2 metadata instance
hosts: streisand-host
gather_facts: no
remote_user: "root"
become: true
tasks:
- name: Copy the EC2 metadata instance oneshot unit file
copy:
src: "./roles/genesis-amazon/files/aws-metadata-instance.service"
dest: "/etc/systemd/system/aws-metadata-instance.service"
owner: root
group: root
mode: 0644
- name: Enable and reload the EC2 metadata instance
systemd:
name: aws-metadata-instance.service
daemon_reload: yes
enabled: yes
state: restarted
================================================
FILE: playbooks/existing-server.yml
================================================
---
# existing-server.yml is an advanced provisioning option that doesn't use a genesis
# role to create a new server and instead applies Streisand to an existing
# remote server.
- name: Register the genesis role in use
hosts: localhost
gather_facts: yes
tasks:
- set_fact:
streisand_genesis_role: "existing-server"
- include: ssh-setup.yml
- name: Check SSH access to existing server
hosts: streisand-host
gather_facts: no
remote_user: "{{ lookup('env', 'SSH_USER') }}"
become: true
tasks:
- block:
- raw: whoami
args:
executable: /bin/bash
changed_when: False
rescue:
- fail:
msg: "Unable to SSH to existing streisand-host.\nEnsure private key corresponding to \"{{ streisand_ssh_private_key }}\" is loaded in your SSH key agent.\nTry using `ssh-keygen -i {{ streisand_ssh_private_key }} to generate your key if it does not exist\n"
# Ensure Python is installed on the system
- import_playbook: python.yml
# Try and detect the remote server's provider & apply required workarounds
- import_playbook: provider-detect.yml
- name: Prepare the remote server for Streisand
# =========================================
hosts: streisand-host
remote_user: "{{ lookup('env', 'SSH_USER') }}"
become: true
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/google.yml
================================================
---
- name: Provision the GCE Server
# =======================================
hosts: localhost
connection: local
gather_facts: yes
vars:
zones:
"1": "us-central1-a"
"2": "us-central1-b"
"3": "us-central1-c"
"4": "us-central1-f"
"5": "us-east4-a"
"6": "us-east4-b"
"7": "us-east4-c"
"8": "us-east1-b"
"9": "us-east1-c"
"10": "us-east1-d"
"11": "us-west1-a"
"12": "us-west1-b"
"13": "us-west1-c"
"14": "europe-west1-b"
"15": "europe-west1-c"
"16": "europe-west1-d"
"17": "europe-west2-a"
"18": "europe-west2-b"
"19": "europe-west2-c"
"20": "europe-west3-a"
"21": "europe-west3-b"
"22": "europe-west3-c"
"23": "europe-west4-a"
"24": "europe-west4-b"
"25": "europe-west4-c"
"26": "asia-east1-a"
"27": "asia-east1-b"
"28": "asia-east1-c"
"29": "asia-east2-a"
"30": "asia-east2-b"
"31": "asia-east2-c"
"32": "asia-northeast1-a"
"33": "asia-northeast1-b"
"34": "asia-northeast1-c"
"35": "asia-south1-a"
"36": "asia-south1-b"
"37": "asia-south1-c"
"38": "asia-southeast1-a"
"39": "asia-southeast1-b"
"40": "australia-southeast1-a"
"41": "australia-southeast1-b"
"42": "australia-southeast1-c"
"43": "southamerica-east1-a"
"44": "southamerica-east1-b"
"45": "southamerica-east1-c"
# These variable files are included so the gce-network role
# knows which ports to open
vars_files:
- roles/openconnect/defaults/main.yml
- roles/openvpn/defaults/main.yml
- roles/shadowsocks/defaults/main.yml
- roles/ssh/defaults/main.yml
- roles/lets-encrypt/vars/main.yml
- roles/streisand-gateway/defaults/main.yml
- roles/stunnel/defaults/main.yml
- roles/tor-bridge/defaults/main.yml
- roles/wireguard/defaults/main.yml
vars_prompt:
- name: "gce_zone_idx"
prompt: >
What zone should the server be located in?
1. Central US (Iowa A)
2. Central US (Iowa B)
3. Central US (Iowa C)
4. Central US (Iowa F)
5. Eastern US (Northern Virginia A)
6. Eastern US (Northern Virginia B)
7. Eastern US (Northern Virginia C)
8. Eastern US (South Carolina B)
9. Eastern US (South Carolina C)
10. Eastern US (South Carolina D)
11. Western US (Oregon A)
12. Western US (Oregon B)
13. Western US (Oregon C)
14. Western Europe (Belgium B)
15. Western Europe (Belgium C)
16. Western Europe (Belgium D)
17. Western Europe (London A)
18. Western Europe (London B)
19. Western Europe (London C)
20. Western Europe (Frankfurt A)
21. Western Europe (Frankfurt B)
22. Western Europe (Frankfurt C)
23. Western Europe (Netherlands A)
24. Western Europe (Netherlands B)
25. Western Europe (Netherlands C)
26. East Asia (Taiwan A)
27. East Asia (Taiwan B)
28. East Asia (Taiwan C)
29. East Asia (Hong Kong A)
30. East Asia (Hong Kong B)
31. East Asia (Hong Kong C)
32. Northeast Asia (Tokyo A)
33. Northeast Asia (Tokyo B)
34. Northeast Asia (Tokyo C)
35. South Asia (Mumbai A)
36. South Asia (Mumbai B)
37. South Asia (Mumbai C)
38. Southeast Asia (Singapore A)
39. Southeast Asia (Singapore B)
40. Southeast Australia (Sydney A)
41. Southeast Australia (Sydney B)
42. Southeast Australia (Sydney C)
43. South America (São Paulo A)
44. South America (São Paulo B)
45. South America (São Paulo C)
Please choose the number of your zone. Press enter for default (#3) zone.
default: "3"
when: gce_zone is not defined
private: no
- name: "gce_server_name"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
default: "streisand"
private: no
- name: "gce_json_file_location"
prompt: "\n\nThe full path of your unique service account credentials file. Details on generating this can be found at \nhttps://docs.ansible.com/ansible/guide_gce.html#credentials\n and \nhttps://support.google.com/cloud/answer/6158849?hl=en&ref_topic=6262490#serviceaccounts\n"
default: "{{ lookup('env','HOME') }}/streisand.json"
private: no
- name: "confirmation"
prompt: "\nStreisand will now set up your server. This process usually takes around ten minutes. Press Enter to begin setup...\n"
pre_tasks:
- name: Set the Google Compute Engine Zone interactive
set_fact:
gce_zone: "{{ zones[gce_zone_idx] }}"
when: gce_zone is not defined
- name: Register JSON file contents
command: cat {{ gce_json_file_location }}
register: gce_json_file_contents
changed_when: False
- name: Set JSON file contents fact
set_fact:
gce_json_contents_fact: "{{ gce_json_file_contents.stdout | from_json }}"
- name: Set the Google Compute Engine Service Account Email
set_fact:
gce_service_account_email: "{{ gce_json_contents_fact.client_email }}"
- name: Set the Google Compute Engine Project ID
set_fact:
gce_project_id: "{{ gce_json_contents_fact.project_id }}"
roles:
- genesis-google
- import_playbook: ssh-setup.yml
- import_playbook: cloud-status.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/group_vars/all
================================================
---
streisand_ci: no
streisand_noninteractive: no
================================================
FILE: playbooks/lets-encrypt.yml
================================================
---
# lets-encrypt.yml asks questions about Streisand instance domain name, which
# is used to request TLS certificates from Let's Encrypt. If user fails to
# answer these questions, lets-encrypt role would not be run, and self-signed
# certificates are generated and used instead.
- name: Collect information about the Streisand domain
# =========================================
hosts: streisand-host
gather_facts: no
vars_files:
- roles/lets-encrypt/vars/main.yml
vars_prompt:
- name: "streisand_domain_var"
prompt: |
Do you have a fully qualified domain pointed at your Streisand server?
This is an optional question. If you have a domain that points to your
Streisand server, the installation scripts can request a Let's Encrypt
HTTPS certificate for you automatically. If you do not provide one or
the request fails, a self-signed certificate will be used instead.
If you have just created a new cloud server in previous steps now is a
good time to point your fully qualified domain to your server's public
address. Make sure the fully qualified domain resolves to the correct IP
address before proceeding.
Please type your fully qualified domain below. Press enter to skip.
private: no
- name: "streisand_admin_email_var"
prompt: |
Which email address do you want to use as a contact for the Streisand
server's Let's Encrypt certificate?
This is an optional question. If you supply an email address Let's
Encrypt will send you important (but infrequent) notifications about
your certificate. These messages include any upcoming certificate
expirations, and important changes to the Let's Encrypt service.
The email provided will not be used for anything else or shared with the
Streisand developers.
Please type your contact email below. Press enter to skip.
private: no
pre_tasks:
- name: Set Streisand domain
set_fact:
streisand_domain: "{{ streisand_domain_var }}"
when: streisand_domain_var != ""
- name: Set Streisand admin email
set_fact:
streisand_admin_email: "{{ streisand_admin_email_var }}"
- name: Enable Let's Encrypt role
set_fact:
streisand_le_enabled: yes
when: streisand_domain_var != ""
- name: Disable Let's Encrypt role
set_fact:
streisand_le_enabled: no
streisand_domain: ""
streisand_admin_email: ""
le_ok: False
when: streisand_domain_var == ""
...
================================================
FILE: playbooks/linode.yml
================================================
---
- name: Provision the Linode Server
# =================================
hosts: localhost
connection: local
gather_facts: yes
vars:
regions:
"1": "ca-central"
"2": "us-central"
"3": "us-west"
"4": "us-southeast"
"5": "us-east"
"6": "eu-west"
"7": "ap-south"
"8": "eu-central"
"9": "ap-northeast"
"10": "ap-west"
"11": "ap-southeast"
vars_prompt:
- name: "linode_datacenter"
prompt: >
What region should the server be located in?
1. Toronto
2. Dallas
3. Fremont
4. Atlanta
5. Newark
6. London
7. Singapore
8. Frankfurt
9. Tokyo
10. Mumbai
11. Sydney
Please choose the number of your region. Press enter for default (#7) region.
default: "7"
private: no
- name: "linode_server_name"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
default: "streisand"
private: no
- name: "linode_api_token"
prompt: "\n\nThe following information can be found in the Linode Manager:\nhttps://cloud.linode.com/profile/tokens\n\nWhat is your Linode API Token?\n"
private: no
- name: "confirmation"
prompt: "\nStreisand will now set up your server. This process usually takes around ten minutes. Press Enter to begin setup...\n"
roles:
- genesis-linode
- import_playbook: ssh-setup.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/localhost.yml
================================================
---
# localhost.yml is an advanced provisioning option that doesn't use a genesis
# role to create a new server and instead applies Streisand to the localhost.
# Ensure Python is installed on the system
- import_playbook: python.yml
# Try and detect localhost's provider & apply required workarounds
- import_playbook: provider-detect.yml
- name: Prepare the localhost for Streisand
# =========================================
hosts: streisand-host
remote_user: "root"
become: true
tasks:
- set_fact:
streisand_genesis_role: "localhost"
# If there's no streisand_ipv4_address set then we try our best using
# the interface Ansible thinks is the default.
- name: "Set the Streisand IPv4 address to the Ansible default: interface: {{ ansible_default_ipv4.alias }} address: {{ ansible_default_ipv4.address }}"
set_fact:
# The ansible_default_ipv4 address is calculated based on the default
# ipv4 route to 8.8.8.8 for the system, and for local provisioning on
# _most_ providers, seems to work well for finding the external facing IP.
# See `provider-detect.yml` for cases where this approach doesn't work
# (e.g. GCE) and workarounds.
streisand_ipv4_address: "{{ ansible_default_ipv4.address }}"
when: streisand_ipv4_address is not defined
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/provider-detect.yml
================================================
---
# provider-detect.yml is used for the advanced existing/localhost provisioning
# to try and determine if a given host is from a specific cloud provider. If
# the cloud provider is detected, some facts/workarounds may be set to aid in
# provisioning in place of one of the geneiss roles.
- name: Try to detect Cloud providers for specific overrides
# =========================================
hosts: streisand-host
remote_user: "root"
become: true
tasks:
- name: "Install dmidecode to use for BIOS version detection"
apt:
package: dmidecode
- name: "Try to determine localhost Cloud provider name from BIOS version"
# Looking into ways to detect EC2/GCE instances without relying on
# connections to metadata IPs this solution[0] seemed the most
# straightforward & reliable.
# https://serverfault.com/a/775063
command: dmidecode -s bios-version
register: streisand_localhost_bios_name
changed_when: False
ignore_errors: True
- name: "Set BIOS name fact from dmidecode if possible"
set_fact:
streisand_bios_name: "{{ streisand_localhost_bios_name.stdout }}"
when: streisand_localhost_bios_name.rc == 0
- name: "...Otherwise set unknown BIOS fact"
set_fact:
streisand_bios_name: "Unknown"
when: streisand_bios_name is undefined
# GCE specific work-arounds:
# * None of the interfaces have the external IP bound, so this must be set
# from the Google Platform medatadata service.
- block:
- name: Warn about manual provisioning of GCE instances
pause:
prompt: "You are running Streisand in an advanced mode against an existing GCE instance. Unlike the standard GCE provisioning mode this means Streisand *CAN NOT* open ports on your behalf. You will need to manually create the correct VPC Network and firewall rules. See 'generated-docs/' for the firewall-information.html file at the end of installation for a list of ports to open. The Streisand maintainers are not able to support this configuration. Press [enter] to continue"
when: not streisand_noninteractive
- name: "Find the external GCE IP from Google Metadata"
# NOTE: We use the command module and `curl` here because (AFAICT)
# there isn't a way to `register` a `get_url` call and it seems
# hackier overall to add an intermediate step using a file on disk
#
# Metadata URL & the required "Metadata-Flavor" are explained in the
# Google Cloud Platform documentation[0].
# [0]: https://cloud.google.com/compute/docs/storing-retrieving-metadata#querying
command: curl -H Metadata-Flavor:Google http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip
register: streisand_gce_external_ip
changed_when: False
- name: "Set the Streiand IPv4 address to the GCE external IP: {{ streisand_gce_external_ip.stdout }}"
set_fact:
streisand_ipv4_address: "{{ streisand_gce_external_ip.stdout }}"
when: "streisand_bios_name == 'Google'"
# Amazon EC2 specific work-arounds:
# * None of the interfaces have the external IP bound, so this must be set
# from the EC2 medatadata service.
- block:
- name: Warn about manual provisioning of EC2 instances
pause:
prompt: "You are running Streisand in an advanced mode against an existing Amazon EC2 instance. Unlike the standard EC2 provisioning mode this means Streisand *CAN NOT* open ports on your behalf. You will need to manually assinging this machine to a security group with the correct firewall rules. See 'generated-docs/' for the firewall-information.html file at the end of installation for a list of ports to open. The Streisand maintainers are not able to support this configuration. Press [enter] to continue"
when: not streisand_noninteractive
# EC2 Instance Metadata API is explained in the EC2 docs[0].
# [0]: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
- name: "Find the external EC2 IP from Metadata"
command: curl http://169.254.169.254/latest/meta-data/public-ipv4
register: streisand_ec2_external_ip
changed_when: False
- name: "Set the Streiand IPv4 address to the EC2 external IP: {{ streisand_ec2_external_ip.stdout }}"
set_fact:
streisand_ipv4_address: "{{ streisand_ec2_external_ip.stdout }}"
when: "'amazon' in streisand_bios_name"
...
================================================
FILE: playbooks/python.yml
================================================
---
- name: Prepare the new server for Ansible
# =========================================
hosts: streisand-host
gather_facts: no
remote_user: "root"
become: true
tasks:
- name: Install Python using a raw SSH command to enable the execution of Ansible modules
raw: apt update && apt install python -y
args:
executable: /bin/bash
...
================================================
FILE: playbooks/rackspace.yml
================================================
---
- name: Provision the Rackspace Server
# ====================================
hosts: localhost
connection: local
gather_facts: yes
vars:
regions:
"1": "ORD"
"2": "DFW"
"3": "HKG"
"4": "IAD"
"5": "SYD"
vars_prompt:
- name: "rackspace_region"
prompt: >
What region should the server be located in?
1. Chicago
2. Dallas
3. Hong Kong
4. Northern Virginia
5. Sydney
Please choose the number of your region. Press enter for default (#1) region.
default: "1"
private: no
- name: "rackspace_server_name"
prompt: "\nWhat should the server be named? Press enter for default (streisand).\n"
private: no
default: "streisand"
- name: "rackspace_username"
prompt: "\nWhat is your Rackspace username?\n"
private: no
- name: "rackspace_api_key"
prompt: "\n\nThe following information can be found in the Rackspace Cloud Control Panel.\nhttps://mycloud.rackspace.com/\n\nWhat is your Rackspace API key?\n"
private: no
- name: "confirmation"
prompt: "\nStreisand will now set up your server. This process usually takes around ten minutes. Press Enter to begin setup...\n"
roles:
- genesis-rackspace
- import_playbook: ssh-setup.yml
- import_playbook: cloud-status.yml
- import_playbook: streisand.yml
...
================================================
FILE: playbooks/roles/ad-blocking/files/download-blocklists
================================================
#!/bin/bash
set -e
# Now, if there were only some convenient way of storing etags from
# those fetches.
download_if_newer () {
filename="$1"
url="$2"
if [ -e "$filename" ]; then
curl --time-cond "$filename" -o "$filename" "$url"
else
curl -o "$filename" "$url"
fi
}
mkdir -p /var/lib/blocklists
download_if_newer /var/lib/blocklists/block-hostnames.txt 'https://raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt'
download_if_newer /var/lib/blocklists/block-domains.txt 'https://raw.githubusercontent.com/notracking/hosts-blocklists/master/domains.txt'
transform-domain-list /etc/dnsmasq.d/block-domains.conf
transform-host-list /etc/dnsmasq-block-hosts
echo "addn-hosts=/etc/dnsmasq-block-hosts" >/etc/dnsmasq.d/block-hosts.conf
# Sadly, "reload" doesn't work"
systemctl restart dnsmasq.service
================================================
FILE: playbooks/roles/ad-blocking/files/download-blocklists.service
================================================
[Unit]
Description=Download blocklists
[Service]
Type=oneshot
ExecStart=/usr/local/bin/download-blocklists
================================================
FILE: playbooks/roles/ad-blocking/files/download-blocklists.timer
================================================
[Timer]
OnActiveSec=0
OnBootSec=60
OnUnitActiveSec=1d
RandomizedDelaySec=1h
[Install]
WantedBy=network.target
================================================
FILE: playbooks/roles/ad-blocking/files/transform-domain-list
================================================
#!/bin/bash
awk '
BEGIN { FS="/"; print "# post-processed by transform-domain-list" }
/^#/ { print $0; next; }
/^address=\/.*\/0\.0\.0\.0$/ { next; }
/^address=\/.*\/::$/ {
if ($2 !~ /\./) {
print "### no dot found in domain, skipping: " $0;
next;
}
print "address=/" $2 "/0.0.0.0\naddress=/" $2 "/::";
next;
}
{ print "### ERROR unprocessed line: " $0; }
'
================================================
FILE: playbooks/roles/ad-blocking/files/transform-host-list
================================================
#!/bin/bash
awk '
BEGIN { print "# post-processed by transform-host-list"; }
/^#/ { print $0; next; }
/^0\.0\.0\.0 / { next; }
/^:: / {
if ($2 !~ /\./) {
print "### no dot found in hostname, skipping: " $0;
next;
}
print "0.0.0.0 " $2 "\n:: " $2;
next;
}
{ print "### ERROR unprocessed line: " $0; }
'
================================================
FILE: playbooks/roles/ad-blocking/tasks/main.yml
================================================
- name: "Install blocklist tools"
copy:
src: "{{ item }}"
dest: /usr/local/bin/
mode: '0755'
loop:
- download-blocklists
- transform-domain-list
- transform-host-list
- name: "Install blocklist systemd goo"
copy:
src: "{{ item }}"
dest: /etc/systemd/system/
mode: '0644'
loop:
- download-blocklists.service
- download-blocklists.timer
- name: "Enable the blocklist download service"
systemd:
name: download-blocklists.service
daemon_reload: true
enabled: true
state: started
- name: "Enable and start the blocklist re-download timer"
systemd:
name: download-blocklists.timer
enabled: true
state: started
================================================
FILE: playbooks/roles/azure-security-group/meta/main.yml
================================================
---
allow_duplicates: yes
================================================
FILE: playbooks/roles/azure-security-group/tasks/main.yml
================================================
---
- name: Create Azure resource group
azure_rm_resourcegroup:
name: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
- name: Create Azure virtual network
azure_rm_virtualnetwork:
resource_group: "{{ azure_resource_group_name }}"
name: "{{ azure_resource_group_name }}"
address_prefixes: "10.10.0.0/16"
- name: Create Azure subnet
azure_rm_subnet:
resource_group: "{{ azure_resource_group_name }}"
name: "{{ azure_resource_group_name }}"
address_prefix: "10.10.0.0/24"
virtual_network: "{{ azure_resource_group_name }}"
- name: Create Azure public ip
azure_rm_publicipaddress:
resource_group: "{{ azure_resource_group_name }}"
allocation_method: Static
name: "{{ azure_resource_group_name }}"
- name: Open all of the necessary ports across every service in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
# Nginx
# ---
- name: "AllowNGINX"
destination_port_range: "{{ nginx_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 101
# SSH
# ---
- name: "AllowSSHTCP"
destination_port_range: "{{ ssh_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 108
# HTTP (Let's Encrypt)
# ---
- name: "AllowHTTP"
destination_port_range: "{{ le_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 120
# Shadowsocks
# ---
- name: Open Shadowsocks ports in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
# Shadowsocks TCP
# ---
- name: "AllowShadowsocksTCP"
destination_port_range: "{{ shadowsocks_server_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 106
# Shadowsocks UDP
# ---
- name: "AllowShadowsocksUDP"
destination_port_range: "{{ shadowsocks_server_port }}"
protocol: Udp
access: Allow
direction: Inbound
priority: 107
when: streisand_shadowsocks_enabled
# WireGuard
# ---
- name: Open WireGuard ports in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
- name: "AllowWireguard"
destination_port_range: "{{ wireguard_port }}"
protocol: Udp
access: Allow
direction: Inbound
priority: 112
when: streisand_wireguard_enabled
# OpenConnect (ocserv)
# ---
- name: Open the OpenConnect ports in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
# OpenConnect TCP
# ---
- name: "AllowOCServTCP"
destination_port_range: "{{ ocserv_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 102
# OpenConnect UDP
# ---
- name: "AllowOCServUDP"
destination_port_range: "{{ ocserv_port }}"
protocol: Udp
access: Allow
direction: Inbound
priority: 103
when: streisand_openconnect_enabled
# OpenVPN
# ---
- name: Open the OpenVPN ports in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
# OpenVPN TCP
# ---
- name: "AllowOpenVPNTCP"
destination_port_range: "{{ openvpn_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 104
# OpenVPN UDP
# ---
- name: "AllowOpenVPNUDP"
destination_port_range: "{{ openvpn_port_udp }}"
protocol: Udp
access: Allow
direction: Inbound
priority: 105
when: streisand_openvpn_enabled
# stunnel
# ---
- name: Open the stunnel port in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
- name: "AllowStunnelTCP"
destination_port_range: "{{ stunnel_remote_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 109
when: streisand_openvpn_enabled and streisand_stunnel_enabled
# Tor
# ---
- name: Open Tor ports in the Azure security group
azure_rm_securitygroup:
name: "{{ azure_resource_group_name }}"
resource_group: "{{ azure_resource_group_name }}"
location: "{{ azure_region }}"
rules:
# Tor TCP
# ---
- name: "AllowTorTCP"
destination_port_range: "{{ tor_orport }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 110
# Tor obfs4 TCP port
# ---
- name: "AllowOBFS4TCP"
destination_port_range: "{{ tor_obfs4_port }}"
protocol: Tcp
access: Allow
direction: Inbound
priority: 111
when: streisand_tor_enabled
- name: Create Azure network interface
azure_rm_networkinterface:
resource_group: "{{ azure_resource_group_name }}"
name: "{{ azure_resource_group_name }}"
virtual_network: "{{ azure_resource_group_name }}"
subnet: "{{ azure_resource_group_name }}"
public_ip_name: "{{ azure_resource_group_name }}"
security_group: "{{ azure_resource_group_name }}"
================================================
FILE: playbooks/roles/azure-security-group/vars/main.yml
================================================
---
azure_resource_group_name: "streisand-{{ azure_instance_name }}"
================================================
FILE: playbooks/roles/certificates/defaults/main.yml
================================================
---
tls_key_country: "US"
tls_key_province: "California"
tls_key_city: "Beverly Hills"
tls_key_org: "ACME CORPORATION"
tls_key_ou: "Anvil Department"
tls_days_valid: "1825"
tls_default_md: "sha256"
tls_key_size: "4096"
# What type of certificates to be generated
# must be explicitly set by playbooks that
# include the certificates role
generate_ca_server: no
generate_client: no
generate_pkcs: no
================================================
FILE: playbooks/roles/certificates/tasks/ca-server.yml
================================================
---
- name: "Generate the private keys for the CA and Server certificates"
command: openssl genrsa -out {{ item }}.key {{ tls_key_size }}
args:
chdir: "{{ ca_path }}"
creates: "{{ item }}.key"
with_items:
- ca
- server
- name: Set the proper permissions on all the private keys
file:
path: "{{ ca_path }}"
recurse: yes
state: directory
owner: root
group: root
mode: 0600
- name: Generate CA certificate
command: openssl req -nodes -batch -new -x509 -key {{ tls_ca }}.key -days {{ tls_days_valid }} -out {{ tls_ca }}.crt -subj "{{ tls_request_subject }}/CN=ca-certificate"
args:
creates: "{{ tls_ca }}.crt"
- name: Generate a random server common name
shell: "{{ streisand_word_gen.long_identifier | trim }} > {{ tls_server_common_name_file }}"
args:
creates: "{{ tls_server_common_name_file }}"
- name: Set permissions on the TLS server common name file
file:
path: "{{ tls_server_common_name_file }}"
owner: root
group: root
mode: 0600
- name: Register the TLS server common name
command: cat "{{ tls_server_common_name_file }}"
register: tls_server_common_name
changed_when: False
- name: Generate the OpenSSL configuration that will be used for the server certificate's req and ca commands
template:
src: openssl.cnf.j2
dest: "{{ ca_path }}/openssl.cnf"
- name: Seed a blank database file that will be used when generating the Server's certificate
file:
path: "{{ ca_path }}/index.txt"
state: touch
- name: Seed a serial file that will be used when generating the Server's certificate
copy:
content: "01"
dest: "{{ ca_path }}/serial"
- name: Generate CSR for the Server
command: openssl req -batch -extensions server -new -key server.key -out server.csr -config {{ ca_path }}/openssl.cnf
args:
chdir: "{{ ca_path }}"
creates: server.csr
- name: Generate certificate for the Server
command: openssl ca -batch -extensions server -in server.csr -out server.crt -config openssl.cnf
args:
chdir: "{{ ca_path }}"
creates: server.crt
================================================
FILE: playbooks/roles/certificates/tasks/client.yml
================================================
---
- name: Create directories for clients
file:
path: "{{ tls_client_path }}/{{ client_name.stdout }}"
state: directory
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: Generate the private keys for the client certificates
command: openssl genrsa -out client.key {{ tls_key_size }}
args:
chdir: "{{ tls_client_path }}/{{ client_name.stdout }}"
creates: client.key
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: Set the proper permissions on all private client keys
file:
path: "{{ ca_path }}"
recurse: yes
state: directory
owner: root
group: root
mode: 0600
- name: Generate CSRs for the clients
command: openssl req -new -extensions client -key client.key -out client.csr -subj "{{ tls_request_subject }}/CN={{ client_name.stdout }}" -config {{ ca_path }}/openssl.cnf
args:
chdir: "{{ tls_client_path }}/{{ client_name.stdout }}"
creates: client.csr
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: Generate certificates for the clients
command: openssl x509 -extensions client -CA {{ tls_ca }}.crt -CAkey {{ tls_ca }}.key -CAcreateserial -req -days {{ tls_days_valid }} -in client.csr -out client.crt -extfile {{ ca_path }}/openssl.cnf
args:
chdir: "{{ tls_client_path }}/{{ client_name.stdout }}"
creates: client.crt
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: Authorize certificates via /etc/allowed_vpn_certs
template:
src: allowed_vpn_certs.j2
dest: /etc/allowed_vpn_certs
owner: root
group: root
mode: 0644
================================================
FILE: playbooks/roles/certificates/tasks/main.yml
================================================
---
- import_tasks: ca-server.yml
when: generate_ca_server
- import_tasks: client.yml
when: generate_client
- import_tasks: pkcs.yml
when: generate_pkcs
================================================
FILE: playbooks/roles/certificates/tasks/pkcs.yml
================================================
---
- name: "Generate a random password that will be used during the PKCS #12 conversion"
shell: "{{ streisand_word_gen.weak_password | trim }} > {{ tls_client_path }}/{{ client_name.stdout }}/{{ vpn_name }}-{{ client_name.stdout }}-pkcs12-password"
args:
creates: "{{ tls_client_path }}/{{ client_name.stdout }}/{{ vpn_name }}-{{ client_name.stdout }}-pkcs12-password"
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: "Set permissions on the PKCS #12 password file"
file:
path: "{{ tls_client_path }}/{{ client_name.stdout }}/{{ vpn_name }}-{{ client_name.stdout }}-pkcs12-password"
owner: root
group: root
mode: 0600
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
- name: "Register the PKCS #12 passwords"
command: cat {{ tls_client_path }}/{{ client_name.stdout }}/{{ vpn_name }}-{{ client_name.stdout }}-pkcs12-password
register: "vpn_client_pkcs12_password_list"
with_items: "{{ vpn_client_names.results }}"
loop_control:
loop_var: "client_name"
label: "{{ client_name.item }}"
changed_when: False
- name: "Convert the {{ vpn_name }} client keys and certificates into PKCS #12 format"
command: >
openssl pkcs12 -export
-in {{ tls_client_path }}/{{ vpn_client_password.client_name.stdout }}/client.crt
-inkey {{ tls_client_path }}/{{ vpn_client_password.client_name.stdout }}/client.key
-name {{ vpn_client_password.client_name.stdout }}
-out {{ tls_client_path }}/{{ vpn_client_password.client_name.stdout }}/{{ vpn_client_password.client_name.stdout }}.p12
-certfile {{ tls_client_path }}/ca.crt
-passout pass:"{{ vpn_client_password.stdout }}"
args:
creates: "{{ tls_client_path }}/{{ vpn_client_password.client_name.stdout }}/{{ vpn_client_password.client_name.stdout }}.p12"
with_items: "{{ vpn_client_pkcs12_password_list.results }}"
loop_control:
loop_var: "vpn_client_password"
label: "{{ vpn_client_password.client_name.item }}"
================================================
FILE: playbooks/roles/certificates/templates/allowed_vpn_certs.j2
================================================
# This file lists all the enabled VPN certificate names. Note that
# it does not affect WireGuard.
{% for client in vpn_client_names.results -%}
{{ client.stdout }}
{% endfor %}
================================================
FILE: playbooks/roles/certificates/templates/openssl.cnf.j2
================================================
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = {{ ca_path }}
certs = $dir
crl_dir = $dir
database = $dir/index.txt
new_certs_dir = $dir
certificate = {{ tls_ca }}.crt
serial = $dir/serial
crl = $dir/crl.pem
private_key = {{ tls_ca }}.key
RANDFILE = $dir/.rand
copy_extensions = copy
x509_extensions = server
default_days = {{ tls_days_valid }}
default_crl_days= 30
default_md = {{ tls_default_md }}
preserve = no
policy = policy_anything
keyUsage = cRLSign, keyCertSign
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
name = optional
emailAddress = optional
[ req ]
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
{% for item in tls_sans %}
IP.{{ loop.index }} = {{ item }}
{% endfor %}
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = {{ tls_key_country }}
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = {{ tls_key_province }}
localityName = Locality Name (eg, city)
localityName_default = {{ tls_key_city }}
0.organizationName = Organization Name (eg, company)
0.organizationName_default = {{ tls_key_org }}
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = {{ tls_key_ou }}
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_default = {{ tls_server_common_name.stdout }}
[ v3_ca ]
keyUsage = digitalSignature, keyEncipherment
[ server ]
basicConstraints=CA:FALSE
nsComment = "Ansible Generated Server Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
extendedKeyUsage=serverAuth
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ client ]
basicConstraints=CA:FALSE
nsComment = "Ansible Generated Client Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
extendedKeyUsage=clientAuth
keyUsage = digitalSignature
================================================
FILE: playbooks/roles/certificates/vars/main.yml
================================================
---
tls_request_subject: "/C={{ tls_key_country }}/ST={{ tls_key_province }}/L={{ tls_key_city }}/O={{ tls_key_org }}/OU={{ tls_key_ou }}"
================================================
FILE: playbooks/roles/cloudflared/defaults/main.yml
================================================
---
cloudflared_base_url: "https://bin.equinox.io/c/VdrWdbjqyF/"
cloudflared_amd64_apt: "cloudflared-stable-linux-amd64.deb"
cloudflared_amd64_yum: "cloudflared-stable-linux-amd64.rpm"
cloudflared_amd64_binary: "cloudflared-stable-linux-amd64.tgz"
cloudflared_arm_apt: "cloudflared-stable-linux-arm.deb"
cloudflared_arm_yum: "cloudflared-stable-linux-arm.rpm"
cloudflared_arm_binary: "cloudflared-stable-linux-arm.tgz"
cloudflared_allow_firewall: false
cloudflared_enable_service: true
cloudflared_upstream1: "https://1.1.1.1/dns-query"
cloudflared_upstream2: "https://1.0.0.1/dns-query"
cloudflared_port: 5053
cloudflared_options: "proxy-dns --port {{ cloudflared_port }} --upstream {{ cloudflared_upstream1 }} --upstream {{ cloudflared_upstream2 }}"
cloudflared_bin_location: /usr/local/bin
================================================
FILE: playbooks/roles/cloudflared/files/cloudflared.service
================================================
[Unit]
Description=cloudflared service
After=syslog.target network-online.target
[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
================================================
FILE: playbooks/roles/cloudflared/handlers/main.yml
================================================
---
- name: restart cloudflared service
systemd:
name: cloudflared.service
state: restarted
================================================
FILE: playbooks/roles/cloudflared/meta/main.yml
================================================
---
dependencies:
- { role: dnsmasq }
- { role: ip-forwarding }
================================================
FILE: playbooks/roles/cloudflared/tasks/install_binary.yml
================================================
---
- name: build filename of file to be downloaded
set_fact:
cloudflared_file: "{{ vars['cloudflared_'+device_arch+'_binary'] }}"
- name: download correct file for device
get_url:
url: "{{ cloudflared_base_url }}{{ cloudflared_file }}"
dest: "/tmp/{{ cloudflared_file }}"
#checksum: "{{ cloudflared_file_checksum }}"
- name: extract cloudflared into /usr/local/bin
unarchive:
src: "/tmp/{{ cloudflared_file }}"
dest: "{{ cloudflared_bin_location }}"
remote_src: yes
================================================
FILE: playbooks/roles/cloudflared/tasks/install_package.yml
================================================
---
- name: build filename of file to be downloaded
set_fact:
cloudflared_file: "{{ vars['cloudflared_'+device_arch+'_'+ansible_pkg_mgr] }}"
- name: download correct file for device
get_url:
url: "{{ cloudflared_base_url }}{{ cloudflared_file }}"
dest: "/tmp/{{ cloudflared_file }}"
#checksum: "{{ cloudflared_file_checksum }}"
- name: Install a .deb package
apt:
deb: "/tmp/{{ cloudflared_file }}"
state: present
register: pkg_mgr_output
ignore_errors: true
when: ansible_pkg_mgr == 'apt'
- name: Install a .rpm package
yum:
name: "/tmp/{{ cloudflared_file }}"
state: present
register: pkg_mgr_output
ignore_errors: true
when: ansible_pkg_mgr == 'yum'
================================================
FILE: playbooks/roles/cloudflared/tasks/main.yml
================================================
---
- stat:
path: "{{ cloudflared_bin_location }}/cloudflared"
register: cloudflared_binary
- set_fact:
cloudflared_installed: "{{ cloudflared_binary.stat.exists | default(false) }}"
- name: set device architecture and package manager vars
set_fact:
device_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm' }}"
- name: install package
import_tasks: install_package.yml
when: (not cloudflared_installed) and (ansible_pkg_mgr == 'yum' or ansible_pkg_mgr == 'apt') and (ansible_architecture == 'x86_64' or ansible_architecture == 'arm')
- name: install binary
import_tasks: install_binary.yml
when: (not cloudflared_installed) and ((pkg_mgr_output is undefined or pkg_mgr_output is failed) or ansible_architecture == 'armv7l')
- name: Set network capabilities for cloudflared
capabilities:
path: "{{ cloudflared_bin_location }}/cloudflared"
capability: cap_net_bind_service+ep
state: present
when: cloudflared_port|int < 1024
- command: cloudflared update
register: update_command
changed_when: update_command.rc == '64'
- name: create cloudflared nologin user
become: yes
user:
name: cloudflared
shell: /usr/sbin/nologin
system: True
create_home: False
- name: set ownership of /usr/local/bin/cloudflared
file:
path: /usr/local/bin/cloudflared
state: file
owner: cloudflared
group: cloudflared
- name: template config file
template:
src: cloudflared.j2
dest: /etc/default/cloudflared
owner: cloudflared
group: cloudflared
notify: restart cloudflared service
tags: systemd
- name: copy systemd service
copy:
src: cloudflared.service
dest: /etc/systemd/system/
owner: root
group: root
mode: 0644
notify: restart cloudflared service
register: service
tags: systemd
- name: enable systemd service
service:
name: cloudflared
enabled: "{{ cloudflared_enable_service }}"
when: service.changed
tags: systemd
- name: Allow port in firewall
ufw:
rule: allow
port: "{{ cloudflared_port }}"
comment: "allow cloudflared"
when: cloudflared_allow_firewall
# DNSMASQ
- name: Remove existing upstream servers in dnsmasq
replace:
path: /etc/dnsmasq.conf
regexp: "^server=(.*)$"
- name: Set upstream DNS server to cloudflared proxy
lineinfile:
path: /etc/dnsmasq.conf
state: present
line: "server=127.0.0.1#{{ cloudflared_port }}"
notify: Restart dnsmasq
================================================
FILE: playbooks/roles/cloudflared/templates/cloudflared.j2
================================================
# Commandline args for cloudflared
CLOUDFLARED_OPTS={{ cloudflared_options }}
================================================
FILE: playbooks/roles/cloudflared/vars/main.yml
================================================
---
# Cloudflared variables
================================================
FILE: playbooks/roles/common/files/english.txt
================================================
abandon
ability
able
about
above
absent
absorb
abstract
absurd
abuse
access
accident
account
accuse
achieve
acid
acoustic
acquire
across
act
action
actor
actress
actual
adapt
add
addict
address
adjust
admit
adult
advance
advice
aerobic
affair
afford
afraid
again
age
agent
agree
ahead
aim
air
airport
aisle
alarm
album
alcohol
alert
alien
all
alley
allow
almost
alone
alpha
already
also
alter
always
amateur
amazing
among
amount
amused
analyst
anchor
ancient
anger
angle
angry
animal
ankle
announce
annual
another
answer
antenna
antique
anxiety
any
apart
apology
appear
apple
approve
april
arch
arctic
area
arena
argue
arm
armed
armor
army
around
arrange
arrest
arrive
arrow
art
artefact
artist
artwork
ask
aspect
assault
asset
assist
assume
asthma
athlete
atom
attack
attend
attitude
attract
auction
audit
august
aunt
author
auto
autumn
average
avocado
avoid
awake
aware
away
awesome
awful
awkward
axis
baby
bachelor
bacon
badge
bag
balance
balcony
ball
bamboo
banana
banner
bar
barely
bargain
barrel
base
basic
basket
battle
beach
bean
beauty
because
become
beef
before
begin
behave
behind
believe
below
belt
bench
benefit
best
betray
better
between
beyond
bicycle
bid
bike
bind
biology
bird
birth
bitter
black
blade
blame
blanket
blast
bleak
bless
blind
blood
blossom
blouse
blue
blur
blush
board
boat
body
boil
bomb
bone
bonus
book
boost
border
boring
borrow
boss
bottom
bounce
box
boy
bracket
brain
brand
brass
brave
bread
breeze
brick
bridge
brief
bright
bring
brisk
broccoli
broken
bronze
broom
brother
brown
brush
bubble
buddy
budget
buffalo
build
bulb
bulk
bullet
bundle
bunker
burden
burger
burst
bus
business
busy
butter
buyer
buzz
cabbage
cabin
cable
cactus
cage
cake
call
calm
camera
camp
can
canal
cancel
candy
cannon
canoe
canvas
canyon
capable
capital
captain
car
carbon
card
cargo
carpet
carry
cart
case
cash
casino
castle
casual
cat
catalog
catch
category
cattle
caught
cause
caution
cave
ceiling
celery
cement
census
century
cereal
certain
chair
chalk
champion
change
chaos
chapter
charge
chase
chat
cheap
check
cheese
chef
cherry
chest
chicken
chief
child
chimney
choice
choose
chronic
chuckle
chunk
churn
cigar
cinnamon
circle
citizen
city
civil
claim
clap
clarify
claw
clay
clean
clerk
clever
click
client
cliff
climb
clinic
clip
clock
clog
close
cloth
cloud
clown
club
clump
cluster
clutch
coach
coast
coconut
code
coffee
coil
coin
collect
color
column
combine
come
comfort
comic
common
company
concert
conduct
confirm
congress
connect
consider
control
convince
cook
cool
copper
copy
coral
core
corn
correct
cost
cotton
couch
country
couple
course
cousin
cover
coyote
crack
cradle
craft
cram
crane
crash
crater
crawl
crazy
cream
credit
creek
crew
cricket
crime
crisp
critic
crop
cross
crouch
crowd
crucial
cruel
cruise
crumble
crunch
crush
cry
crystal
cube
culture
cup
cupboard
curious
current
curtain
curve
cushion
custom
cute
cycle
dad
damage
damp
dance
danger
daring
dash
daughter
dawn
day
deal
debate
debris
decade
december
decide
decline
decorate
decrease
deer
defense
define
defy
degree
delay
deliver
demand
demise
denial
dentist
deny
depart
depend
deposit
depth
deputy
derive
describe
desert
design
desk
despair
destroy
detail
detect
develop
device
devote
diagram
dial
diamond
diary
dice
diesel
diet
differ
digital
dignity
dilemma
dinner
dinosaur
direct
dirt
disagree
discover
disease
dish
dismiss
disorder
display
distance
divert
divide
divorce
dizzy
doctor
document
dog
doll
dolphin
domain
donate
donkey
donor
door
dose
double
dove
draft
dragon
drama
drastic
draw
dream
dress
drift
drill
drink
drip
drive
drop
drum
dry
duck
dumb
dune
during
dust
dutch
duty
dwarf
dynamic
eager
eagle
early
earn
earth
easily
east
easy
echo
ecology
economy
edge
edit
educate
effort
egg
eight
either
elbow
elder
electric
elegant
element
elephant
elevator
elite
else
embark
embody
embrace
emerge
emotion
employ
empower
empty
enable
enact
end
endless
endorse
enemy
energy
enforce
engage
engine
enhance
enjoy
enlist
enough
enrich
enroll
ensure
enter
entire
entry
envelope
episode
equal
equip
era
erase
erode
erosion
error
erupt
escape
essay
essence
estate
eternal
ethics
evidence
evil
evoke
evolve
exact
example
excess
exchange
excite
exclude
excuse
execute
exercise
exhaust
exhibit
exile
exist
exit
exotic
expand
expect
expire
explain
expose
express
extend
extra
eye
eyebrow
fabric
face
faculty
fade
faint
faith
fall
false
fame
family
famous
fan
fancy
fantasy
farm
fashion
fat
fatal
father
fatigue
fault
favorite
feature
february
federal
fee
feed
feel
female
fence
festival
fetch
fever
few
fiber
fiction
field
figure
file
film
filter
final
find
fine
finger
finish
fire
firm
first
fiscal
fish
fit
fitness
fix
flag
flame
flash
flat
flavor
flee
flight
flip
float
flock
floor
flower
fluid
flush
fly
foam
focus
fog
foil
fold
follow
food
foot
force
forest
forget
fork
fortune
forum
forward
fossil
foster
found
fox
fragile
frame
frequent
fresh
friend
fringe
frog
front
frost
frown
frozen
fruit
fuel
fun
funny
furnace
fury
future
gadget
gain
galaxy
gallery
game
gap
garage
garbage
garden
garlic
garment
gas
gasp
gate
gather
gauge
gaze
general
genius
genre
gentle
genuine
gesture
ghost
giant
gift
giggle
ginger
giraffe
girl
give
glad
glance
glare
glass
glide
glimpse
globe
gloom
glory
glove
glow
glue
goat
goddess
gold
good
goose
gorilla
gospel
gossip
govern
gown
grab
grace
grain
grant
grape
grass
gravity
great
green
grid
grief
grit
grocery
group
grow
grunt
guard
guess
guide
guilt
guitar
gun
gym
habit
hair
half
hammer
hamster
hand
happy
harbor
hard
harsh
harvest
hat
have
hawk
hazard
head
health
heart
heavy
hedgehog
height
hello
helmet
help
hen
hero
hidden
high
hill
hint
hip
hire
history
hobby
hockey
hold
hole
holiday
hollow
home
honey
hood
hope
horn
horror
horse
hospital
host
hotel
hour
hover
hub
huge
human
humble
humor
hundred
hungry
hunt
hurdle
hurry
hurt
husband
hybrid
ice
icon
idea
identify
idle
ignore
ill
illegal
illness
image
imitate
immense
immune
impact
impose
improve
impulse
inch
include
income
increase
index
indicate
indoor
industry
infant
inflict
inform
inhale
inherit
initial
inject
injury
inmate
inner
innocent
input
inquiry
insane
insect
inside
inspire
install
intact
interest
into
invest
invite
involve
iron
island
isolate
issue
item
ivory
jacket
jaguar
jar
jazz
jealous
jeans
jelly
jewel
job
join
joke
journey
joy
judge
juice
jump
jungle
junior
junk
just
kangaroo
keen
keep
ketchup
key
kick
kid
kidney
kind
kingdom
kiss
kit
kitchen
kite
kitten
kiwi
knee
knife
knock
know
lab
label
labor
ladder
lady
lake
lamp
language
laptop
large
later
latin
laugh
laundry
lava
law
lawn
lawsuit
layer
lazy
leader
leaf
learn
leave
lecture
left
leg
legal
legend
leisure
lemon
lend
length
lens
leopard
lesson
letter
level
liar
liberty
library
license
life
lift
light
like
limb
limit
link
lion
liquid
list
little
live
lizard
load
loan
lobster
local
lock
logic
lonely
long
loop
lottery
loud
lounge
love
loyal
lucky
luggage
lumber
lunar
lunch
luxury
lyrics
machine
mad
magic
magnet
maid
mail
main
major
make
mammal
man
manage
mandate
mango
mansion
manual
maple
marble
march
margin
marine
market
marriage
mask
mass
master
match
material
math
matrix
matter
maximum
maze
meadow
mean
measure
meat
mechanic
medal
media
melody
melt
member
memory
mention
menu
mercy
merge
merit
merry
mesh
message
metal
method
middle
midnight
milk
million
mimic
mind
minimum
minor
minute
miracle
mirror
misery
miss
mistake
mix
mixed
mixture
mobile
model
modify
mom
moment
monitor
monkey
monster
month
moon
moral
more
morning
mosquito
mother
motion
motor
mountain
mouse
move
movie
much
muffin
mule
multiply
muscle
museum
mushroom
music
must
mutual
myself
mystery
myth
naive
name
napkin
narrow
nasty
nation
nature
near
neck
need
negative
neglect
neither
nephew
nerve
nest
net
network
neutral
never
news
next
nice
night
noble
noise
nominee
noodle
normal
north
nose
notable
note
nothing
notice
novel
now
nuclear
number
nurse
nut
oak
obey
object
oblige
obscure
observe
obtain
obvious
occur
ocean
october
odor
off
offer
office
often
oil
okay
old
olive
olympic
omit
once
one
onion
online
only
open
opera
opinion
oppose
option
orange
orbit
orchard
order
ordinary
organ
orient
original
orphan
ostrich
other
outdoor
outer
output
outside
oval
oven
over
own
owner
oxygen
oyster
ozone
pact
paddle
page
pair
palace
palm
panda
panel
panic
panther
paper
parade
parent
park
parrot
party
pass
patch
path
patient
patrol
pattern
pause
pave
payment
peace
peanut
pear
peasant
pelican
pen
penalty
pencil
people
pepper
perfect
permit
person
pet
phone
photo
phrase
physical
piano
picnic
picture
piece
pig
pigeon
pill
pilot
pink
pioneer
pipe
pistol
pitch
pizza
place
planet
plastic
plate
play
please
pledge
pluck
plug
plunge
poem
poet
point
polar
pole
police
pond
pony
pool
popular
portion
position
possible
post
potato
pottery
poverty
powder
power
practice
praise
predict
prefer
prepare
present
pretty
prevent
price
pride
primary
print
priority
prison
private
prize
problem
process
produce
profit
program
project
promote
proof
property
prosper
protect
proud
provide
public
pudding
pull
pulp
pulse
pumpkin
punch
pupil
puppy
purchase
purity
purpose
purse
push
put
puzzle
pyramid
quality
quantum
quarter
question
quick
quit
quiz
quote
rabbit
raccoon
race
rack
radar
radio
rail
rain
raise
rally
ramp
ranch
random
range
rapid
rare
rate
rather
raven
raw
razor
ready
real
reason
rebel
rebuild
recall
receive
recipe
record
recycle
reduce
reflect
reform
refuse
region
regret
regular
reject
relax
release
relief
rely
remain
remember
remind
remove
render
renew
rent
reopen
repair
repeat
replace
report
require
rescue
resemble
resist
resource
response
result
retire
retreat
return
reunion
reveal
review
reward
rhythm
rib
ribbon
rice
rich
ride
ridge
rifle
right
rigid
ring
riot
ripple
risk
ritual
rival
river
road
roast
robot
robust
rocket
romance
roof
rookie
room
rose
rotate
rough
round
route
royal
rubber
rude
rug
rule
run
runway
rural
sad
saddle
sadness
safe
sail
salad
salmon
salon
salt
salute
same
sample
sand
satisfy
satoshi
sauce
sausage
save
say
scale
scan
scare
scatter
scene
scheme
school
science
scissors
scorpion
scout
scrap
screen
script
scrub
sea
search
season
seat
second
secret
section
security
seed
seek
segment
select
sell
seminar
senior
sense
sentence
series
service
session
settle
setup
seven
shadow
shaft
shallow
share
shed
shell
sheriff
shield
shift
shine
ship
shiver
shock
shoe
shoot
shop
short
shoulder
shove
shrimp
shrug
shuffle
shy
sibling
sick
side
siege
sight
sign
silent
silk
silly
silver
similar
simple
since
sing
siren
sister
situate
six
size
skate
sketch
ski
skill
skin
skirt
skull
slab
slam
sleep
slender
slice
slide
slight
slim
slogan
slot
slow
slush
small
smart
smile
smoke
smooth
snack
snake
snap
sniff
snow
soap
soccer
social
sock
soda
soft
solar
soldier
solid
solution
solve
someone
song
soon
sorry
sort
soul
sound
soup
source
south
space
spare
spatial
spawn
speak
special
speed
spell
spend
sphere
spice
spider
spike
spin
spirit
split
spoil
sponsor
spoon
sport
spot
spray
spread
spring
spy
square
squeeze
squirrel
stable
stadium
staff
stage
stairs
stamp
stand
start
state
stay
steak
steel
stem
step
stereo
stick
still
sting
stock
stomach
stone
stool
story
stove
strategy
street
strike
strong
struggle
student
stuff
stumble
style
subject
submit
subway
success
such
sudden
suffer
sugar
suggest
suit
summer
sun
sunny
sunset
super
supply
supreme
sure
surface
surge
surprise
surround
survey
suspect
sustain
swallow
swamp
swap
swarm
swear
sweet
swift
swim
swing
switch
sword
symbol
symptom
syrup
system
table
tackle
tag
tail
talent
talk
tank
tape
target
task
taste
tattoo
taxi
teach
team
tell
ten
tenant
tennis
tent
term
test
text
thank
that
theme
then
theory
there
they
thing
this
thought
three
thrive
throw
thumb
thunder
ticket
tide
tiger
tilt
timber
time
tiny
tip
tired
tissue
title
toast
tobacco
today
toddler
toe
together
toilet
token
tomato
tomorrow
tone
tongue
tonight
tool
tooth
top
topic
topple
torch
tornado
tortoise
toss
total
tourist
toward
tower
town
toy
track
trade
traffic
tragic
train
transfer
trap
trash
travel
tray
treat
tree
trend
trial
tribe
trick
trigger
trim
trip
trophy
trouble
truck
true
truly
trumpet
trust
truth
try
tube
tuition
tumble
tuna
tunnel
turkey
turn
turtle
twelve
twenty
twice
twin
twist
two
type
typical
ugly
umbrella
unable
unaware
uncle
uncover
under
undo
unfair
unfold
unhappy
uniform
unique
unit
universe
unknown
unlock
until
unusual
unveil
update
upgrade
uphold
upon
upper
upset
urban
urge
usage
use
used
useful
useless
usual
utility
vacant
vacuum
vague
valid
valley
valve
van
vanish
vapor
various
vast
vault
vehicle
velvet
vendor
venture
venue
verb
verify
version
very
vessel
veteran
viable
vibrant
vicious
victory
video
view
village
vintage
violin
virtual
virus
visa
visit
visual
vital
vivid
vocal
voice
void
volcano
volume
vote
voyage
wage
wagon
wait
walk
wall
walnut
want
warfare
warm
warrior
wash
wasp
waste
water
wave
way
wealth
weapon
wear
weasel
weather
web
wedding
weekend
weird
welcome
west
wet
whale
what
wheat
wheel
when
where
whip
whisper
wide
width
wife
wild
will
win
window
wine
wing
wink
winner
winter
wire
wisdom
wise
wish
witness
wolf
woman
wonder
wood
wool
word
work
world
worry
worth
wrap
wreck
wrestle
wrist
write
wrong
yard
year
yellow
you
young
youth
zebra
zero
zone
zoo
================================================
FILE: playbooks/roles/common/files/footer.html
================================================