Xray diverting outbound via Cloudflare WARP

Xray offers WireGuard as a outbound protocol possibility.

This feature is not intended for tunneling through a firewall. WireGuard is too easy to detect.

Rather it is intended to provide you with the possibility of diverting your outbound traffic through Cloudflare. By routing your traffic (in WireGuard protocol) to a free Cloudflare node, your traffic will reach its final destination from an IP address different from your server’s IP address.

This is especially important for traffic that returns to your own country. You do not want packets to go out and return directly from the same IP address. That would make it obvious that your server is a proxy server.

Rather you divert such packets through Cloudflare. That way they come back to your country from an anonymous-looking Cloudflare WARP IP address.

(WARP is Cloudflare’s VPN service. Using WARP, you connect to the Internet through Cloudflare’s servers, optimizing your traffic along the way.)

The stages in configuring Xray to divert traffic through Cloudflare WARP servers are:

  1. Register for a Cloudflare WARP account, which in the process generates a Cloudflare WARP configuration.
  2. Export your Cloudflare WARP configuration in sing-box format.
  3. Use your WARP configuration to add a new outbound from your Xray server that routes traffic through Cloudflare WARP using the WireGuard protocol.
  4. Add routing instructions that determine which packets are to be diverted through Cloudflare WARP.

For a detailed example see https://github.com/chika0801/Xray-examples/blob/main/wireguard.md.

There’s an old stock market adage, “If a system becomes too well known, it stops working.”

The same thing applies to tunneling. If everyone else is using a system, eventually it gets blocked. There’s a lot to be said for choosing a method different from everyone else’s.

In this post, you’ll tunnel your traffic though WireGuard, then tunnel the WireGuard connection through Xray.

Both server and client in this tutorial run Ubuntu Linux 22.04.

Tunnel WireGuard through Xray

Server

Domain name

Since we are using Xray Vision, your server will need a domain name and a DNS A record for this tutorial.

Our hostname (fully qualified domain name) in the examples will be:

1
charlie.cscot.buzz

We represent the server IP address as <SERVER-IP-ADDRESS>.

Prepare server

SSH into your server, replacing <SERVER-IP-ADDRESS> by your actual server IP address:

1
ssh root@<SERVER-IP-ADDRESS>

Suppress lengthy login messages:

1
touch .hushlogin

Get your existing package metadata up to date, and upgrade all existing packages:

1
apt update && apt upgrade

You may be prompted to reboot and SSH back in again.

Protect your server with iptables, replacing <HOME-IP-ADDRESS> by your actual home IP address:

1
2
3
4
5
6
7
8
9
10
11
12
13
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s <HOME-IP-ADDRESS> -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -P INPUT DROP

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -P INPUT DROP

Notice that we opened ports 80/tcp and 443/tcp, but we did not open the WireGuard port 51820/udp. This is because the WireGuard traffic will pass through the Xray tunnel instead of arriving directly.

Check that you can still access the server with the above rules before you make them permanent:

1
exit

Reconnect:

1
ssh root@<SERVER-IP-ADDRESS>

Make the iptables rules permanent:

1
apt install iptables-persistent

Get an SSL certificate for the server

Use the Automatic Certificate Management Environment (ACME) script to request an SSL certificate for your server. In the commands that follow, replace both occurrences of charlie.cscot.buzz by your actual server hostname:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apt install socat

curl https://get.acme.sh | sh

alias acme.sh=~/.acme.sh/acme.sh

acme.sh --upgrade --auto-upgrade

acme.sh --set-default-ca --server letsencrypt

acme.sh --issue -d charlie.cscot.buzz --standalone --keylength ec-256

acme.sh --install-cert -d charlie.cscot.buzz --ecc --fullchain-file /etc/ssl/private/fullchain.cer --key-file /etc/ssl/private/private.key

chown -R nobody:nogroup /etc/ssl/private/

Install web server

The web server will receive control from Xray and handle fallbacks.

Install the Nginx web server:

1
apt install nginx

Edit the web server configuration file:

1
vi /etc/nginx/nginx.conf

Replace the existing contents with the template that follows, which is adapted from https://github.com/chika0801/Xray-examples/blob/main/VLESS-XTLS-Vision/nginx.conf.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
user www-data;
worker_processes auto;
pid /var/run/nginx.pid;

error_log /var/log/nginx/error.log notice;

events {
worker_connections 1024;
}

http {
log_format main '[$time_local] $proxy_protocol_addr "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main;

map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}

map $proxy_protocol_addr $proxy_forwarded_elem {
~^[0-9.]+$ "for=$proxy_protocol_addr";
~^[0-9A-Fa-f:.]+$ "for=\"[$proxy_protocol_addr]\"";
default "for=unknown";
}

map $http_forwarded $proxy_add_forwarded {
"~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
default "$proxy_forwarded_elem";
}

# When ACME uses standalone mode to request or renew a certificate,
# it will listen on port 80. If port 80 is occupied, ACME will fail.
# Therefore comment out the block that makes Nginx listen on port 80.
#server {
#listen 80;
#return 301 https://$host$request_uri;
#}

server {
listen 127.0.0.1:8001 proxy_protocol;
listen 127.0.0.1:8002 http2 proxy_protocol;
set_real_ip_from 127.0.0.1;

location / {
sub_filter $proxy_host $host;
sub_filter_once off;

proxy_pass https://www.lovelive-anime.jp;
proxy_set_header Host $proxy_host;

proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;

proxy_ssl_server_name on;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

resolver 1.1.1.1;
}
}
}

Save the web server configuration file.

Test the configuration file:

1
nginx -t

Restart Nginx with the new configuration:

1
systemctl restart nginx

Review the status to make sure Nginx is active (running):

1
systemctl status nginx

If necessary, quit the status display by entering q for quit.

Install Xray on server

Install Xray version 1.8.0 on your server to run as root. If a more advanced release is available by the time you read this, you can omit --version 1.8.0 and just install the newest release.

1
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -u root --version 1.8.0

Generate UUID

On the Linux server, generate a universally unique id:

1
xray uuid

Example of output:

1
1e63753f-8f98-44e0-8d10-4bcbaa92f060

Plug this UUID into your Xray server and client configuration files.

Configure Xray on server

Edit the Xray server configuration file:

1
vi /usr/local/etc/xray/config.json

