NaiveProxy + Caddy 2
NaiveProxy is an anticensorship tool that uses Chrome’s network stack to better camouflage your traffic. Recent versions of NaiveProxy (we are currently on NaiveProxy 91) are implemented as customized builds of Caddy 2’s ForwardProxy plugin. Caddy 2 is a major revision of Caddy 1.
Prebuilt clients for NaiveProxy are available for Android, Linux, OpenWRT, macOS, and Windows.
In this article, you’ll learn how to install and configure NaiveProxy and Caddy 2 on a Debian or Ubuntu server and client. The procedure has been tested with a server running Ubuntu 21.04.
1. Set Up Server
1.1. Get Domain Name and Server
Before you set up your NaiveProxy server, you’ll need to acquire a domain name. If you do not already have a domain name registrar, you can check out Freenom (free) or Porkbun (paid) or any other registrar of your choosing.
You’ll also need a virtual private server (VPS). If you do not already have a VPS provider, you can check out Linode or Google or any other provider of your choice.
At your domain name registrar, create DNS type A
records pointing from the naked domain and the www
subdomain to the public IP address of
your VPS. You’ll need to allow some time for the DNS addition to propagate. On a PC, you can check to see if the propagation has happened by looking up your domain and
subdomain. For example, if your domain name is example.com
, then open a command prompt and issue the commands:
nslookup example.com
nslookup www.example.com
1.2. Install and Configure Firewall
There are multiple ways to implement a firewall on a Debian/Ubuntu server: nftables, iptables, ufw, and firewalld. The modern way is nftables, and that is what we will use here.
SSH into your server as root
. Issue each of the following commands in turn to install and start nftables:
apt update && apt upgrade -y
apt install nftables -y
systemctl enable nftables
systemctl start nftables
Configure the firewall to accept related traffic, internal traffic, and ping
requests:
nft add rule inet filter input ct state related,established counter accept
nft add rule inet filter input iif lo counter accept
nft add rule inet filter input ip protocol icmp icmp type echo-request counter accept
nft add rule inet filter input ip6 nexthdr icmpv6 icmpv6 type echo-request counter accept
Open port 22
for SSH. (If you can restrict the port 22
rule so that only certain source IP addresses are whitelisted for SSH access, then
so much the better.)
nft add rule inet filter input tcp dport 22 counter accept
Open ports 80 and 443 for HTTP and HTTPS requests, respectively:
nft add rule inet filter input tcp dport { http, https } counter accept
Drop all unexpected input:
nft add rule inet filter input counter drop
Save the rules:
nft list ruleset > /etc/nftables.conf
1.3. Implement BBR
Bottleneck Bandwidth and Round-trip propagation time (BBR) is a TCP congestion control algorithm developed at Google. Under certain types of network congestion, it will improve your latency. Implement BBR TCP congestion control on your server with the following commands:
cat >> /etc/sysctl.d/50-bbr.conf <<EOF
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
sysctl -p /etc/sysctl.d/50-bbr.conf
1.4. Create Camouflage Website
So that your server can pass a manual inspection, install a few pages of web content. Make a directory for the web pages:
mkdir -p /var/www/html
Install the prerequisite utilities:
apt install wget zip unzip -y
Get some sample web pages from GitHub:
wget https://github.com/arcdetri/sample-blog/archive/master.zip
Unzip the downloaded sample web pages:
unzip master.zip
Copy the web pages into place in your directory for web pages:
cp -rf sample-blog-master/html/* /var/www/html/
1.5. Install Go Language
On your PC, open Firefox and visit golang.org/dl. Determine the most recent version of Go for 64-bit Linux. At
the time of writing, this is named go1.16.5.linux-amd64.tar.gz
.
In your SSH session with your server, download the archive for the Go language:
wget https://golang.org/dl/go1.16.5.linux-amd64.tar.gz
Extract the archive into /usr/local
:
tar -C /usr/local -xzf go1.16.5.linux-amd64.tar.gz
Add /usr/local/go/bin
to your executable PATH by editing the system-wide profile:.
vi /etc/profile
Add a line at the end:
export PATH=$PATH:/usr/local/go/bin
Write the file to disk, and quit the editor. Log out and log in again:
exit
ssh root@www.example.com
Check that the Go language is installed by issuing the command:
go version
You should see a response that looks like this:
go version go1.16.5 linux/amd64
1.6. Get Source for ForwardProxy
Get the source code for the NaiveProxy version of Caddy’s ForwardProxy:
apt install git -y
git clone -b naive https://github.com/klzgrad/forwardproxy
1.7. Custom Build of Caddy 2
Download and install packages and dependencies for custom builds of the Caddy 2 web server:
go get -u github.com/caddyserver/xcaddy/cmd/xcaddy
Use xcaddy to build Caddy with the ForwardProxy plugin, as modified by the NaiveProxy project, which you just downloaded:
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy=$PWD/forwardproxy
The download and build will take several minutes. The final lines read something like this:
2021/06/12 15:45:24 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /root/caddy -ldflags -w -s -trimpath
2021/06/12 15:49:19 [INFO] Build complete: ./caddy
2021/06/12 15:49:19 [INFO] Cleaning up temporary folder: /tmp/buildenv_2021-06-12-1544.050638754
Once it has finished, copy the Caddy binary into a more central location:
cp caddy /usr/bin
1.8. Allow Caddy to Bind to Privileged Ports
Allow Caddy to bind to “privileged” ports (i.e. TCP/IP port numbers below 1024):
setcap cap_net_bind_service=+ep /usr/bin/caddy
1.9. Generate Strong Password
Generate a strong password to access your proxy server:
cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c32; echo;
The example result that we will use in the rest of this tutorial:
MFUZ4eMngSRJ9888tvM8S9HjEULm2Ptj
1.10. Configure Caddy with Forwardproxy
Edit the Caddy configuration JSON file:
mkdir /etc/caddy
vi /etc/caddy/config.json
Use the template below, making these changes:
- Replace
yourname
by your choice of username for NaiveProxy authentication - Replace
MFUZ4eMngSRJ9888tvM8S9HjEULm2Ptj
by your actual password - Replace
example.com
andwww.example.com
by your domain name and hostname (3 lines affected) - Replace
youremail@example.com
by your actual email address for Let’s Encrypt notifications
{ "admin": {"disabled": true}, "logging": { "sink": {"writer": {"output": "discard"}}, "logs": {"default": {"writer": {"output": "discard"}}} }, "apps": { "http": { "servers": { "srv0": { "listen": [":443"], "routes": [{ "handle": [{ "handler": "forward_proxy", "hide_ip": true, "hide_via": true, "auth_user_deprecated": "yourname", "auth_pass_deprecated": "MFUZ4eMngSRJ9888tvM8S9HjEULm2Ptj", "probe_resistance": {"domain": ""} }] }, { "match": [{"host": ["example.com", "www.example.com"]}], "handle": [{ "handler": "file_server", "root": "/var/www/html" }], "terminal": true }], "tls_connection_policies": [{ "match": {"sni": ["example.com", "www.example.com"]} }] } } }, "tls": { "automation": { "policies": [{ "subjects": ["example.com", "www.example.com"], "issuer": { "email": "youremail@example.com", "module": "acme" } }] } } } }
Write the file to disk, and quit the editor.
1.11. Create Systemd Service File
Create a systemd service file for Caddy:
vi /usr/lib/systemd/system/caddy.service
Insert contents like this:
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target
[Service]
ExecStart=/usr/bin/caddy run --config /etc/caddy/config.json
[Install]
WantedBy=multi-user.target
Write the file to disk, and quit the editor.
1.12. Run Caddy on Server
Start Caddy with the NaiveProxy version of ForwardProxy:
systemctl enable caddy
systemctl start caddy
Check that the status is active (running)
:
systemctl status caddy
Check that Caddy is listening on ports 80
and 443
:
ss -tulpn | grep caddy
Exit your SSH session with the server:
exit
You can check that the camouflage website is in place by opening Firefox on your PC and visiting your host, e.g., https://www.example.com
.
2. Set Up Client
2.1. Download NaiveProxy Client
Now go to work on your PC. Open your browser, and visit the releases page for NaiveProxy.
Download the latest release of the NaiveProxy client. We will use Windows as our example client. For example, at the time of writing the client for Windows is named
naiveproxy-v91.0.4472.77-1-win-x64.zip
.
Extract the zip file.
2.2. Configure NaiveProxy Client
Edit the configuration file for the NaiveProxy client, which is named config.json
:
Use the template below, making these changes:
- Replace
yourname
by your choice of username for NaiveProxy authentication - Replace
MFUZ4eMngSRJ9888tvM8S9HjEULm2Ptj
by your actual password - Replace
www.example.com
by your hostname
{
"listen": "socks://127.0.0.1:1080",
"proxy": "https://yourname:MFUZ4eMngSRJ9888tvM8S9HjEULm2Ptj@www.example.com"
}
Save the file.
2.3. Run NaiveProxy
In a Command Prompt window on the client, run the NaiveProxy client with your configuration file:
cd Downloads\naiveproxy-v91.0.4472.77-1-win-x64\naiveproxy-v91.0.4472.77-1-win-x64
naive config.json
Leave the Command Prompt window open, with the NaiveProxy client still running in it. NaiveProxy is listening on port 1080
.
2.4. Configure Firefox
Open Firefox. From the hamburger menu, select Settings > General. Scroll down to Network Settings. Click the Settings button.
- Select Manual proxy configuration.
- Enter SOCKS Host
127.0.0.1
. - Enter Port
1080
. - Select SOCKS v5.
- Check Proxy DNS when using SOCKS v5.
- Click OK.
2.5. End-to-end Test
Visit IP Chicken.
You should see the IP address of your remote server, not your local client.
3. Get Help and Report Issues
Report any NaiveProxy issues on GitHub.
Updated 2021-06-12