Personal Proxy on IPv6 + NAT IPv4 Server

In some countries, mainstream sites like Google, YouTube, and Wikipedia are blocked by censors. People who want to get around the censors have to use VPNs or encrypted proxies. Some countries have the additional problem of a devalued currency. People in these countries want to build their proxy server as cheaply as possible, and this means IPv6 with shared NAT IPv4. This post is aimed at these users. It requires two things:

  • An Ubuntu 20.04 server with IPv6 and NAT IPv4, and a minimum of 256 MB RAM. This tutorial was developed on a dual-stack VPS with both IPv6 and IPv4, so if you want to test it on a real NAT IPv4 server, you are welcome to go ahead and leave your results in the comments.
  • You’ll also need a domain name, either a free one or one of those dollar-a-year introductory offers.

At your domain name registrar, create an AAAA record pointing from your hostname — let’s use www.example.com as our example — to your server’s IPv6 address.

Now you have your server provisioned, we’re ready to go.

Create Camouflage Website:

Part of the art of getting past censors is to disguise your proxy server as a web server. For this reason, you need to install Nginx and some realistic but uncontroversial web pages. Install Nginx like this:

apt update && apt upgrade -y
apt install nginx -y

Add some content, so that your web server looks like a real web server. What follows is just an example. You can add whatever content you like so that your server passes manual inspection by the censors:

apt install wget zip unzip -y
wget https://github.com/arcdetri/sample-blog/archive/master.zip
unzip master.zip
cp -rf sample-blog-master/html/* /var/www/html/

Now configure Nginx to listen on IPv6 only, and specify the actual name of your server. We’re using www.example.com in the templates here. Edit /etc/nginx/sites-available/default and make it look like this:

server {
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html;
        server_name www.example.com;
        location / {
                try_files $uri $uri/ =404;

Save the file, and restart Nginx with your new configuration:

systemctl restart nginx

Install Let’s Encrypt SSL Certificate:

To get past censors you need to encrypt traffic between your client and the server. To offer an encrypted HTTPS website, we’ll use a free SSL certificate from the Let’s Encrypt project. You’ll need to have waited an hour or more for your DNS records to propagate before you proceed. You can check at Network-Tools or CentralOps to see if they know about your www.example.com server name and a query type of AAAA.

Once your DNS records have propagated, obtain your Let’s Encrypt SSL certificate using the Certbot client:

apt install certbot python3-certbot-nginx -y
certbot --nginx
certbot renew --dry-run

When I tested this, I experienced a problem with the Certbot renew attempt not connecting to my server. If this happens to you, you can retry with webroot authentication like this:

certbot certonly --webroot -w /var/www/html -d www.example.com
certbot renew --dry-run

Protect Server with Cloudflare:

It’s also helpful to conceal your server’s IP address. We do that by positioning the server behind a Content Distribution Network. The CDN we use here is Cloudflare.

Add your domain to Cloudflare. If you don’t already have a Cloudflare account, you’ll be prompted to create one when you create your first domain. Specify that you want the FREE plan.

Now you need to change your domain’s nameservers at your domain name registrar. Cloudflare will provide you with the new Cloudflare nameservers you need to use.

Back at Cloudflare, set the SSL/TLS Encryption mode to Full.

Wait a few hours for the email to arrive saying the domain is now active on Cloudflare. Then check that your server now gives Cloudflare IPv4 and IPv6 addresses, and not the real IPv6 address of your server.

nslookup www.example.com

At this point, you can check in a browser to see what a censor visiting your server would see:


Install V2Ray Plugin

Install the V2Ray plugin for Shadowsocks on the server:

wget https://github.com/shadowsocks/v2ray-plugin/releases/download/v1.3.1/v2ray-plugin-linux-amd64-v1.3.1.tar.gz
tar -xf v2ray-plugin-linux-amd64-v1.3.1.tar.gz
cp v2ray-plugin_linux_amd64 /usr/bin/v2ray-plugin

Install Shadowsocks-libev:

Now we come to the Shadowsocks install in the server. The version of Shadowocks we’ll use is Shadowsocks-libev. It’s written in pure C and is designed to be a lightweight implementation of the Shadowsocks protocol that keeps resource usage as low as possible. Also, Shadowsocks-libev supports plugins.

Install the package:

apt install shadowsocks-libev -y

Edit the configuration file /etc/shadowsocks-libev/config.json. Make the contents look like the template below. Replace the password and secret path by your actual chosen values.


Save the file, and restart Shadowsocks on the server:

systemctl restart shadowsocks-libev

Pass Traffic from Nginx to SS+V2Ray:

Incoming traffic arrives first at Nginx. If the user requests the secret path, Nginx passes the request to Shadowsocks+V2Ray. (You must keep the path name secret and hard to guess.) To do this hand-off, add a new Nginx location block within the server block for port 443. Edit the configuration file /etc/nginx/sites-available/default. Add the block as specified:

location /abc123 {
    proxy_redirect off;
    proxy_pass http://[::1]:10001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;

Save the file, and restart Nginx:

systemctl restart nginx

Configure Client

The V2Ray plugin exists for Windows, macOS, Linux, FreeBSD, and Android. In this post, we will use Android as our sample client.

  • Install Shadowsocks by Max Lv. You can get it from the Google Play Store. If that is censored in your country, you can get it from GitHub.
  • Install the V2Ray Plugin by Max Lv. You can also get it from the Google Play Store or from GitHub.

Open the Shadowsocks app. Add a new profile, creating it from Manual Settings:

  • Profile Name = ss+v2ray
  • Server = www.example.com
  • Remote Port = 443
  • Password = pass1234
  • Encrypt Method = chacha20-ietf-poly1305
  • Route = All
  • IPv6 Route = On
  • Apps VPN Mode = Off
  • Metered Hint = Off
  • Remote DNS =
  • Send DNS over UDP = Off
  • Plugin = v2ray
  • Transport mode = websocket-tls
  • Hostname = www.example.com
  • Path = /abc123
  • Concurrent connections = 1
  • Certificate for TLS verification = Not set
  • Logcat level = warning
  • Generated line = path=/abc123;host=www.example.com;tls
  • UDP Fallback = Disabled

Now open a browser and connect to the web via your encrypted proxy server. Happy surfing!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back to top button