Model your configuration on the template below, which is adapted from https://github.com/chika0801/Xray-examples/blob/main/VLESS-XTLS-Vision/config_server.json. Notice that Chinese IP addresses are blocked. This impedes identification of the server as a proxy by the GFW.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
{
"log":{
"loglevel":"warning",
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"geoip:cn"
],
"outboundTag": "block"
}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "1e63753f-8f98-44e0-8d10-4bcbaa92f060",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none",
"fallbacks": [
{
"dest": "8001",
"xver": 1
},
{
"alpn": "h2",
"dest": "8002",
"xver": 1
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"rejectUnknownSni": true,
"minVersion": "1.2",
"certificates": [
{
"ocspStapling": 3600,
"certificateFile": "/etc/ssl/private/fullchain.cer",
"keyFile": "/etc/ssl/private/private.key"
}
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"policy": {
"levels": {
"0": {
"handshake": 2,
"connIdle": 120
}
}
}
}

Run Xray on server

After saving your server configuration file, /usr/local/etc/xray/config.json, restart the Xray service with the command:

1
systemctl restart xray

Review the status to make sure Xray is active (running):

1
systemctl status xray

If necessary, quit the status display by entering q for quit.

Install and configure WireGuard on server

Download the angristan WireGuard install script:

1
curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh

Make the script executable:

1
chmod +x wireguard-install.sh

Run the script:

1
./wireguard-install.sh

Answer the questions as shown below. Note that you must manually input the WireGuard port (51820) and possibly also the server’s public IP address:

1
2
3
4
5
6
7
8
9
10
IPv4 or IPv6 public address: <SERVER-IP-ADDRESS>
Public interface: <PUBLIC-INTERFACE>
WireGuard interface name: wg0
Server WireGuard IPv4: 10.66.66.1
Server WireGuard IPv6: fd42:42:42::1
Server WireGuard port [1-65535]: 51820
First DNS resolver to use for the clients: 1.1.1.1
Second DNS resolver to use for the clients (optional): 1.0.0.1
WireGuard uses a parameter called AllowedIPs to determine what is routed over the VPN.
Allowed IPs list for generated clients (leave default to route everything): 0.0.0.0/0,::/0

Generate WireGuard client configuration

After the server install has completed, the angristan script automatically generates a configuration file for the first client:

1
2
3
4
The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.
Client name: home
Client WireGuard IPv4: 10.66.66.2
Client WireGuard IPv6: fd42:42:42::2

At the end of its run, the script displays a message:

1
Your client config file is in /root/wg0-client-home.conf

Here is an example of the client configuration file:

1
2
3
4
5
6
7
8
9
PrivateKey = 6FcyqKcFWPVUFW/mnbGgxx2JeTBlpJZSPFkDMvK7lEM=
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = 8IclXDQJGqyHeex9pX7kDvheicDRiX1uqaMNx/C0FEw=
PresharedKey = HzVc6rLuVb/6aWfkT2Hp3HHJWBz9nQmYXL2ufyBOlDQ=
Endpoint = <SERVER-IP-ADDRESS>:51820
AllowedIPs = 0.0.0.0/0,::/0

You will download this configuration file from the server to the client in a moment.

Although probably not essential, it is recommended at this stage that you reboot your server:

1
reboot

Check camouflage site

At this point, you can check your camouflage. Open an ordinary browser on your PC and attempt to visit your server:

1
https://charlie.cscot.buzz

The camouflage website should be displayed.

If there is a problem, try SSH-ing back into the server and restarting Nginx:

1
systemctl restart nginx

Check the status:

1
systemctl status nginx

Client

Now switch to working on your PC.

Download Xray command-line client

Open a browser, and visit https://github.com/XTLS/Xray-core/releases. From release 1.8.0 or greater, download Xray-linux-64.zip.

Unzip the .zip file.

1
unzip ~/Downloads/Xray-linux-64.zip -d ~/Downloads/Xray-linux-64

This creates a folder ~/Downloads/Xray-linux-64 with the Xray application inside it.

Configure Xray client

Inside the folder ~/Downloads/Xray-linux-64, create a client configuration file config.json.

1
vi ~/Downloads/Xray-linux-64/config.json

Model your configuration on the one that follows. It simply routes WireGuard input straight to the proxy server. At a minimum, make these changes to the template:

  • Replace <SERVER-IP-ADDRESS> by your actual server IP address.
  • Replace charlie.cscot.buzz by the name on your SSL certificate (i.e. your server hostname)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
"log": {
"loglevel": "warning"
},
"routing":{
"rules": [
{
"type": "field",
"inboundTag": [
"wireguard"
],
"outboundTag": "proxy"
}
]
},
"inbounds": [
{
"tag": "wireguard",
"port": 51820,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1",
"port": 51820,
"network": "udp"
}
}
],
"outbounds": [
{
"tag":"proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "<SERVER-IP-ADDRESS>",
"port": 443,
"users": [
{
"id": "1e63753f-8f98-44e0-8d10-4bcbaa92f060",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "charlie.cscot.buzz",
"allowInsecure": false,
"fingerprint": "chrome"
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}

Save the file ~/Downloads/Xray-linux-64/config.json.

Install WireGuard client

Get your client PC up to date:

1
sudo apt update && sudo apt upgrade

Install WireGuard:

1
sudo apt install resolvconf wireguard

Download WireGuard client configuration

Securely download the WireGuard client configuration from your server by issuing the command:

1
sudo scp root@<SERVER-IP-ADDRESS>:/root/wg0-client-home.conf /etc/wireguard/wg0.conf

Edit the downloaded copy of the configuration file wg0.conf:

1
sudo vi /etc/wireguard/wg0.conf

Change the Endpoint to be localhost port 51820, i.e. 127.0.0.1:51820, which is where Xray will be listening.

Here is an example of the wg0.conf configuration file at this stage:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = 6FcyqKcFWPVUFW/mnbGgxx2JeTBlpJZSPFkDMvK7lEM=
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = 8IclXDQJGqyHeex9pX7kDvheicDRiX1uqaMNx/C0FEw=
PresharedKey = HzVc6rLuVb/6aWfkT2Hp3HHJWBz9nQmYXL2ufyBOlDQ=
Endpoint = 127.0.0.1:51820
AllowedIPs = 0.0.0.0/0,::/0

Calculate AllowedIPs

The idea is that WireGuard should handle traffic for all IP addresses except the IP address of the Xray server. Traffic for the Xray server must be sent directly, otherwise you will get a routing loop.

Open a browser. Visit https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator.

  1. Set Allowed IPs to 0.0.0.0/0,::/0.
  2. Set Disallowed IPs to <SERVER-IP-ADDRESS>.
  3. Press Calculate.
  4. Copy the resulting AllowedIPs = line into your downloaded copy of the wg0.conf configuration file, replacing the original line.
  5. Save the amended wg0.conf file.

Connect both tunnels

Change into the Xray directory:

1
cd ~/Downloads/Xray-linux-64

Run the Xray connection:

1
./xray run -c config.json

Once the Xray tunnel is up, open a new terminal window.

In the second terminal, bring up your WireGuard tunnel:

1
sudo wg-quick up wg0

Disconnect

Once you’ve finished browsing the web, bring down the WireGuard interface:

1
sudo wg-quick down wg0

Press Ctrl+c to stop Xray.

The scenario in this post is that you are browsing the web from a Windows PC at a location called HOME. You want your web traffic to emerge from a server we’ll call Hop2. However, to get to Hop2, you want your traffic to pass through a relay server we’ll call Hop1.

WireGuard Double-Hop

Hop1

Start by working on the server in the middle, which will act as a relay.

SSH from your HOME PC into Hop1. Replace XX.XX.XX.XX by the IP address of Hop1:

1
ssh root@XX.XX.XX.XX

Get the server Hop1 up to date:

1
apt update && apt upgrade

Download the angristan WireGuard install script from https://github.com/angristan/wireguard-install:

1
curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh

Make the script executable:

1
chmod +x wireguard-install.sh

Run the script:

1
./wireguard-install.sh

Answer the questions like this. Note that you must manually select the WireGuard port and possibly also the public IP address:

1
2
3
4
5
6
7
8
9
10
IPv4 or IPv6 public address: XX.XX.XX.XX
Public interface: xxxx
WireGuard interface name: wg0
Server WireGuard IPv4: 10.66.66.1
Server WireGuard IPv6: fd42:42:42::1
Server WireGuard port [1-65535]: 51820
First DNS resolver to use for the clients: 1.1.1.1
Second DNS resolver to use for the clients (optional): 1.0.0.1
WireGuard uses a parameter called AllowedIPs to determine what is routed over the VPN.
Allowed IPs list for generated clients (leave default to route everything): 0.0.0.0/0,::/0

After the server install has completed, the script automatically continues by generating a configuration file for the first client:

1
2
3
4
The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.
Client name: home
Client WireGuard IPv4: 10.66.66.2
Client WireGuard IPv6: fd42:42:42::2

At the end of the script, it displays a message to say:

1
Your client config file is in /root/wg0-client-home.conf

Here is an example of the client configuration file contents:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = QEiKaWkKycxpxtv2M9Y382eReSFDSwAp7Wv+MjC3fmM=
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = GmghM04lpXYVs1lxlQCrVSUWpoqqJNUYRUGSZeavFWc=
PresharedKey = Fr9S9lA9Vk9teoHTdxAyeWDVdDx+eMFSzsaQUBHoVqE=
Endpoint = XX.XX.XX.XX:51820
AllowedIPs = 0.0.0.0/0,::/0

Now run the script a second time to generate a WireGuard client configuration for Hop2:

1
./wireguard-install.sh

This time, answer the questions like this:

1
2
3
4
5
6
7
8
9
10
11
What do you want to do?
1) Add a new user
2) List all users
3) Revoke existing user
4) Uninstall WireGuard
5) Exit
Select an option [1-5]:1
The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.
Client name: hop2
Client WireGuard IPv4: 10.66.66.3
Client WireGuard IPv6: fd42:42:42::3

At the end of the second run of the script, a message appears to say:

1
Your client config file is in /root/wg0-client-hop2.conf

Here is an example of the contents of the second client configuration file:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = uC0bG25CbZ/HJkoJdjbR+HhOEALKt7FRejKNXnzFLmo=
Address = 10.66.66.3/32,fd42:42:42::3/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = GmghM04lpXYVs1lxlQCrVSUWpoqqJNUYRUGSZeavFWc=
PresharedKey = wSTBfM0xXzpCgi322+Kv9T/HogVtlaUp1tbMYWAtfZI=
Endpoint = XX.XX.XX.XX:51820
AllowedIPs = 0.0.0.0/0,::/0

Your work on Hop1 is done for now, so exit your SSH session:

1
exit

Hop2

SSH from your HOME PC into Hop2. Replace YY.YY.YY.YY by the IP address of Hop2:

1
ssh root@YY.YY.YY.YY

Get the server Hop2 up to date:

1
apt update && apt upgrade

Install WireGuard on Hop2:

1
apt install resolvconf wireguard

Configure WireGuard by editing the wg0 configuration file:

1
vi /etc/wireguard/wg0.conf

Insert the Hop2 client configuration file that was generated by the script. Make these changes to the generated file:

  • Replace the AllowedIPs line so that only traffic for 10.66.66.0/24 goes through the WireGuard tunnel.
  • Add a PersistentKeepalive line so that the “client” (Hop2) always stays connected to the “server” (Hop1).
1
2
3
4
5
6
7
8
9
10
11
[Interface]
PrivateKey = uC0bG25CbZ/HJkoJdjbR+HhOEALKt7FRejKNXnzFLmo=
Address = 10.66.66.3/32,fd42:42:42::3/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = GmghM04lpXYVs1lxlQCrVSUWpoqqJNUYRUGSZeavFWc=
PresharedKey = wSTBfM0xXzpCgi322+Kv9T/HogVtlaUp1tbMYWAtfZI=
Endpoint = XX.XX.XX.XX:51820
AllowedIPs = 10.66.66.0/24
PersistentKeepalive = 25

Save the file.

Bring up the WireGuard interface wg0:

1
wg-quick up wg0

Show the current WireGuard configuration and runtime information of the interface:

1
wg show

Ping the server Hop1:

1
ping 10.66.66.1

Do Ctrl+c to stop the ping command.

Assuming you are using iptables and iptables-persistent for your firewall, open the iptables firewall for Squid:

1
2
iptables -I INPUT -p tcp -s 10.66.66.0/24 --dport 3128 -j ACCEPT
dpkg-reconfigure iptables-persistent

Install Squid proxy server:

1
apt install squid

Edit the Squid configuration file:

1
vi /etc/squid/squid.conf

Find the existing localnet Access Control Lists. Insert a localnet ACL line for traffic from your WireGuard network:

1
acl localnet src 10.66.66.0/24          # WireGuard network

Uncomment the line:

1
http_access allow localnet

Save the Squid configuration file.

Restart Squid (this can take up to a minute):

1
systemctl restart squid

Check that Squid is active (running):

1
systemctl status squid

Your work on Hop2 is done for now, so exit your SSH session:

1
exit

HOME

Install Firefox browser from https://www.mozilla.org.

Download and run the WireGuard for Windows installer from https://www.wireguard.com/install.

