xjkj8

Create a Tor WebTunnel bridge

To assist users behind restrictive firewalls, the Tor Project has developed pluggable transports. These obfuscate the connection between the user and the Tor network. WebTunnel is one such pluggable transport. It wraps the payload in a WebSocket-like HTTPS connection. This gives the impression that the user is simply browsing the web. This article shows you how to set up a Tor WebTunnel bridge, either for public distribution to users behind firewalls, or for your own private use.

1. Set up web server

If you already have a working web server, and you have done all the steps below, you can skip this section and go directly to section 2.

1.1. Create DNS records

You will need to purchase a domain name to implement the configuration in this article.

Example:

xjkj8.xyz

Add your domain to Cloudflare.

1.2. Set up hostname

Choose a subdomain that will be the hostname for your server.

Example:

wt.xjkj8.xyz

Wherever you see this example in what follows, change it to your own chosen hostname (subdomain).

Go to the Cloudflare DNS page for your domain. Add a DNS A record (or AAAA for IPv6) pointing from your subdomain (i.e. hostname) to your virtual private server IP address.

Turn the DNS record's proxy status off for now. The Cloudflare icon for an unproxied record (DNS only) is a gray cloud.

Click Save to save the new record you just added.

1.3. Open firewall

Open your server's firewall and/or security groups for input:

1.4. Install Nginx

SSH into your server as root.

The easiest way to install Nginx is to use your Linux distribution's repositories.

apt update && apt upgrade -y && apt autoremove -y

apt install nginx -y

Confirm that the default configuration is active (running):

systemctl status nginx

1.5. Create directory for web content

Create a new directory for the web root of your chosen hostname:

mkdir -p /var/www/wt.xjkj8.xyz/html

1.5. Create virtual host

Create a configuration file for a new site with your chosen hostname:

vi /etc/nginx/sites-available/wt.xjkj8.xyz

Insert contents like this, substituting in your own hostname:

