-
Notifications
You must be signed in to change notification settings - Fork 887
HAProxy Setup
As root, install acme.sh:
git clone https://github.com/Neilpang/acme.sh.git
cd ./acme.sh
./acme.sh --install
. ~/.bashrc
Issue ECC and RSA certificates for example.org (assuming an HTTP server running at /var/www/html
):
site=example.org
acme.sh -k ec-256 -d $site -d www.$site --issue -w /var/www/html
acme.sh -k 2048 -d $site -d www.$site --issue -w /var/www/html
Install in bundled format as required by HAProxy for supporting dual certificates:
mkdir -p /etc/haproxy/certs
acme.sh --install-cert --ecc -d $site --key-file /tmp/$site.key --fullchain-file /tmp/$site.crt --reloadcmd "cat /tmp/$site.* >/etc/haproxy/certs/$site.pem.ecdsa; rm /tmp/$site.*; service haproxy restart"
acme.sh --install-cert -d $site --key-file /tmp/$site.key --fullchain-file /tmp/$site.crt --reloadcmd "cat /tmp/$site.* >/etc/haproxy/certs/$site.pem.rsa; rm /tmp/$site.*; service haproxy restart"
Here acme.sh also automatically installs a crontab for certificate renewal.
apt install tinyproxy
.
Edit /etc/tinyproxy/tinyproxy.conf
:
User tinyproxy
Group tinyproxy
PidFile "/run/tinyproxy/tinyproxy.pid"
MaxClients 100
MinSpareServers 5
MaxSpareServers 20
StartServers 10
Port 8888
Listen 127.0.0.1
LogFile "/dev/null"
DisableViaHeader Yes
You can also use NaiveProxy as the forward proxy: nohup ./naive --listen=http://127.0.0.1:8080 &
. Although as a proxy server it only works together with Naive client, not directly with the browser (only HTTPS works).
apt install haproxy
on server. (Make sure it is 1.8.15+ or 1.9+.)
Append the following to /etc/haproxy/haproxy.cfg
:
userlist users
user name insecure-password pass
frontend haproxy_tls
bind :443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
option http-use-proxy-header
acl login base_dom login-key.test
acl auth_ok http_auth(users)
http-request auth if login !auth_ok
http-request redirect location https://google.com if login auth_ok
use_backend proxy if auth_ok
default_backend masquerade
backend proxy
http-request del-header proxy-authorization
server proxy 127.0.0.1:8888
backend masquerade
server nginx 127.0.0.1:80
Without credentials the proxy disguises as a regular HTTP server, rejecting proxy requests.
If your browser can't preset credentials, visit https://login-key.test
to login with name
and pass
. (http://login-key.test
doesn't work!)
name
, pass
, and login-key.test
should be changed to something hard to guess, e.g. login-<random-digits>.test
.
HTTPS proxying on Android needs a URL for a PAC file. Add the following to the top of frontend haproxy_tls
section after the bind
clause:
acl pac path /proxy-key.pac
errorfile 200 /etc/haproxy/errors/proxy.pac.http
http-request deny deny_status 200 if pac
proxy-key.pac
should be changed to something hard to guess.
The content of /etc/haproxy/errors/proxy.pac.http
should look like (double new lines at the end):
HTTP/1.0 200 OK
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
function FindProxyForURL(url, host) {
if (shExpMatch(host, "localhost")) return "DIRECT";
if (shExpMatch(host, "192.168.*")) return "DIRECT";
if (shExpMatch(host, "127.0.*")) return "DIRECT";
return "HTTPS example.org";
}
Check https://github.com/klzgrad/naiveproxy/wiki/Parameter-Tuning.
Also, consider deploying a caching DNS server to speed up DNS resolution.
The overall rationale is to select the most commonly used pieces of software/configurations so there are less distinguishable features to detect.
HAProxy is one of the commonly used traffic front-ends here for removing traffic signatures. Nginx is more popular but it hardly supports HTTP CONNECT tunnels and even less so for HTTP/2 proxying. Apache Traffic Server seems to have a lot of bugs; I didn't manage to make it work. Nghttpx doesn't do application-layer routing.
https://github.com/cloudflare/sslconfig is used as the TLS cipher list here because it seems quite the standard. TLS cipher selection can be very non-trivial and can leak a lot of entropy, see https://ssllabs.com/. There is also this https://mozilla.github.io/server-side-tls/ssl-config-generator/. The two main considerations here are to use elliptic curve cryptos for signatures which are faster than RSA, and to prioritize ChaPoly for encryption which can be energy efficient on mobile devices (if AES is not CPU-accelerated, otherwise it's not that much). The cipher list used here is modified from Cloudflare's list because This is no longer the case as Debian provides a modern cipher list by default via https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate.[algo1|algo2]
("bracketed equal-preference") is specific to BoringSSL and not supported in OpenSSL built with HAProxy.
Let's Encrypt is used for TLS certificates. Let's Encrypt may seem to have issued a lot of certificates but many of those are issued for malware and phising sites too, which means using Let's Encrypt doesn't really exempt your domain names from scrutiny. In fact, for the purpose of reducing traffic features it's probably no better than creating TLS certificates with your own self-signed root CA (different from self-signed certificates). Here we use Let's Encrypt because it's easier to setup, without having to manipulate the user's root CA store. We use acme.sh to issue both RSA and ECC certificates because the dual certificate setup is common (the business reason is usually to improve browser compatibility). certbot doesn't support ECC certificates yet. acme.sh's reloadcmd may look unwieldy because HAProxy has some specific requirements for dual certificate files and acme.sh's HAProxy hook doesn't do that yet.
Tinyproxy is used instead of Squid only because I didn't figure out how to set up transparent proxying with Squid.