Securely download the home WireGuard client configuration from Hop1 by opening Windows PowerShell and issuing the command:

1
scp root@XX.XX.XX.XX:/root/wg0-client-home.conf Downloads/wg0-client-home.conf

Here is an example of the wg0-client-home.conf configuration file:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = QEiKaWkKycxpxtv2M9Y382eReSFDSwAp7Wv+MjC3fmM=
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = GmghM04lpXYVs1lxlQCrVSUWpoqqJNUYRUGSZeavFWc=
PresharedKey = Fr9S9lA9Vk9teoHTdxAyeWDVdDx+eMFSzsaQUBHoVqE=
Endpoint = XX.XX.XX.XX:51820
AllowedIPs = 0.0.0.0/0,::/0

In the WireGuard for Windows GUI, click Import tunnel(s) from file.

Select the configuration file Downloads/wg0-client-home.conf.

Click the Activate button.

You should see a successful connection be made and the tunnel becomes Active.

At this point you can ping both relay server Hop1:

1
ping 10.66.66.1

And the far client Hop2:

1
ping 10.66.66.3

Now open Firefox.

  1. From the hamburger menu select Settings > General > Network Settings.
  2. Click the Settings button.
  3. Select Manual proxy configuration.
  4. Specify the HTTP Proxy as 10.66.66.3 port 3128.
  5. Check the box to Also use this proxy for HTTPS.
  6. Click OK.

CNN reports that @programthink has been sent to prison for 7 years. Having exposed corruption, he had made himself into a high-value target. Possibly he was caught by some kind of correlation attack. He used to reply to comments on his blog in real time.

Wang Sir's News Talk | How did Program Think Subvert State Power?

Yes! You can host a Tor onion service (previously called a “hidden service”) on a Windows PC. Here’s how to create a blog without having to pay for hosting or a domain name.

Tor onion service hosted on a Windows PC

Install Hugo on your PC

In this tutorial, you’ll build your blog using the Hugo static site generator.

Visit the Hugo releases page, https://github.com/gohugoio/hugo/releases.

In the section for the most recent release, scroll down until you reach the Assets subsection.

Download the archive for your chosen version, operating system, and processor. You want the “extended” version of Hugo, since it includes support for SCSS (a language that provides extra features for CSS). As an example, if the most recent release is 0.111.3, and if your PC runs Windows on a 64-bit processor, you would download:

1
hugo_extended_0.111.3_windows-amd64.zip

Extract the .zip file.

Make hugo executable like this:

  1. Create a new directory named C:\hugo.
  2. Copy the application Downloads\hugo_extended_0.111.3_windows-amd64\hugo.exe into the directory C:\hugo.
  3. In the Windows search box, type env, and select Edit the system environment variables.
  4. Click the button Environment Variables.
  5. Select Path, and click Edit.
  6. Click New, type C:\hugo, and click OK.
  7. Click OK.
  8. Click OK.

Now in the Windows search box, type cmd, and select the Command Prompt app.

Enter the command:

1
echo %PATH%

Make sure C:\hugo is listed as part of your execution path.

If all is okay, then enter the command:

1
hugo version

Make sure you see a version number referring to your installed version, e.g. hugo v0.111.3, etc.

Close the Command Prompt app.

Install Git on your PC

Git will be useful for installing Hugo themes and also if you ever want to back up your website content to a GitHub repository.

The official build is available for download on the Git website. Open a browser, and visit https://git-scm.com/download/win.

Download 64-bit Git for Windows Setup. The installer has a name such as Git-2.40.0-64-bit.exe.

Run the installer. Accept the defaults all the way through the installation.

When the installation is complete, go to the Windows search box, type cmd, and select the Command Prompt app.

Enter the command:

1
git --version

You should see a result such as:

1
git version 2.40.0.windows.1

Start a Hugo site

In the Command Prompt app, start a new Hugo site named myonionblog (or another name of your choosing) by issuing the command:

1
hugo new site myonionblog

Change into the directory for your onion blog:

1
cd myonionblog

Initialize it as a Git repository:

1
git init

Leave the Command Prompt app open, positioned in the myonionblog folder.

Add a Hugo theme to your site

Tor Browser users often disable JavaScript. Therefore for an onion site, you are recommended to use a Hugo theme that renders without JavaScript. Some possible choices are hugo-xmin (556 stars), hugo-notepadium (327 stars), smol (171 stars), no-js-hugo-theme (18 stars), or hugo-theme-sk1 (18 stars).

We will use no-js-hugo-theme. Add it to your Hugo site by entering this command:

1
git submodule add https://github.com/stevenengler/no-js-hugo-theme themes/no-js-hugo-theme

Now use Windows Explorer to copy the entire contents of C:\Users\<YOUR-USER-NAME>\myonionblog\themes\no-js-hugo-theme\exampleSite up to myonionblog, replacing any existing contents that have the same name.

Test the site locally

In your Command Prompt app, still positioned in the myonionblog folder, issue the command:

1
hugo server

Open a browser, and navigate to localhost port 1313:

1
http://localhost:1313

You should see the example site.

Close the browser.

Select the Command Prompt window, and press Ctrl+c on your computer keyboard to stop the Hugo server.

Execute Hugo with no arguments to generate the standalone public HTML:

1
hugo

This regenerates the contents of myonionblog\public.

Install a web server

So far, we’ve used the server that comes with Hugo. Now we’ll install the full-function Apache web server.

Open a browser, and visit https://www.apachefriends.org. Download XAMPP for Windows. At the time of writing it is version 8.2.0, which includes Apache 2.4.54. The installer has a name that looks like xampp-windows-x64-8.2.0-0-VS16-installer.exe.

XAMPP recommends that you disable User Account Control before running the installer. In your Command Prompt window, type:

1
msconfig

On the tab for Tools, select Change UAC Settings and click Launch.

Slide the slider all the way down to the lowest level, Never notify. Click OK. Click OK.

Now you can run the XAMPP installer, xampp-windows-x64-8.2.0-0-VS16-installer.exe.

On the Select Components screen, the only one that needs to remain checked is Apache.

Leave the installation folder at C:\xampp.

Configure Apache

On the XAMPP Control Panel, click the Config button for Apache.

In httpd.conf, change the document root to be your Hugo public HTML folder:

1
2
DocumentRoot "`C:/Users/<YOUR-USER-NAME>/myonionblog/public"
<Directory "`C:/Users/<YOUR-USER-NAME>/myonionblog/public">

Save httpd.conf, and close Notepad.

On the XAMPP Control Panel, click the Start button to start Apache.

Note that this adds Windows inbound firewall rules for the XAMPP program. If your PC is behind a home router, it will typically not be open for traffic from the outside world due to the router’s own firewall.

Test the site under XAMPP by opening a browser on your PC and visiting the site on localhost port 80 (which is the default anyway):

1
http://localhost:80

Close your browser.

Install Tor

Open a browser, and visit https://7-zip.org.

Download the installer for the 64-bit x64 version of 7-Zip for Windows. Run the installer. You’ll need 7-Zip in a moment to extract the Tor .tar.gz archive.

Create a new directory C:\tor.

In your browser, visit https://www.torproject.org/download/tor.

Download the Tor Expert Bundle for Windows (x86_64), placing the download in C:\tor. It will have a name such as tor-expert-bundle-12.0.4-windows-x86_64.tar.gz.

Right-click on tor-expert-bundle-12.0.4-windows-x86_64.tar.gz, and use 7-Zip to extract the archive.

Right-click on the inner archive tor-expert-bundle-12.0.4-windows-x86_64.tar, and again use 7-Zip to extract the archive.

Your folder C:\tor will now contain two additional directories: data and tor.

Run Tor

Open a Command Prompt window with the option Run as administrator.

Issue the command:

1
C:\tor\tor\tor.exe --service install

Configure Tor

Open Notepad with the option Run as administrator.

Create content like this:

1
2
3
Log notice file C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\tor\notice.log
HiddenServiceDir C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\tor\myonionblog
HiddenServicePort 80 127.0.0.1:80

Save the file as C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\tor\torrc (with no extension). You’ll need to have the option checked to view hidden items to see AppData folders. If Notepad saves your torrc file with .txt on the end, rename it so there is no .txt on the end of its name.

In the Windows search box type services, and open the Services app with the option Run as administrator.

Select the service Tor Win32 Service.

Stop and then Start the service.

Find your onion URL

Your folder C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\tor now contains a folder myonionblog.

Inside this new folder is a file called hostname.

Open the file hostname with Notepad. It will look like this:

1
gzbf3m6y4yxq5pbajk43bxasu4blyos6lfuukdiuigpvgtkxblryokqd.onion

Close Notepad.

End-to-end test

Wait a few hours for the new onion URL to propagate.

Now go to a different PC. Open a browser and visit https://www.torproject.org/download. Install Tor Browser for Windows.

After the .onion URL has had time to propagate, visit your URL in Tor Browser on your second PC:

1
http://gzbf3m6y4yxq5pbajk43bxasu4blyos6lfuukdiuigpvgtkxblryokqd.onion

Promote your blog

At a minimum, submit your .onion URL to the onion search engine https://ahmia.fi.

Mainly you need to publicize your .onion URL to your friends and on your social media accounts.

Before you read this post, familiarize yourself with the basics of running a proxy server on a home PC. These basics are explained in Helping friends in foreign countries. Most of that post applies to all home proxy servers, even if the clients are in the same country as you.

You can then proceed to install Shadowsocks as a server on your PC.

We use Windows as a sample client in the last part of this tutorial.

Decisions

Decide whether your clients will access your PC by IP address or by DNS name.

In the examples in this post, we have used the DNS name alice.cscot.buzz.

Decide on the protocol(s) your server will support. Shadowsocks can support both TCP and UDP.

We will support both TCP and UDP in our examples.