server {
    listen 80;
    server_name wt.xjkj8.xyz;

    root /var/www/wt.xjkj8.xyz/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Save the file.

Enable the new virtual host by creating a symbolic link in /etc/nginx/sites-enabled:

ln -s /etc/nginx/sites-available/wt.xjkj8.xyz /etc/nginx/sites-enabled/

1.6. Restart Nginx

Restart Nginx with your new virtual host:

systemctl restart nginx

Check that Nginx is still active (running):

systemctl status nginx

1.7. Add camouflage web content

Add some web content to /var/www/wt.xjkj8.xyz/html. In the example given here, we will use PavelDoGreat/WebGL-Fluid-Simulation. Download the content:

curl -L https://github.com/PavelDoGreat/WebGL-Fluid-Simulation/archive/refs/heads/master.zip -O

Extract the archive:

apt install -y unzip

unzip master.zip

Copy the web content into place:

cp -r WebGL-Fluid-Simulation-master/* /var/www/wt.xjkj8.xyz/html

ls -l /var/www/wt.xjkj8.xyz/html

1.8. Obtain SSL certificate

Install the snap daemon:

apt install -y snapd

Install the certbot snap:

snap install --classic certbot

Create a symbolic link to the certbot binary:

ln -s /snap/bin/certbot /usr/bin/certbot

Invoke certbot. As always, replace the example hostname by your actual hostanme in the instruction below:

certbot --nginx --agree-tos --register-unsafely-without-email -d wt.xjkj8.xyz

The certificate is saved at /etc/letsencrypt/live/wt.xjkj8.xyz/fullchain.pem. The key is saved at /etc/letsencrypt/live/wt.xjkj8.xyz/privkey.pem.

Test certificate renewal with a dry run:

certbot renew --dry-run

Restart Nginx with your SSL virtual host:

systemctl restart nginx

Check that Nginx is still active (running):

systemctl status nginx

1.9. Turn on Cloudflare full settings

Now you can turn on the final configuration of Cloudflare.

On the DNS page, turn on your subdomain's proxy status. The Cloudflare icon turns to an orange cloud. Click Save to save your change.

On the SSL/TLS page, select Custom SSL/TLS, and configure Cloudflare to use the Full (Strict) option for your domain. Click Save to save your change.

1.10. Test web server

At this stage, open any browser and verify that you can connect to your web site, and that it displays the expected web content. For example:

https://wt.xjkj8.xyz

2. Add location block to virtual host configuration

When clients visit your web server, they will be connected to your WebTunnel proxy if they request the secret path.

2.1. Generate secret path

Generate a pseudorandom path by running this command:

< /dev/urandom tr -dc a-z0-9 | head -c${1:-24};echo;

Example:

ujonu8rp58uuz9du1sxo6tb1

2.2. Add location block to virtual host

Edit the configuration file for your virtual host:

vi /etc/nginx/sites-available/wt.xjkj8.xyz

It now includes an SSL server block listening on port tcp/443, generated by certbot. Insert in this server block a new location block, replacing the path in the example by your actual path:

    location = /ujonu8rp58uuz9du1sxo6tb1 {
        proxy_pass http://127.0.0.1:10000;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header        Accept-Encoding   "";
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        add_header              Front-End-Https   on;

        proxy_redirect     off;
        access_log  off;
        error_log /dev/null;
    }

Note that WebTunnel is deliberately hidden, so you do not need to open port tcp/10000 in your firewall.

Save the virtual host configuration file.

2.3. Reload Nginx

Reload Nginx with your new configuration:

systemctl reload nginx

3. Build WebTunnel server binary

3.1. Install Golang

Install Git and the Go language compiler:

apt update && apt upgrade -y && apt autoremove -y

apt install -y git golang

Check your installation:

git -v

go version

3.2. Clone WebTunnel source code

Clone the WebTunnel git repository:

git clone https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel

3.3. Compile WebTunnel

Compile the WebTunnel server binary:

cd webtunnel/main/server

go build

3.4. Install WebTunnel

Copy the server binary to a location in your execution path:

cp server /usr/local/bin/webtunnel

4. Install Tor

Install the prerequisite packages:

apt install -y gnupg apt-transport-https lsb-release

Determine your distribution's code name:

lsb_release -cs

Example:

bookworm

Create a new repository list for the Tor Project:

vi /etc/apt/sources.list.d/tor.list

Insert contents like this, replacing bookworm by your actual distribution code name:

deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org bookworm main
deb-src [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org bookworm main

Save the file.

Download and import the Tor Project keyring:

wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null

Update your package metadata due to the new repositories:

apt update

And install Tor:

apt install -y tor deb.torproject.org-keyring

5. Configure Tor

Edit your Tor configuration file:

vi /etc/tor/torrc

Delete the existing contents.

Insert new contents modeled on the following:

BridgeRelay 1
ORPort 127.0.0.1:auto
AssumeReachable 1
ServerTransportPlugin webtunnel exec /usr/local/bin/webtunnel
ServerTransportListenAddr webtunnel 127.0.0.1:10000
ServerTransportOptions webtunnel url=https://wt.xjkj8.xyz/ujonu8rp58uuz9du1sxo6tb1
ExtORPort auto
ContactInfo [email protected]
Nickname bridgexjkj8
SocksPort 0

Replace the hostname, path, email address, and server nickname by your actual values.

By default, the bridge will be distributed to whoever requests it. If you want the bridge to be reserved for your private use, then append a line:

BridgeDistribution none

Save the file.

Restart tor:

systemctl restart tor@default

systemctl status tor@default

6. Configure AppArmor

Determine if AppArmor is running on your system:

apparmor_status

If so, edit the AppArmor system_tor profile, which is in the file /etc/apparmor.d/system_tor:

vi /etc/apparmor.d/system_tor

Add an entry before the closing curly brace } allowing tor to execute webtunnel:

# During startup, tor (as root) tries to open various things such as
# directories via check_private_dir().  Let it.
/usr/local/bin/webtunnel ix,

Save the file.

Reload the AppArmor profile:

apparmor_parser -r /etc/apparmor.d/system_tor

7. Review log

Check the logs for the tor@default systemd service unit:

journalctl -e -u tor@default

You may see a line complaining about your IPv4 ORPort address 127.0.0.1. This is fine, because Nginx will listen for external connections and pass them to 127.0.0.1.

To confirm your bridge is running with no issues, you should see something like this:

[notice] Bootstrapped 100%: Done

Display your Tor installation's fingerprint:

cat /var/lib/tor/fingerprint

Example:

bridgexjkj8 16803...EDBA3

Display your Tor installation's hashed fingerprint:

cat /var/lib/tor/hashed-fingerprint

Example:

bridgexjkj8 A07CA...89047

You can monitor your WebTunnel bridge's status on Relay Search. Just enter your bridge's hashed fingerprint (without the nickname) and click Search. It will take about three hours for your bridge to show up after you first create it.

8. Test WebTunnel bridge

If your bridge is running, you can test it by copying and pasting your bridge line into Tor Browser.

Build a bridge line modeled on the following:

webtunnel 10.0.0.2:443 16803...4EDBA3 url=https://wt.xjkj8.xyz/ujonu8rp58uuz9du1sxo6tb1

Replace the fingerprint, hostname, and secret path in the above. 10.0.0.2:443 is just a meaningless IP address and port that are never used for anything. They are there only because the pluggable transport syntax requires them.

When you start Tor Browser, click Configure Connection.

Scroll down to where it says Enter bridge address you already know, and click Add new bridges....

Enter your WebTunnel bridge line, and click Next.

Click Connect.

To test your connectivity, follow the steps of the Standard testing procedure.