Decide which port number clients will use to connect to your Shadowsocks server as follows. Open Windows PowerShell and issue the command:

1
Get-Random –Minimum 10000 -Maximum 42767

We will use port 14816 as our example.

Decide on a strong password as follows. Copy and paste into PowerShell the following script, which is taken from the blog https://www.sharepointdiary.com/2020/04/powershell-generate-random-password.html:

1
2
3
4
5
6
7
8
9
10
11
12
Function Get-RandomPassword
{
param([int]$PasswordLength = 10)
$CharacterSet = @{
Uppercase = (97..122) | Get-Random -Count 10 | % {[char]$_}
Lowercase = (65..90) | Get-Random -Count 10 | % {[char]$_}
Numeric = (48..57) | Get-Random -Count 10 | % {[char]$_}
SpecialChar = (33..47)+(58..64)+(91..96)+(123..126) | Get-Random -Count 10 | % {[char]$_}
}
$StringSet = $CharacterSet.Uppercase + $CharacterSet.Lowercase + $CharacterSet.Numeric + $CharacterSet.SpecialChar
-join(Get-Random -Count $PasswordLength -InputObject $StringSet)
}

Now call the function to generate a random password of 32 characters:

1
Get-RandomPassword -PasswordLength 32

If you get a result with a double-quote in it (ASCII code 34), then try again, as double-quote would mean end-of-field when it appears in the JSON configuration file.

Our example will be:

1
@oyTFb7e:C$8Ui6IL2!z1]`Qqg53J40<

Close Windows PowerShell.

Open your PC’s firewall

We are using tcp/14816 and udp/14816 for client input.

You should have already opened these protocols and ports on your router and forwarded them to your PC, as explained in the article on the basics.

Now open these port for input in your Windows PC firewall like this:

  1. In the Windows search box, type firewall.
  2. Select Windows Defender Firewall with Advanced Security.
  3. In the left pane, select Inbound Rules.
  4. In the right pane, select New Rule.
  5. Type is Port. Click Next.
  6. Type is TCP, and specific local port as 14816. Click Next.
  7. Action is Allow. Click Next.
  8. Leave all domains checked. Click Next.
  9. Set the Name to Shadowsocks Inbound TCP.
  10. Click Finish.

Repeat the above process to open for udp/14816, and name the new rule Shadowsocks Inbound UDP.

When you are done, close Windows Defender Firewall with Advanced Security.

Windows firewall configured for Shadowsocks server

Download the Rust version of Shadowsocks for Windows

Open a browser and visit https://github.com/shadowsocks/shadowsocks-rust/releases.

Download the latest release of the Rust version of Shadowsocks, compiled for Windows with the Microsoft Visual Studio compiler. Example:

1
shadowsocks-v1.15.3.x86_64-pc-windows-msvc.zip

Unzip the .zip file. This gives you a folder named Downloads\shadowsocks-v1.15.3.x86_64-pc-windows-msvc with the Shadowsocks executables in it.

Create configuration file for Shadowsocks server

Use Windows Notepad to create the server configuration file config.json. Below is the recommended configuration for a Shadowsocks server, adapted from the blog post at https://gfw.report/blog/ss_tutorial/en/:

1
2
3
4
5
6
7
8
{
"server":"0.0.0.0",
"server_port":14816,
"method":"chacha20-ietf-poly1305",
"password":"@oyTFb7e:C$8Ui6IL2!z1]`Qqg53J40<",
"mode":"tcp_and_udp",
"fast_open":false
}

Save this file with the name config.json (with no .txt at the end of its name) in the same folder as the Shadowsocks executables. In our example, that folder is Downloads\shadowsocks-v1.15.3.x86_64-pc-windows-msvc.

Shadowsocks executables and configuration file on Windows

Run Shadowsocks as a server

Open a Command Prompt window.

Navigate to your Shadowsocks folder:

1
cd Downloads\shadowsocks-v1.15.3.x86_64-pc-windows-msvc

Run Shadowsocks server:

1
ssserver.exe

Optionally add Shadowsocks as a startup program

Right-click on ssserver.exe and create a Shortcut to it, ssserver - Shortcut.

Open a Run command box by pressing Win+r.

Type shell:startup and press the Enter key to open the Startup folder.

Drag ssserver - Shortcut into the Startup folder.

Restart your computer to check that it works.

Install Shadowsocks for Windows on client

On the client PC, open a browser and visit https://github.com/shadowsocks/shadowsocks-windows/releases.

Download the most recent .zip file, e.g. Shadowsocks-4.4.1.0.zip.

Unzip the .zip file.

Configure Shadowsocks for Windows on client

Launch Shadowsocks.exe.

Add your server. Continuing with our example, the field values would be:

Field Value
Server Addr alice.cscot.buzz
Server Port 14816
Password @oyTFb7e:C$8Ui6IL2!z1]Qqg53J40<`
Encryption chacha20-ietf-poly1305
Plugin Program Blank
Plugin Options Blank
Remarks Optional
Timeout (Sec) 5
Group Blank
Proxy Port 10808

Click Apply.

Click OK.

Right-click on the Shadowsocks icon in the system tray, and set the System Proxy to Global.

Shadowsocks C# client configuration on Windows

Before you read this post, familiarize yourself with the basics of running a VPN server on a home PC. These basics are explained in Helping friends in foreign countries. Most of that post applies to all home VPN servers, even if the clients are actually in the same country as you.

You can then proceed to install OpenVPN as a server on your PC.

We use Windows as a sample client at the end of this tutorial, but OpenVPN client software also exists for Linux, macOS, Android, and iOS.

Decisions

Decide whether your clients will access your PC by IP address or by DNS name.

In the examples in this post, we have used the DNS name alice.cscot.buzz.

Decide on a protocol and port for your clients to reach your PC. OpenVPN supports both TCP and UDP. TCP is more reliable, whereas UDP is faster. If clients are subject to censorship, you may have heard about the old trick of using TCP on port 443. This rarely works against modern firewalls.

We will use UDP on port 1194 in our examples.

Open your PC’s firewall

We are using udp/1194 for client input. You should have already opened that port on your router and forwarded it to your PC. Now open that port for input in the Windows firewall like this:

  1. In the Windows search box, type firewall.
  2. Select Windows Defender Firewall with Advanced Security.
  3. In the left pane, select Inbound Rules.
  4. In the right pane, select New Rule.
  5. Type is Port. Click Next.
  6. Type is UDP, and specific local port as 1194. Click Next.
  7. Action is Allow. Click Next.
  8. Leave all domains checked. Click Next.
  9. Set the Name to OpenVPN Inbound.
  10. Click Finish.

When you are done, close Windows Defender Firewall with Advanced Security.

Install OpenVPN

Open your browser, and go to the OpenVPN Community Downloads page at https://openvpn.net/community-downloads.

Download the Windows 64-bit MSI installer. Run the installer.

Don’t install immediately. Make sure you click the Customize button first.

  • Deselect the OpenVPN GUI, but make sure the OpenVPN Service remains selected
  • Select the EasyRSA 3 Certificate Management Scripts

Click Install now.

When the installation is complete, click Close.

Initialize public key infrastructure

The installer has placed the EasyRSA 3 Certificate Management Scripts in C:\Program Files\OpenVPN\easy-rsa.

In the Windows search box, type cmd. Right-click on the Command Prompt app, and select Run as administrator.

Enter the command:

1
cd C:\Program Files\OpenVPN\easy-rsa

Open an Easy-RSA shell:

1
EasyRSA-Start.bat

Initialize your public key infrastructure by entering the command:

1
./easyrsa init-pki

Your newly created public key infrastructure directory is C:\Program Files\OpenVPN\easy-rsa\pki. It has a variables file named vars inside it.

Optionally, launch Notepad with the Run as administrator option, and edit C:\Program Files\OpenVPN\easy-rsa\pki\vars to your liking. Save the file if you edited it.

Create Certification Authority

Create your CA. Inside the Easy-RSA shell enter the command:

1
./easyrsa build-ca nopass

You are promoted for a Common Name. If you just press Enter, the Common Name defaults to Easy-RSA CA.

Your new CA certificate file is created at C:/Program Files/OpenVPN/easy-rsa/pki/ca.crt.

Build server certificate and key

Build a server certificate and key. In our example, the server will be named alice.

1
./easyrsa build-server-full alice nopass

You are asked to type the word yes to confirm the details.

The certificate is created at C:/Program Files/OpenVPN/easy-rsa/pki/issued/alice.crt. The inline file, which we will not use in this tutorial, is created at C:/Program Files/OpenVPN/easy-rsa/pki/inline/alice.inline.

Build client certificate(s) and key(s)

For each client, build a client certificate and key. In our example, the first client will be named bob:

1
./easyrsa build-client-full bob nopass

You are asked to type the word yes to confirm the details.

The certificate is created at C:/Program Files/OpenVPN/easy-rsa/pki/issued/bob.crt. In this tutorial, we will use the automatically generated inline file to make it easier to construct a client .ovpn file. The inline file is created at C:/Program Files/OpenVPN/easy-rsa/pki/inline/bob.inline.

Build Diffie-Hellman parameters

The Diffie-Hellman parameters are used only by an OpenVPN server. They are not needed on the client(s).

1
./easyrsa gen-dh

After the generation process, the Diffie-Hellman parameters of size 2048 are created at C:/Program Files/OpenVPN/easy-rsa/pki/dh.pem.

Build TLS encryption key

Open a browser. Download the most recent Easy-TLS source code .zip file from https://github.com/TinCanTech/easy-tls/releases.

Unzip the .zip file.

Copy the file easytls into C:\Program Files\OpenVPN\easy-rsa. You need administrator permissions to do this.

Back inside the Easy-RSA shell in the Command Prompt window, initialize Easy-TLS:

1
./easytls init-tls

Build a TLS crypt v1 key:

1
./easytls build-tls-crypt

The TLS crypt v1 key is created at C:/Program Files/OpenVPN/easy-rsa/pki/easytls/tls-crypt.key.

Exit the Easy-RSA shell:

1
exit

Close the Command Prompt window for now.

Create server configuration file

Launch Notepad running as administrator.

Using the following as a model for your configuration. Of course, you must change values such as protocol (udp), port (1194), and server name (alice) to match your choices.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dev tun
proto udp
port 1194
ca "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\issued\\alice.crt"
key "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\private\\alice.key"
dh "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\dh.pem"
tls-crypt "C:\\Program Files\\OpenVPN\\easy-rsa\\pki\\easytls\\tls-crypt.key"
cipher AES-256-GCM
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 1.0.0.1"
push "block-outside-dns"
keepalive 10 60
persist-key
persist-tun
explicit-exit-notify 1
verb 3

When you are done editing, save the file as C:\Program Files\OpenVPN\config-auto\alice.ovpn. Make sure you use the directory name config-auto and that Notepad does not add .txt to the end of the file name.

Close Notepad.

Enable forwarding

Open Control Panel > Network and Internet > Network and Sharing Center > Change adapter settings.

You will see that the installation has created a new network adapter described as TAP-Windows Adapter V9. It will have a name such as OpenVPN TAP-Windows 6.

Now open a Command Prompt window running as administrator. Determine the interface number of OpenVPN TAP-Windows 6 (or whatever name applies in your case) as follows. Issue the command:

1
netsh int ipv4 show int

Note down the interface index number of OpenVPN TAP-Windows 6 (in our example). In our example, the interface index number was 11.

See if forwarding is enabled. For example, if your interface index is 11:

1
netsh int ipv4 show int 11 | findstr "Forwarding"

If forwarding is disabled, then enable forwarding by issuing the command:

1
netsh int ipv4 set int 11 Forwarding="enabled"

Double-check the results show Forwarding is enabled:

1
netsh int ipv4 show int 11 | findstr "Forwarding"

Close the Command Prompt window for now.

Close the Control Panel for now.

Enable routing

In the Windows search box, type regedit, right-click Registry Editor, and select Run as administrator. In the left pane, navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters.

Find IPEnableRouter of type REG_DWORD.

Set its value to 1.

Click OK.

Close Registry Editor.

Start services

In the Windows search box, type services, right-click the Services app, and select Run as administrator.

Find the row for Routing and Remote Access.

  1. Right-click on it, and select Properties.
  2. Set the Startup type to Automatic.
  3. Click Apply.
  4. Click Start.
  5. Click OK.

Locate the row for OpenVPN Interactive service.

  1. Right-click, and select Properties.
  2. Click Stop.
  3. Change its Startup type to Manual.
  4. Click Apply.
  5. Click OK.

Locate the row for OpenVPNService.

  1. Stop the service.
  2. Start the service.

Close the Services app.

Open Windows File Explorer. Navigate to C:\Program Files\OpenVPN\log. Check the log file alice.log for any error messages. It should show Initialization Sequence Completed.

Share Internet adapter

Go to Windows Control Panel > Network and Internet > Network and Sharing Center > Change adapter settings.

On your main Internet network adapter (i.e. Ethernet or wireless), right-click, and select Properties.

Select the Sharing tab.

Check the box for Allow other network users to connect through this computer’s internet connection.

Select OpenVPN TAP-Windows 6.

Click OK.

Disable and enable TAP-Windows Adapter V9

On the OpenVPN TAP-Windows 6 adapter (or whatever your TAP-Windows Adapter V9 is named), right-click, then disable and re-enable the adapter.

Close the Network Connections window.

Close the Control Panel windows.

Create client configuration

In Notepad, create a configuration file for the client. Model it on the following.

  • You will need to change the remote DNS name or IP address to match your situation.
  • Copy and paste in your inline certificates and keys from C:/Program Files/OpenVPN/easy-rsa/pki/inline/bob.inline.
  • Copy and paste in your TLS encryption key from C:/Program Files/OpenVPN/easy-rsa/pki/easytls/tls-crypt.key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
client
dev tun
proto udp
remote alice.cscot.buzz 1194
resolv-retry infinite
nobind
persist-key
persist-tun
<cert>
-----BEGIN CERTIFICATE-----
MIIDUTCCAjmgAwIBAgIQQWJuayzEoM7gSiKJfPDMRjANBgkqhkiG9w0BAQsFADAW
MRQwEgYDVQQDDAtFYXN5LVJTQSBDQTAeFw0yMzA0MDQwNjA3MzdaFw0yNTA3MDcw
NjA3MzdaMA4xDDAKBgNVBAMMA2JvYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBANB39CBsvSng26utFsoPa9i0F/p/w0kb8x4EW/PKyGTj3HdOPJcnI28t
vcqJenIct/D6x8wRGq54p12YKz46vzWDOcOqh/xTrRyI5I5YH3bMQWXNuzkCeit+
FayOakVlcyuUOUGovXxjYDX39JE5WEHqtmRPGuJahimEtx/gaBWGVemMEklTbusK
L0SjIV2uGxRJ41I699T+gMvTUqoycj7dtbIwDSpD75skx/Ne0zO6pHirIfTGX1BU
Qmxo50MfxjvWT2jOT03+GyLx/RMMtokgLLome8tJT4MkHD5KuuivNy/U+kqNK+kW
tcpukX046WpPfk1SpVQDFn84uTyfxwsCAwEAAaOBojCBnzAJBgNVHRMEAjAAMB0G
A1UdDgQWBBSzUQF7f+StkA/zYqoJL1sM6AMbTTBRBgNVHSMESjBIgBTUfoyTfPl2
W4Ey2t3n/WWRElwaC6EapBgwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0GCFDfDAWWK
dLwHywsgWLvff7IaGMYkMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAsGA1UdDwQEAwIH
gDANBgkqhkiG9w0BAQsFAAOCAQEAe5rUYU3zHNyy7O+SJBzNxWnTDpe2zBrPbdUW
6jUXbav86N6a74wVHtf9zaKh5j0Z8PTqEUERdFb4BrCswrfcgRmI87z6Ni6/RZEx
nVgwU3xk7kx2e3QB57fA8Zo9Hxn4e04RJRpS/KjzkdEBSfEDsS9P+yEVdvMkTpDt
ox1yruldMWZ0GoV9s4nPWbS7ta2GUtSLNe4orW51dozCXwdbRIb8vCIvhbKAdzzn
cA44NEJ2TVsK47QAzwXqn1cArl3i2Xyh0as2+heBNA759VUUk8rsAhG1t4wRUTb+
VBKAeJ5XE8KrWmaeTBcMVuYPOpeS6uzh6kHh2UGBHDduQC2gQw==
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQd/QgbL0p4Nur
rRbKD2vYtBf6f8NJG/MeBFvzyshk49x3TjyXJyNvLb3KiXpyHLfw+sfMERqueKdd
mCs+Or81gznDqof8U60ciOSOWB92zEFlzbs5AnorfhWsjmpFZXMrlDlBqL18Y2A1
9/SROVhB6rZkTxriWoYphLcf4GgVhlXpjBJJU27rCi9EoyFdrhsUSeNSOvfU/oDL
01KqMnI+3bWyMA0qQ++bJMfzXtMzuqR4qyH0xl9QVEJsaOdDH8Y71k9ozk9N/hsi
8f0TDLaJICy6JnvLSU+DJBw+Srrorzcv1PpKjSvpFrXKbpF9OOlqT35NUqVUAxZ/
OLk8n8cLAgMBAAECggEAWjrxMW+fWJb4vY/Hg2G1XjBlCIlwLx6n1eAxJI4qunBd
pk34r7vC/IYh1Z43n1iKzQTeoZbto4KZfks0vFSVGkZYJDaVcUOOdAFUW8AMrlCu
JbAsTvqhgl2qZ+ukV7EXbk9TkPXGPiaNKA7QjmLxrmY216fdjQd9dk75LBTnOBkK
0Yan/tu++JtvCjryO043Z36alLyA4IgNWUA7ul2p0pfgU3BRm/WWv239yg03dgFT
w1ImmFJn/PFiC49WcpLvOcJEw+sxAM8hV5RlADUhEZ9nCo4bbGlvhHOktR/PIPA1
khgnWdcbo0/WTDOf05yhFSwk0BoWH9XqWli2MyA1kQKBgQDvCPf2bmf0wnayeR2l
NfCgSoDXU3OqVvlSsD+u9fTh1kmJSXnfZfyAPJEAV9KTujUqEz/s9i+KOJkhPQH5
Ria6OpQfEL7jD813GVHsj+h16agmP3the97omsLtY2q6AD+iGJh2at/NdITVPRCP
lpWfJMSVIGZbEmf4Pvo9wPVlrwKBgQDfQ59XEBQptRuofx3pQ40Cc/Vk/JERDWGY
lvNifBx1h7MHwZCblDzemd02mGXqJHIYQPDiaZjnwxVMIpegvGV0prm1sa2DM8Yp
7KhhVXA7AK5CR0nQjdwwPGiuZ+StGJlBNfEJNR7oIqDqiIxzAfqprz/FDj+R16dD
k1XskP8nZQKBgHD0QwBvca5mimKR+yFL2PZV3oZiCAFRciXR5XYPAfYKJdu7Hd0k
O2p5tGd+GKL4VhEY4ZdfSl29mxbq1ljt/nT4I3B+oEV5/TSvgVgRNN8rV+sjCnGp
cE9oen5lAVT9sxQtHTawECvtSKvfXEkN9owqer6hfdzBWOIlGGlAGnY/AoGABqEh
aBpoHtzr11L+9mA1Ha+Hx9ngDNuS3E8PJwt8ZNkEreRHgPcj35A+C1L3I761TJcR
EAgGrEsUpNAaJIGzmYUh2o1OE6lD5xbJ4SoCTR42Dm3DeVfdA+mnShZ3qdQjKNaL
M7TKGCZ/FLe9Q+T5JnS3tgg4RwJaSx1i3cVobikCgYBiFeZgcR8t8v980DGw7xUp
kcdzSx7UqtKCq2qy4R2oiJSdjiWGOrMIAXa8YC+TnG/A+ooynlWoyiudCKI+lhxH
TrCjb32w2FU3S/VeZA+55WW4jtdiXJTB8mKXr8pxj6BcMVVttouj/gGXGU0pHHG1
lqvGY4Wua8tIhfLhZCD7RA==
-----END PRIVATE KEY-----
</key>
<ca>
-----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIUN8MBZYp0vAfLCyBYu99/shoYxiQwDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjMwNDA0MDYwNjI4WhcNMzMw
NDAxMDYwNjI4WjAWMRQwEgYDVQQDDAtFYXN5LVJTQSBDQTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAPpmTVIoJIWDH+U1sbuPaPkkYfKC0/QNnF8koS0z
lGzrYZlNHHB9KlZo9zx8J76q3JaY6Vi9JBd0JF0d3czEgy0uVUV+UqNIJ07AhTIM
9LtRIEb1aRXgfzaQbLTa1XmRko1MUJKDmRAgNP1TY5crjUS4PEK3xwY8ZneaAYxu
Qkg8b8sK05b50NCP+Emnf/uow1bT5wNhHMwU6xber/D8YgtXDWAhDOKsku+7ExAs
tI+IBRdSjMOqFOpnDWV98AZjO+0BV2vqd2JgylpZ5OvBKZdMHr8FX58KXVqoYlmF
Yx2bI0G9C/64VoLAvA+B9OvILBix0ZS3rsWz16iNljM4w0MCAwEAAaOBkDCBjTAM
BgNVHRMEBTADAQH/MB0GA1UdDgQWBBTUfoyTfPl2W4Ey2t3n/WWRElwaCzBRBgNV
HSMESjBIgBTUfoyTfPl2W4Ey2t3n/WWRElwaC6EapBgwFjEUMBIGA1UEAwwLRWFz
eS1SU0EgQ0GCFDfDAWWKdLwHywsgWLvff7IaGMYkMAsGA1UdDwQEAwIBBjANBgkq
hkiG9w0BAQsFAAOCAQEAbF1tpIL0632IpjZ42Gtgs1MPLMoeuGOGvcK32Xfld3pj
xXQCyiF6mVlnXYFLD0QLNLl3MPdMhHuZtGOHqYmdD8uEE01TaTki0mZ5ObnN5pOG
kIk/Q8E0VVjGoWKYGfUvMxxdXVpnZqDzm2oFGKhYh8JCUkMiAQB7pUw1IgflZ1kd
60bYYvryi2EeP8v8sM3yQIEtD/QO3gzHTPVtZIMZGpsJcHB3MjK4XS7dYYg2vjaN
7AJlaaqGUFeDpfq2l6tfFcul8Nr6j0dxxRK+N9TEDjhnNG1fuCzfUw7f2fo8eTpk
PhOWSdmt5alLf8zE37yovTFrw0gSuCFGs7MvSTPSmw==
-----END CERTIFICATE-----
</ca>
<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
48e3921f8013f667318938d3454a0e10
cb592af181e30da37643acbbfd36b54d
099441265e768047334242c08db4eb01
1a136cecd628452ba004a042b92362d5
3b69b766ebf9af7f264718b849e83030
b99bc255a627e788061b533d06678d99
b661b485c1df0d4a552c44f6e1c4ff82
34636917f48479eef95033071a763c5a
4738cc084737a4c58e08e62020a6dc84
bdf37ae4d8a2edf9310d60967320378d
4bf261151e7aaa3698a0cce1c9758fb1
a6a41a87da3a619b4e6ce4917c3af53e
2cbf0f4aef9c3c9eb5315e4cfa30508b
e153d051310bf1a96788255d4d408f9d
837c786570980178e98c4bcb15b7801e
cab6b007f31204b71e4ad0d611d9da21
-----END OpenVPN Static key V1-----
</tls-crypt>
remote-cert-tls server
cipher AES-256-GCM
verb 3

Save the file in your server’s Documents folder as bob.ovpn.

Securely copy client ovpn file to client PC

Securely copy bob.ovpn from the server’s Documents folder to the client’s Downloads folder.

You can use any secure tool to do the copy.

  • If both server and client are nearby, you can use a USB memory stick.
  • For a remote server, you can use the Remote Desktop Connection (RDC) app with local disk access enabled.
  • Or you can just copy and paste from Notepad on an RDC session with the server down to Notepad on your local client.

However you do the secure copy, you will end up with a file bob.ovpn in your client PC Downloads folder.

Set up Windows client

Switch to working on the client PC.

From the OpenVPN Downloads page at https://openvpn.net/community-downloads, download the 64-bit installer for Windows.

Run the installer. On the client, you need the OpenVPN GUI component, but you do not need the EasyRSA 3 Certificatre Management scripts. These are the defaults.

The installer places an OpenVPN GUI shortcut icon on your desktop.

Double-click the OpenVPN GUI shortcut icon on your desktop.

A message appears to say that there are as yet no readable connection profiles (i.e., configurations). Click OK.

Import bob.ovpn as follows:

  1. Right-click on the OpenVPN icon in the system tray.
  2. Select Import file.
  3. Select the bob.ovpn file from your Downloads folder.
  4. You should see a message indicating that the file was imported successfully.
  5. Click OK.

Right-click on the OpenVPN icon in the system tray, and select Connect. If problems occur, check C:\Users\<YOUR-USER-NAME>\OpenVPN\log\bob.log for any error messages.

On successful connect, a notification appears to say you are now connected.

The OpenVPN icon in the system tray turns green.

Foreign countries

You may want to help a friend in a foreign country by hosting a proxy server for them.

Hosting the proxy in your home has the advantage that your residential IP address is highly unlikely to be on a block list.

Here are the preconditions you must meet:

  1. Hosting a proxy server for your friend will not work if you have Carrier Grade NAT (CGNAT) at home. This is where an ISP allocates a single IP address to an entire building or block. It is common in some countries.
  2. You need to either have a relatively static IP address, or else subscribe to a dynamic DNS service.
  3. You need to have access to your home router, and enough knowledge to open port(s) and forward them to the computer you’ll be using to host your proxy server.
  4. If you’ve never done anything like this before, you’ll need to know how to use a search engine to find solutions to any problems you encounter.

If you meet all these preconditions, you need to determine which protocol(s) will work for your friend. Ten or fifteen years ago, it was easy to solve this problem with suggestions like “Use TCP on port 443” or “Use Shadowsocks.” Unfortunately censorship is rapidly evolving. Nowadays you need to get up-to-date information about recent conditions in your friend’s country. You can get this by reading forums like NTC, GitHub, or the various Telegram groups, e.g. projectXray or v2fly_chat.

Now for the choice of hardware platform:

  • A Raspberry Pi dedicated to hosting your proxy server gives you the most flexibility and the widest range of choices. You need to be comfortable enough with Linux and the command line to follow along with tutorials and videos.
  • You can alternatively host a proxy server on an ordinary Windows PC. You need to leave the PC on all the time, and adjust the PC’s power settings so the PC never goes to sleep.

Once you’ve decided on a protocol that will work, you can build your proxy server. Examples of appropriate software would be SoftEther, the Rust version of Shadowsocks, OpenVPN, V2Ray, or Xray. You can alternatively host a WireGuard server on a Raspberry Pi. WireGuard as a server is not officially supported on Windows.

This post shows you how to manually create an IKEv2 IPsec VPN server using the strongSwan package on an Ubuntu 22.04 server. It also outlines the process for setting up the corresponding client on a Windows PC, a Linux PC, and an Android device. Since IPsec is a standards-based protocol, client devices often support IPsec natively. You can reach your server without installing additional software on the client.

VPS and domain name

You will need a Linux server running Ubuntu 22.04 with 1 GB of RAM.

You also need to buy a domain name and create a DNS A record pointing from your server hostname (moon.cscot.buzz in our examples) to the your server IP address.

Prepare server

SSH into your server using a terminal emulator app or Windows PowerShell. In the SSH command below, replace moon.cscot.buzz by your actual server hostname:

1
ssh root@moon.cscot.buzz

Suppress lengthy login messages:

1
touch .hushlogin

Get the existing package metadata up to date, and upgrade all existing packages:

1
apt update && apt upgrade

You may be prompted to reboot and then SSH back in again.

Protect your server with iptables, replacing <HOME-IP-ADDRESS> by your actual home IP address. We need to open the firewall for UDP input on ports 500 and 4500, and also for protocols AH and ESP. We masquerade the source IP address on outbound packets to set it to the IP address of the server, not the original client.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s <HOME-IP-ADDRESS> -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
iptables -A INPUT -p ah -j ACCEPT
iptables -A INPUT -p esp -j ACCEPT
iptables -A INPUT -p udp --dport 500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT
iptables -P INPUT DROP

iptables -t nat -A POSTROUTING -s 10.0.8.0/24 -o eth0 -j MASQUERADE

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -P INPUT DROP

Check that you can still access the server with these rules before you make them permanent:

1
2
3
exit

ssh root@moon.cscot.buzz

Make the iptables rules permanent:

1
apt install iptables-persistent

Enable forwarding

Enable packet forwarding in the Linux kernel. Create a new configuration file in the /etc/sysctl.d directory, with a single line in it:

1
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/40-ipv4-forward.conf

Make this change effective immediately:

1
sysctl -p /etc/sysctl.d/40-ipv4-forward.conf

Install packages

Install strongSwan and its related packages by entering the command:

1
apt install strongswan libstrongswan strongswan-pki libstrongswan-standard-plugins libstrongswan-extra-plugins strongswan-swanctl strongswan-charon strongswan-starter strongswan-libcharon libcharon-extra-plugins libcharon-extauth-plugins charon-systemd libtss2-tcti-tabrmd0

Create Certificate Authority

Create a self-signed Certificate Authority (CA) key and certificate as follows.

Generate a private key for the CA:

1
pki --gen --outform pem > /etc/swanctl/private/strongswanKey.pem

Generate a self-signed CA certificate with a lifetime of 10 years (3652 days). Replace country CH, organization strongSwan, and common name strongSwan Root CA with your own choice of values.

1
pki --self --ca --lifetime 3652 --in /etc/swanctl/private/strongswanKey.pem --dn "C=CH, O=strongSwan, CN=strongSwan Root CA" --outform pem > /etc/swanctl/x509ca/strongswanCert.pem

Create server certificate

Generate a private key for the host moon.cscot.buzz:

1
pki --gen --outform pem > /etc/swanctl/private/moonKey.pem

Create a PKCS#10 certificate request that has to be signed by the CA:

1
pki --req --type priv --in /etc/swanctl/private/moonKey.pem --dn "C=CH, O=strongswan, CN=moon.cscot.buzz" --san moon.cscot.buzz --outform pem > /etc/swanctl/x509/moonReq.pem

Issue a signed server certificate based on the certificate request:

1
pki --issue --cacert /etc/swanctl/x509ca/strongswanCert.pem --cakey /etc/swanctl/private/strongswanKey.pem --type pkcs10 --in /etc/swanctl/x509/moonReq.pem --flag serverAuth --flag ikeIntermediate --lifetime 365 --outform pem > /etc/swanctl/x509/moonCert.pem

Create client certificate

Generate a private key for the client carol:

1
pki --gen --outform pem > /etc/swanctl/private/carolKey.pem

Create a PKCS#10 certificate request that has to be signed by the CA:

1
pki --req --type priv --in /etc/swanctl/private/carolKey.pem --dn "C=CH, O=strongswan, CN=carol.cscot.buzz" --san carol.cscot.buzz --outform pem > /etc/swanctl/x509/carolReq.pem

Issue a signed client certificate based on the certificate request:

1
pki --issue --cacert /etc/swanctl/x509ca/strongswanCert.pem --cakey /etc/swanctl/private/strongswanKey.pem --type pkcs10 --in /etc/swanctl/x509/carolReq.pem --flag clientAuth --lifetime 365 --outform pem > /etc/swanctl/x509/carolCert.pem

Create client PKCS#12 file

Many platforms prefer the private key, certificate, and CA certificate combined into a PKCS#12 container. Combine them with the openssl command:

1
openssl pkcs12 -export -inkey /etc/swanctl/private/carolKey.pem -in /etc/swanctl/x509/carolCert.pem -name "carol" -certfile /etc/swanctl/x509ca/strongswanCert.pem -caname "strongSwan Root CA" -out /etc/swanctl/pkcs12/carolCert.p12

When prompted, enter and confirm an export password. You will need to know this export password when you import the .p12 file to your client.

Android cannot import newer .p12 files. Therefore if you aim to support an Android client, convert your client .p12 file to “legacy” format:

1
openssl pkcs12 -nodes < /etc/swanctl/pkcs12/carolCert.p12 > /tmp/certbag.pem

Enter the original export password. Then:

1
openssl pkcs12 -export -legacy -in /tmp/certbag.pem > /etc/swanctl/pkcs12/carolCertLegacy.p12

Enter and confirm a new export password (which may be the same as the original one, if you wish).

Configure strongSwan server

Create a new file for IKEv2 connections with machine certificate authentication:

1
vi /etc/swanctl/swanctl.conf

Insert a configuration based on the template below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
connections {
ikev2-pubkey {
version = 2
proposals = aes192gcm16-aes128gcm16-prfsha256-ecp256-ecp521,aes192-sha256-modp3072,aes256-sha256-modp2048,aes128-sha256-modp2048,aes256-sha1-modp2048,aes128-sha1-modp2048
rekey_time = 0s
pools = primary-pool-ipv4
fragmentation = yes
dpd_delay = 30s
send_cert = always
local {
certs = moonCert.pem
id = moon.cscot.buzz
}
remote {
}
children {
ikev2-pubkey-child {
local_ts = 0.0.0.0/0
rekey_time = 0s
esp_proposals = aes192gcm16-aes128gcm16-prfsha256-ecp256-modp3072,aes192-sha256-ecp256-modp3072,aes256-sha256-modp2048,aes128-sha256-modp2048,aes256-sha1-modp2048,aes128-sha1-modp2048
}
}
}
}
pools {
primary-pool-ipv4 {
addrs = 10.0.8.0/24
dns = 8.8.8.8,8.8.4.4
}
}

Save the file /etc/swanctl/swanctl.conf.

Restart strongSwan

Restart strongSwan with your new configuration:

1
systemctl restart strongswan-swanctl

Check that strongSwan is active and running:

1
systemctl status strongswan-swanctl

Your server work is done for now, so exit from the SSH session with the server:

1
exit

Windows IKEv2 client

First, use the Registry Editor to enforce the use of MODP2048.

  1. Press the Win+r keys, type regedit, then press Enter.
  2. If asked if you want to allow the Registry Editor to make changes to your device, click Yes.
  3. In the tree in the left pane, navigate to HKEY_LOCAL_MACHINE > SYSTEM > CurrentControlSet > Services > RasMan > Parameters.
  4. Right-click on Parameters, and insert a new DWORD (32-bit value).
  5. Set the name to NegotiateDH2048_AES256.
  6. Set the value to 2, which means enforce the use of AES-256-CBC and MODP2048.

Windows Registry Editor entry for NegotiateDH2048_AES256

Close the Registry Editor.

Now securely copy the client .p12 file to your Windows workstation by opening PowerShell and running the scp command:

1
scp root@moon.cscot.buzz:/etc/swanctl/pkcs12/carolCert.p12 Downloads/carolCert.p12

Use the Microsoft Management Console to import the client certificate and key, and also the CA certificate, from the .p12 file:

  1. Press the Win+r keys, type mmc, and click OK.
  2. If asked if you want to allow the Microsoft Management Console to make changes to your device, click Yes.
  3. From the Microsoft Management Console menu, select File, Add/Remove Snap-in, then choose Certificates.
  4. Click Add.
  5. Select Computer Account then press Next.
  6. Select Local computer then press Finish.
  7. Click OK.
  8. Expand the tree item Certificates (Local Computer) and select Personal.
  9. From the menu, select Action > All Tasks > Import.
  10. Click Next.
  11. Browse to your downloaded .p12 file (Downloads/carolCert.p12 in our example) and click Next.
  12. You will need to enter the password for the .p12 file and click Next.
  13. Click Next.
  14. Click Finish.
  15. Click OK.
  16. The client certificate and the CA certificate appear under Personal > Certificates.
  17. Cut and paste the CA certificate from Personal to Trusted Root Certification Authorities.
  18. Close the Microsoft Management Console (there is no need to save the console settings).

Microsoft Management Console Personal Certificate

Add the new VPN connection using Settings > Network & Internet > VPN.

  1. Set the VPN provider to Windows (built-in).
  2. Set the connection name to (for example) moon.
  3. The server name or address in our example is moon.cscot.buzz.
  4. The VPN type is IKEv2.
  5. The type of sign-in info is Certificate.

Adding and IKEv2 VPN connection in Microsoft Windows

Now click Change adapter options.

  1. Right-click on the WAN Miniport for your IKEv2 connection moon.
  2. Select Properties.
  3. Select the Security tab.
  4. For Authentication, select the radio button for Use machine certificates.
  5. Click OK.
  6. Close the Network Connections window.

Microsoft Windows WAN miniport set to machine certificate authentication

Use PowerShell to set the IPsec configuration for the IKEv2 tunnel:

1
Set-VpnConnectionIPsecConfiguration -ConnectionName "Contoso" -AuthenticationTransformConstants None -CipherTransformConstants AES256 -EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -PfsGroup None -DHGroup Group14 -PassThru -Force

Close PowerShell.

Now connect your client to your server.

From Settings > Network & Internet > VPN, select your VPN moon.

Press Connect.

Linux IKEv2 client

Securely copy the client certificate and key files, and the CA certificate file, to your Linux workstation by opening your terminal emulator and running the scp commands:

1
2
3
scp root@moon.cscot.buzz:/etc/swanctl/x509/carolCert.pem ~/Downloads/carolCert.pem
scp root@moon.cscot.buzz:/etc/swanctl/private/carolKey.pem ~/Downloads/carolKey.pem
scp root@moon.cscot.buzz:/etc/swanctl/x509ca/strongswanCert.pem ~/Downloads/strongswanCert.pem

Install strongSwan for Network Manager:

1
sudo apt install network-manager-strongswan

In the GNOME Settings app, go to the Network page. In the VPN section, click the plus sign + to add a new VPN client configuration.

Select type IPsec/IKEv2 (strongswan).

Fill in the fields as illustrated.

  • Name is a name of your choice, e.g. moon
  • Server Address is your server’s DNS name, e.g. moon.cscot.buzz
  • Server Certificate is the CA certificate you downloaded
  • Server Identity can be left blank
  • Client Authentication is Certificate
  • Client Certificate is Certificate/private key
  • Client Certificate file is the one you downloaded
  • Client Private key is the one you downloaded
  • Client Identity can be left blank
  • Client Username can be left blank
  • Client Password can be left blank
  • Check the box for Request an inner IP address
  • Check the box for Enforce UDP encapsulation

Linux GNOME desktop Network Manager settings for IPsec IKEv2 client configuration

Click Add.

Connect the client to the server by toggling the VPN switch to the on position.

Android IKEv2 client

You need to securely copy the legacy-format .p12 file from the server to your client. You also need to copy the CA certificate, though this need not be transmitted securely.

The easiest way to do all this is to copy the files to a PC first, then copy them over a USB cable from your PC to your Android device. For an alternative method using a local web server, see the section below titled “Securely transfer a certificate from a PC to a mobile device.”

Securely copy the legacy-format client .p12 file from the server to your PC:

1
scp root@moon.cscot.buzz:/etc/swanctl/pkcs12/carolCertLegacy.p12 Downloads/carolCertLegacy.p12

Copy the CA certificate file from the server to your PC:

1
scp root@moon.cscot.buzz:/etc/swanctl/x509ca/strongswanCert.pem Downloads/strongswanCert.pem

Now connect your PC to your Android device with a USB cable. Copy the two downloaded files from your PC to your Android device’s Download directory.

Next install the client .p12 certificate and the CA certificate on your Android device. The exact menu path for doing this varies depending on which version of Android you are running. It will be something like Settings > Lock screen and security > Other security settings > Install from device storage.

Select strongswanCert.pem from the list. Enter your device PIN. Choose a certificate name such as strongSwan. Click OK.

Now repeat the process, but this time select carolCertLegacy.p12 from the list. Enter the export password. Choose a certificate name such as carol. Enter your device PIN. Click OK.

On recent versions of Android, you have a choice of clients:

  • the Android native IPSec IKEv2 RSA client
  • the strongSwan app from Google’s Play Store

We will describe here the process for configuring the Android native client.

Go to Settings > Connections > More connection settings > VPN.

Tap ADD VPN.

  • Give it a name, e.g. moon.
  • Type is IPSec IKEv2 RSA.
  • Server address is moon.cscot.buzz in our example.
  • IPSec user certificate is carol.
  • IPSec CA certificate was named strongSwan.
  • IPSec server certificate is received from the server.
  • Tap SAVE.

Tap the row for the VPN configuration. Click CONNECT.

Apple IKEv2 clients

Both macOS and iOS allow you to configure IKEv2 clients from their respective graphical user interfaces.

Additionally, if you have a macOS computer, you can create a .mobileconfig file for a VPN client using the Apple Configurator from the App Store.

Securely transfer a certificate from a PC to a mobile device

One way to securely copy a .p12 file from your PC to an Android, iOS, or iPadOS device is to build a small website on your PC that serves up the file to mobile devices.

If all communication takes place over your LAN, and if your LAN is behind a firewalled router, then all your transfers are secure.

To host a website on a Windows 10 computer, first enable Internet Information Services (IIS):

  1. Search for and launch the Control Panel app.
  2. Go to the Programs page.
  3. Click Turn Windows features on or off.
  4. Check the box for Internet Information Services.
  5. Click OK.
  6. Wait while Windows searches for the required files and applies the changes.
  7. When the install has completed, click Close.
  8. Close the Control Panel app.

Copy your certificate file, carolCertLegacy.p12 in our example, into the folder C:\inetpub\wwwroot. This needs administrator permissions.

In your Documents folder, create a simple HTML page named index.html.

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Certificates</title>
</head>
<body>
<h1>Certificates</h1>
<p><a href="carolCertLegacy.p12">carolCertLegacy.p12</a></p>
</body>
</html>

If you use Windows Notepad as your editor, make sure you save the HTML as index.html without .txt on the end.

Copy index.html into your C:\inetpub\wwwroot folder. This needs administrator permissions.

Determine your PC’s IP address on the LAN:

1
ipconfig

Now visit your PC’s LAN IP address from a browser on a mobile device which is connected to the same LAN.

The webpage index.html is displayed.

Click on the link to download the .p12 file and install the certificate on your mobile device.

gRPC is Google’s Remote Procedure Call framework. It is based around the idea of defining a service and specifying methods that can be called remotely. Services may handle either a one-time request or a streaming request. gRPC uses HTTP/2 for transport.

This post describes the procedure used to test gRPC HTTP/2 on Xray REALITY for a Linux server and a Windows client. The test server had 1 GB of RAM and ran Ubuntu 22.04. The test client ran Windows 10. Server and client configurations are based on https://github.com/chika0801/Xray-examples/tree/main/VLESS-gRPC-uTLS-REALITY.

Prepare server

SSH into your server using Windows PowerShell. In the command below, replace <SERVER-IP-ADDRESS> by your actual server IP address:

1
ssh root@<SERVER-IP-ADDRESS>

Suppress lengthy login messages:

1
touch .hushlogin

Get the existing package metadata up to date, and upgrade all existing packages:

1
apt update && apt upgrade

You may be prompted to reboot and then SSH back in again.

Protect your server with iptables, replacing <HOME-IP-ADDRESS> by your actual home IP address:

1
2
3
4
5
6
7
8
9
10
11
12
13
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s <HOME-IP-ADDRESS> -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -P INPUT DROP

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -P INPUT DROP

Check that you can still access the server with these rules before you make them permanent:

1
2
3
exit

ssh root@<SERVER-IP-ADDRESS>

Make the iptables rules permanent:

1
apt install iptables-persistent

Enable BBR congestion control algorithm

Copy and paste these three commands into your SSH session to enable the Bottleneck Bandwidth and Round-trip propagation time (BBR) congestion control algorithm:

1
2
3
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p

Install Xray on server

Install Xray version 1.8.0 to run as root:

1
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -u root --version 1.8.0

Generate parameters

On the Linux server, generate a universally unique id with xray uuid. Example of output:

1
b29ce075-dcb5-46ce-a0c5-189e3f633701

Plug the id into both the server and the client configuration files.

Generate a public-private key pair with xray x25519. Example of output:

1
2
Private key: uJTbBa9Wt4GfTWHkSBv4e9ph_rljUhGfTgV4Gx9JZWo
Public key: 8eH2aDUtsCkBJxnIqknHP-3qu-MMyjYFhNs4-MFHpBs

Plug the private key into the server configuration file, and the public key into the client configuration file.

Choose a shortId of up to 16 hexadecimal characters. Example:

1
b1

Plug this into the server and client configuration files.

Determine camouflage website

The minimum standard of the camouflage website is that it be a foreign website, support TLSv1.3 and HTTP/2, and have a URL that is not redirected elsewhere (though the apex domain name may be redirected to www).

Bonus points if it has a similar IP to your server, the handshake messages after the “Server Hello” are encrypted together (such as for dl.google.com), and the server implements Online Certificate Status Protocol (OCSP) stapling.

Plug your camouflage website into both the server and the client configuration files.

Our example: www.microsoft.com.

Xray configuration on the server

Edit /usr/local/etc/xray/config.json. The template used for testing was like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
"log": {
"loglevel": "warning"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"geoip:cn"
],
"outboundTag": "block"
}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "b29ce075-dcb5-46ce-a0c5-189e3f633701",
"flow": ""
}
],
"decryption": "none"
},
"streamSettings": {
"network": "grpc",
"security": "reality",
"realitySettings": {
"show": false,
"dest": "www.microsoft.com:443",
"xver": 0,
"serverNames": [
"www.microsoft.com"
],
"privateKey": "uJTbBa9Wt4GfTWHkSBv4e9ph_rljUhGfTgV4Gx9JZWo",
"shortIds": [
"a1"
]
},
"grpcSettings": {
"serviceName": "grpc"
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"policy": {
"levels": {
"0": {
"handshake": 2,
"connIdle": 120
}
}
}
}

Run Xray on the server

After saving your server configuration file in /usr/local/etc/xray/config.json, restart the Xray service with the command:

1
systemctl restart xray

Exit SSH session with server

Since the server work is now done:

1
exit

Download v2rayN latest release

Download v2rayN-With-Core.zip version 6.19 from https://github.com/2dust/v2rayN/releases.

Unzip the .zip file.

Download Xray-core latest release

Download Xray-windows-64.zip version 1.8.0 from https://github.com/XTLS/Xray-core/releases.

Unzip the .zip file.

Update core

Copy Downloads\Xray-windows-64\xray.exe into Downloads\v2rayN-With-Core\v2rayN-With-Core\bin\Xray.

Check that you have the latest version by opening Windows PowerShell and issuing the command:

1
.\Downloads\v2rayN-With-Core\v2rayN-With-Core\bin\Xray\xray.exe --version

With version 1.8.0 you should see the results:

1
2
Xray 1.8.0 (Xray, Penetrates Everything.) Custom (go1.20.2 windows/amd64)
A unified platform for anti-censorship.

Change v2rayN to English

Launch v2rayN.exe for the first time.

Change the v2rayN panel language to English. If you have never done this before, watch the video demonstration How to change v2rayN to English.

Add VLESS server configuration

From the v2rayN menu bar, select Servers > Add [VLESS] server.

Specify a VLESS server as follows:

Field Value
Core Type Xray
Alias Anything you like, e.g. gRPC
Address Server IP address, e.g. 168.235.89.227
UUID E.g. b29ce075-dcb5-46ce-a0c5-189e3f633701
Port 443
Flow Blank
Encryption none
Transport grpc
grpc mode multi
Camouflage type Blank
Camouflage domain (host) Blank
Path (grpc serverName) grpc
TLS reality
SNI www.microsoft.com
Fingerprint e.g. chrome
Public Key 8eH2aDUtsCkBJxnIqknHP-3qu-MMyjYFhNs4-MFHpBs
Short Id a1
SpiderX /

Click Confirm to save the server configuration.

Set system proxy

To allow you to use any browser, find the v2rayN icon in the system tray, right-click to bring up the context menu, and select Set system proxy.

v2rayN screenshot

v2rayN configured for gRPC and REALITY

0%