Why You Need a Three-Layer Tunnel

Does your AI company often encounter the following situations?

  • Need to access applications or large model APIs that are only open to US IPs, such as OpenAI, Anthropic, Google, etc.
  • Need to connect to the company’s internal network in the US but don’t want to frequently set up proxies

Many people set up application layer proxies, which require setting HTTP_PROXY, HTTPS_PROXY, etc., in environment variables. However, many software do not support configuring proxies directly using environment variables, such as:

  • Docker containers do not perceive external environment variables. If you want to use existing docker compose files and want the services inside the docker to automatically use the proxy, you’ll have to tinker a bit.
  • Docker requires separate proxy configuration when accessing docker.io to pull images and build images.
  • Various software sources, such as pip, npm, etc., require separate proxy configuration.
  • Some software, like Google Cloud CLI, do not read proxy configurations from environment variables and require separate proxy configuration.
  • Some software, like Cursor, directly use IP addresses to access servers and use non-standard WebSocket protocols, which some proxy software are not compatible with or are prone to issues.
  • Some Node.js server-side libraries do not directly detect the HTTP_PROXY environment variable and require configuring an HTTP Proxy Agent. Some libraries (like axios) have bugs in proxy mode.
  • Some compiled language code (like C++, Go) often assembles HTTP requests themselves and may not support configuring HTTP proxies.
  • Some apps (like ChatGPT, Claude Code) use additional mechanisms to detect network environments. If they detect a proxy, they may refuse service or reduce intelligence (e.g., using a poorer model instead of the SOTA model).

Even by early 2023, the HTTP_PROXY environment variable in the official OpenAI Python library still had issues!

In March 2023, I fixed a small bug in the HTTP_PROXY environment variable for the OpenAI Python libraryIn March 2023, I fixed a small bug in the HTTP_PROXY environment variable for the OpenAI Python library

Many people spend a lot of time struggling with network issues when downloading and trying open-source AI projects, which is really a waste of time.

This tutorial will guide you step-by-step on how to set up a three-layer tunnel with full US IP, achieving:

  1. No need to manually set up proxies in each application
  2. All network requests are sent from US servers
  3. Support for multiple devices (Mac/Linux/iOS/Android/OpenWRT routers)

Principles and Architecture

What is a Three-Layer Tunnel?

In simple terms, we want to establish a connection path like this:

Your DeviceDomestic ServerUS ServerInternet/Company Intranet

The reason for relaying through a domestic server is that the network environment of many devices is relatively unstable when directly accessing US servers, and may even be inaccessible during peak times. By relaying through a domestic server, the company can purchase an international dedicated line between the domestic server and the US server. Large cloud service providers like Huawei, Alibaba, and Tencent offer such dedicated line services, with options for traffic or bandwidth billing. Even if you don’t want to purchase a dedicated line, using the public internet is also feasible in practice.

Technical Architecture

1
2
3
4
5
+-----------------+       +------------------+       +----------------+       +-----------+
| 你的设备 | | 国内服务器 | | 美国服务器 | | 互联网 |
| WireGuard客户端 | ====> | WireGuard接收 | ====> | VLESS接收 | ====> | /公司内网 |
| | | VLESS转发 | | WireGuard发送 | | |
+-----------------+ +------------------+ +----------------+ +-----------+

WireGuard is the three-layer tunnel protocol. We choose WireGuard because it is directly supported by the Linux kernel, has a simple and elegant design, and offers higher performance than other three-layer tunnel protocols like PPTP and OpenVPN. WireGuard has been praised by Linus Torvalds as a work of art:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Message-ID: <CA+55aFz5EWE9OTbzDoMfsY2ez04Qv9eg0KQhwKfyJY0vFvoD3g@mail.gmail.com>
Date: Thu, 2 Aug 2018 10:15:40 -0700
From: Linus Torvalds <torvalds@...ux-foundation.org>
To: David Miller <davem@...emloft.net>
Cc: Andrew Morton <akpm@...ux-foundation.org>,
Network Development <netdev@...r.kernel.org>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: Re: [GIT] Networking

On Wed, Aug 1, 2018 at 9:37 PM David Miller <davem@...emloft.net> wrote:
>
> Fixes keep trickling in:

Pulled.

Btw, on an unrelated issue: I see that Jason actually made the pull
request to have wireguard included in the kernel.

Can I just once again state my love for it and hope it gets merged
soon? Maybe the code isn't perfect, but I've skimmed it, and compared
to the horrors that are OpenVPN and IPSec, it's a work of art.

Linus

The reason for using the VLESS protocol instead of directly connecting with the WireGuard protocol is that WireGuard uses UDP. Both the public internet and some traffic-billed international dedicated lines will degrade UDP traffic, leading to higher packet loss rates during peak times. Therefore, we encapsulate the UDP packets of the WireGuard protocol and forward them using the VLESS protocol, which uses TCP + WebSocket protocol, making the connection more stable.

Data Flow Transmission Process

Let’s analyze in detail how data packets flow in this system:

  1. Local Device → Domestic Server:

    • Your device runs the WireGuard client, creating a virtual network interface (usually named wg0)
    • When an application sends a network request, the operating system routes the target traffic to the WireGuard virtual interface based on the routing table
    • The WireGuard client encrypts the data packets and sends them to the specified port on the domestic server via UDP (port 42371 in this example)
    • This stage uses WireGuard’s native UDP transmission, suitable for the relatively stable network environment from local to domestic server
  2. Domestic Server Internal Processing:

    • The Xray on the domestic server receives the WireGuard UDP traffic through dokodemo-door inbound
    • The received WireGuard encrypted data is forwarded to VLESS outbound by the Xray routing system
    • This step achieves the key protocol conversion: from UDP to TCP-based WebSocket
  3. Domestic Server → US Server:

    • The converted traffic is transmitted to the US server via VLESS protocol + WebSocket + TLS (optional)
    • WebSocket over TCP protocol avoids the issue of low priority for UDP traffic during transmission
    • Optional TLS encryption provides an additional security layer, preventing WireGuard protocol header data from being eavesdropped or tampered with by middlemen
  4. US Server Internal Processing:

    • The Xray on the US server receives the WebSocket traffic through VLESS inbound
    • Xray directs the received data to the local WireGuard service (configured via freedom outbound as 127.0.0.1:42371)
    • The WireGuard service decrypts the data packets and forwards the traffic to the target website or service via IP forwarding
  5. US Server → Internet/Intranet:

    • The decrypted data packets are sent out from the physical network interface of the US server
    • To external services and the company intranet, these requests appear to be directly sent from the US server

Network Performance Considerations

Under this architecture, several performance-related factors need attention:

  1. Increased Latency: Relaying through domestic and US servers inevitably increases network latency, but this is acceptable for most applications.
  2. Reduced Download Speed: Due to the three-layer tunnel, the entire TCP connection handshake process is directly between the client and the US server. The slow start process’s RTT is also cross-border network latency, which will reduce download speed compared to traditional HTTP/HTTPS proxy methods.
  3. MTU Settings: Due to multi-layer encapsulation, the MTU value needs to be appropriately lowered (such as the recommended 1280 in this article) to avoid performance issues caused by IP fragmentation.
  4. Slow Access to Domestic Websites: Due to the three-layer tunnel, accessing domestic websites requires a round trip from the US, which will be much slower.

Despite these overheads, the stability, compatibility, and convenience advantages brought by this architecture are usually more important, especially in enterprise environments, where it can avoid a lot of proxy configuration work and save valuable development and operation time.

Preparation

Resources You Need

  1. US Server: A US server with a public IP
  2. Domestic Server: A domestic server with a public IP
  3. Domain Name (optional): If using CloudFlare relay, a domain name is needed

Server Requirements

  • Operating System: Recommended to use Ubuntu 22.04
  • Network: Requires a public IP
  • Domestic server needs to open the firewall for UDP port 42371
  • US server needs to open the firewall for TCP port 10444 (direct connection mode) or TCP port 80 (CloudFlare relay mode)

Install Necessary Software

Run the following commands on each server:

1
2
3
4
5
6
7
8
9
10
11
# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装基本工具
sudo apt install -y curl wget git unzip net-tools

# 安装 WireGuard
sudo apt install -y wireguard

# 安装 Xray
sudo bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)"

Note: If the above steps to install Xray on the domestic server do not execute correctly, you can first download install-release.sh, modify the PROXY configuration to a usable public proxy, and then run it with sudo to install Xray.

UUID Generation and Management

When configuring Xray, a UUID is needed as the client identifier.

Method 1: Use Linux System Built-in Tool

1
cat /proc/sys/kernel/random/uuid

Method 2: Use Python

1
python3 -c "import uuid; print(uuid.uuid4())"

Detailed Configuration Steps

Step 1: Configure the US Server

1.1 Generate WireGuard Keys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建WireGuard配置目录
sudo mkdir -p /etc/wireguard
cd /etc/wireguard

# 生成密钥对
wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genpsk > preshared.key

# 查看生成的密钥(记录下来)
echo "服务器私钥: $(cat server_private.key)"
echo "服务器公钥: $(cat server_public.key)"
echo "预共享密钥: $(cat preshared.key)"

# 生成客户端密钥对
wg genkey | tee client_private.key | wg pubkey > client_public.key

# 查看生成的密钥
echo "客户端私钥: $(cat client_private.key)"
echo "客户端公钥: $(cat client_public.key)"

The above keys will need to be filled in the subsequent configuration files.

1.2 Create WireGuard Configuration File

1
sudo nano /etc/wireguard/wg0.conf

Enter the following content (replace with the corresponding keys):

1
2
3
4
5
6
7
8
9
10
[Interface]
Address = 10.10.20.1/16
ListenPort = 42371
PrivateKey = <server-private-key>
MTU = 1280

[Peer]
PublicKey = <client-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.10.0.0/24

1.3 Configure Xray

1
sudo nano /usr/local/etc/xray/config.json

Enter the following content (replace UUID with the previously generated value):

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
{
"log": {
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log",
"loglevel": "debug"
},
"inbounds": [
{
"tag": "wireguard-vless-in",
"port": 10444,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<random-uuid>",
"level": 0
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/wss"
}
}
}
],
"outbounds": [
{
"tag": "wireguard-out",
"protocol": "freedom",
"settings": {
"redirect": "127.0.0.1:42371"
}
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": ["wireguard-vless-in"],
"outboundTag": "wireguard-out"
}
]
}
}

1.4 Start the Service

1
2
3
4
5
6
7
8
9
10
11
# 启动WireGuard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# 启动Xray
sudo systemctl enable xray
sudo systemctl restart xray

# 检查状态
sudo systemctl status wg-quick@wg0
sudo systemctl status xray

1.5 Enable IP Forwarding

1
2
3
4
5
6
7
8
# 编辑系统配置文件
sudo nano /etc/sysctl.conf

# 添加或修改以下行
net.ipv4.ip_forward = 1

# 应用更改
sudo sysctl -p

1.6 Configure NAT

IP forwarding is enabled, but we also need to configure NAT to allow traffic from the WireGuard network to be forwarded to the internet. This step is very critical, otherwise the tunnel will not work properly.

1
2
3
4
5
# 添加 iptables NAT 规则
sudo iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -o eth0 -j MASQUERADE

# 查看添加的规则
sudo iptables -t nat -L -v

Note: In the above command, eth0 is the network interface name of the US server, and you need to replace it according to the actual situation. You can use the ip addr or ifconfig command to view the network interface name of your server.

If your server loses iptables rules after rebooting, you can use the following method to make the NAT rules persistent:

1
2
3
4
5
# 安装 iptables-persistent
sudo apt install -y iptables-persistent

# 保存当前 iptables 规则
sudo netfilter-persistent save

If you are using nftables instead of iptables (Ubuntu 22.04 uses nftables by default), you can use the following command:

1
2
3
4
5
6
7
8
# 添加 nftables NAT 规则
sudo nft add table nat
sudo nft 'add chain nat postrouting { type nat hook postrouting priority 100; }'
sudo nft add rule nat postrouting ip saddr 10.10.0.0/16 oif eth0 masquerade

# 保存 nftables 规则
sudo nft list ruleset > /etc/nftables.conf
sudo systemctl enable nftables

Step 2: Configure the Domestic Server

2.1 Create V2Ray/Xray Configuration File

1
sudo nano /usr/local/etc/xray/config.json

Enter the following content (replace the corresponding values):

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
{
"log" : {
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log",
"loglevel": "debug"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 42371,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1",
"port": 42371,
"network": "udp"
},
"tag": "wireguard-in"
}
],
"outbounds": [
{
"tag": "wireguard-vless-direct-out",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "<us-server-ip>",
"port": 10444,
"users": [
{
"id": "<random-uuid>",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/wss"
}
}
},
{
"tag": "wireguard-vless-proxy-out",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "<cloudflare-reverse-proxy-domain-name>",
"port": 443,
"users": [
{
"id": "<random-uuid>",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"wsSettings": {
"path": "/wss"
}
}
}
],
"routing": {
"strategy": "rules",
"rules": [
{
"type": "field",
"inboundTag": [
"wireguard-in"
],
"outboundTag": "wireguard-vless-direct-out"
}
]
}
}

Note: If direct connection is unstable, you can use CloudFlare as a relay and change outboundTag to “wireguard-vless-proxy-out”

2.2 Start the Service

1
2
3
4
5
6
# 启动Xray
sudo systemctl enable xray
sudo systemctl restart xray

# 检查状态
sudo systemctl status xray

Step 3: Configure CloudFlare Relay (Optional)

Step 3: Configure CloudFlare Relay (Optional)

If the direct connection from the domestic server to the US server is unstable, you can use CloudFlare as a relay. CloudFlare can help you automatically apply for a TLS certificate, proxy the 443 port of the CloudFlare server and the user-specified domain name to the 80 port of the US server, and then set up an Nginx reverse proxy on the US server to proxy the 80 port to the 10444 port.

3.1 Register a CloudFlare Account and Add a Domain

  1. Register a CloudFlare account
  2. Add your domain to CloudFlare
  3. Change the DNS server of the domain to the server provided by CloudFlare

3.2 Create DNS Records

  1. Select your domain in the CloudFlare control panel
  2. Click the “DNS” tab
  3. Add an A record pointing to the US server IP address
    • Type: A
    • Name: Subdomain (e.g., tunnel)
    • Content: US server IP
    • Proxy status: Proxied (cloud icon is orange)

3.3 Configure Nginx Reverse Proxy on the US Server

Since CloudFlare proxies to port 80, and our Xray listens on port 10444, we need to configure Nginx for forwarding:

  1. Install Nginx:

    1
    sudo apt install -y nginx
  2. Create an Nginx configuration file:

    1
    sudo nano /etc/nginx/sites-available/xray
  3. Add the following configuration content (adjust according to your domain):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    server {
    listen 80;
    server_name tunnel.yourdomain.com; # 替换为你的域名

    location /wss {
    proxy_pass http://127.0.0.1:10444;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    }
  4. Enable the configuration and restart Nginx:

    1
    2
    3
    sudo ln -s /etc/nginx/sites-available/xray /etc/nginx/sites-enabled/
    sudo nginx -t # Check for configuration errors
    sudo systemctl restart nginx
  5. Modify the Xray configuration on the domestic server:

    Edit the /usr/local/etc/xray/config.json file and modify the wireguard-vless-proxy-out outbound section to:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    "wireguard-vless-proxy-out": {
    "protocol": "vless",
    "settings": {
    "vnext": [
    {
    "address": "tunnel.yourdomain.com", // 替换为你的 CloudFlare 域名
    "port": 80, // 修改为 80 端口
    "users": [
    {
    "id": "<random-uuid>",
    "encryption": "none"
    }
    ]
    }
    ]
    },
    "streamSettings": {
    "network": "ws",
    "security": "none", // 移除 TLS
    "wsSettings": {
    "path": "/wss"
    }
    }
    }

After completing the above configuration, CloudFlare will proxy traffic to the 80 port of the US server, and then Nginx will forward the traffic to the 10444 port of Xray. This configuration does not require handling SSL certificates, simplifying the deployment process.

Note: In this configuration, traffic between CloudFlare and the US server is transmitted in plaintext. However, since the WireGuard protocol itself is already encrypted, the actual security risk is limited. If higher security is required, it is recommended to use HTTPS configuration.

Step 4: Generate WireGuard Client Configuration

Create a file named wg0-client.conf:

1
2
3
4
5
6
7
8
9
10
11
12
[Interface]
PrivateKey = <client-private-key>
Address = 10.10.0.1/16
DNS = 8.8.8.8, 8.8.4.4
MTU = 1280

[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <domestic-server-ip>:42371
PersistentKeepalive = 25

Note: AllowedIPs = 0.0.0.0/0, ::/0 means all traffic will go through the WireGuard tunnel

Step 5: Use on Different Devices

5.1 Windows Client

  1. Download the WireGuard official client
  2. Install and start WireGuard
  3. Click “Add Tunnel” → “Import from File”, and select the configuration file you just created
  4. Click the “Activate” button to enable the tunnel

5.2 macOS Client

  1. Download the WireGuard client from the App Store
  2. Open WireGuard, click “+”, and select “Import from File or Archive”
  3. Select the configuration file and click “Add”
  4. Click the switch to enable the tunnel

5.3 iOS Client

  1. Download the WireGuard client from the App Store
  2. Open WireGuard, click “+”, and select “Create from QR Code” or “Create from File”
  3. After importing the configuration, click the switch to enable the tunnel

5.4 Android Client

  1. Download the WireGuard client from the Google Play Store
  2. Open WireGuard, click “+”, and select “Import from File”
  3. Select the configuration file and click “Import”
  4. Click the switch to enable the tunnel

5.5 Linux Client

1
2
3
4
5
6
7
8
9
# 安装WireGuard
sudo apt install wireguard

# 复制配置文件
sudo cp wg0-client.conf /etc/wireguard/wg0.conf

# 启用隧道
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

5.6 OpenWRT Router

  1. Log in to the router management interface
  2. Install the WireGuard package:
    • System → Software → Search “wireguard” → Install
  3. Network → Interfaces → Add New Interface
    • Name: WireGuard
    • Protocol: WireGuard VPN
    • Copy the configuration file content to the corresponding fields
  4. Firewall Settings:
    • Firewall → General Settings → Allow Forwarding
    • Add the WireGuard interface to the WAN zone

Verification and Testing

Connection Test

  1. After connecting to WireGuard, ping the internal IP of the US server:

    1
    ping 10.10.20.1
  2. Visit ip.gs or ip.sb to check your current IP address, which should show as a US IP

Troubleshooting Guide

Connection Issues

  1. Unable to connect to the domestic server

    • Check if the firewall is open for port 42371 (UDP)
    • Check if the Xray service is running properly
  2. Can connect to the domestic server but cannot access the internet

    • Check if the firewall is open for port 10444 (TCP)
    • Check the WireGuard configuration on the US server
    • Check if the Xray service is running properly
    • Check if IP forwarding is enabled
  3. Unstable connection

    • Try using CloudFlare as a relay
    • Check MTU settings, you can try lowering it (e.g., 1200)

View Logs

  • WireGuard logs: sudo journalctl -u wg-quick@wg0
  • Xray logs: sudo cat /var/log/xray/error.log

Advanced Performance Optimization

  1. BBR Acceleration
1
2
3
4
5
6
7
8
9
10
11
12
# 编辑sysctl配置
sudo nano /etc/sysctl.conf

# 添加以下内容
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

# 应用设置
sudo sysctl -p

# 检查是否启用
sudo sysctl net.ipv4.tcp_congestion_control
  1. Adjust MTU Value

If the network connection is unstable, you can try different MTU values (between 1200-1500).

Policy Routing: Direct Access to Domestic Websites

As mentioned above, using a global tunnel will slow down access to domestic websites. In this section, we will explain how to configure policy routing so that domestic websites are accessed directly, while foreign websites go through the tunnel.

Preparing a List of Chinese IP Address Ranges

First, we need to obtain a list of Chinese IP address ranges.

Option 1: Use an open-source project

1
2
3
4
5
# 创建存放中国 IP 段的目录
sudo mkdir -p /etc/wireguard/chnroute

# 下载中国 IP 段列表
sudo curl -o /etc/wireguard/chnroute/chnroute.txt https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt

Option 2: Use APNIC official data

1
2
3
4
5
# 创建存放中国 IP 段的目录
sudo mkdir -p /etc/wireguard/chnroute

# 使用 APNIC 官方数据
sudo bash -c "curl 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | grep ipv4 | grep CN | awk -F\| '{ printf(\"%s/%d\\n\", \$4, 32-log(\$5)/log(2)) }' > /etc/wireguard/chnroute/chnroute.txt"

Configuration on Linux Systems

1. Create Routing Scripts (Linux Systems)

Create WireGuard up/down scripts to automatically execute when the WireGuard connection is established or disconnected:

1
sudo nano /etc/wireguard/wg-up.sh

Enter the following content:

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
#!/bin/bash

# 定义路由表 ID (用一个不常用的 ID,避免冲突)
TABLE_ID=200
# IP规则优先级
RULE_PRIO=100

# 创建新的路由表
ip rule add prio $RULE_PRIO table $TABLE_ID

# 添加默认路由到 WireGuard 接口
ip route add default dev wg0 table $TABLE_ID

# 将国内IP段添加到主路由表,使其走默认网关
if [ -f "/etc/wireguard/chnroute/chnroute.txt" ]; then
while read -r line; do
# 排除空行和注释行
[[ "$line" == "" || "$line" == \#* ]] && continue
# 添加路由规则,让中国IP走默认网关
ip route add $line via $(ip route | grep default | awk '{print $3}') dev $(ip route | grep default | awk '{print $5}')
done < "/etc/wireguard/chnroute/chnroute.txt"
echo "中国 IP 路由规则已添加"
else
echo "中国 IP 列表文件不存在"
fi

# 添加常见国内 DNS 服务器的路由
for dns in 114.114.114.114 114.114.115.115 223.5.5.5 223.6.6.6 180.76.76.76 119.29.29.29; do
ip route add $dns via $(ip route | grep default | awk '{print $3}') dev $(ip route | grep default | awk '{print $5}')
done

echo "WireGuard 策略路由配置完成"

Create a down script to clean up routing rules when the connection is disconnected:

1
sudo nano /etc/wireguard/wg-down.sh

Enter the following content:

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
#!/bin/bash

# 定义与 g-up.sh 相同的参数
TABLE_ID=200
RULE_PRIO=100

# 删除路由表规则
ip rule del prio $RULE_PRIO table $TABLE_ID 2>/dev/null

# 删除所有中国 IP 路由规则
if [ -f "/etc/wireguard/chnroute/chnroute.txt" ]; then
while read -r line; do
# 排除空行和注释行
[[ "$line" == "" || "$line" == \#* ]] && continue
# 删除路由规则
ip route del $line 2>/dev/null
done < "/etc/wireguard/chnroute/chnroute.txt"
echo "中国IP路由规则已删除"
fi

# 删除DNS服务器的路由
for dns in 114.114.114.114 114.114.115.115 223.5.5.5 223.6.6.6 180.76.76.76 119.29.29.29; do
ip route del $dns 2>/dev/null
done

echo "WireGuard 策略路由已清理"

Set script execution permissions:

1
2
sudo chmod +x /etc/wireguard/wg-up.sh
sudo chmod +x /etc/wireguard/wg-down.sh

2. Configure WireGuard to Use Scripts

Modify the WireGuard configuration file to add PostUp and PostDown hooks:

1
sudo nano /etc/wireguard/wg0.conf

Add the following in the [Interface] section:

1
2
PostUp = /etc/wireguard/wg-up.sh
PostDown = /etc/wireguard/wg-down.sh

Complete configuration example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Interface]
PrivateKey = <client-private-key>
Address = 10.10.0.1/16
DNS = 8.8.8.8, 8.8.4.4
MTU = 1280
PostUp = /etc/wireguard/wg-up.sh
PostDown = /etc/wireguard/wg-down.sh

[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <domestic-ip>:42371
PersistentKeepalive = 25

3. Restart the WireGuard Service

1
sudo systemctl restart wg-quick@wg0

4. Verify if Policy Routing is Effective

Test if accessing domestic websites is done directly:

1
2
3
4
5
6
7
8
# 追踪到百度的路由
traceroute www.baidu.com

# 查看当前路由表
ip route show

# 查看策略路由规则
ip rule list

Configuration on Mac Systems

macOS users can use the following script to achieve similar functionality:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# 定义变量
WIREGUARD_INTERFACE="utun3" # 根据实际情况调整WireGuard接口名称
DEFAULT_INTERFACE=$(route -n get default | grep interface | awk '{print $2}')
DEFAULT_GATEWAY=$(route -n get default | grep gateway | awk '{print $2}')
CHNROUTE_FILE="$HOME/chnroute.txt"

# 下载中国IP列表
curl -s 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > "$CHNROUTE_FILE"

# 添加中国IP路由规则
while read -r line; do
sudo route add -net "$line" "$DEFAULT_GATEWAY"
done < "$CHNROUTE_FILE"

# 添加常用中国DNS服务器路由
for dns in 114.114.114.114 114.114.115.115 223.5.5.5 223.6.6.6; do
sudo route add "$dns" "$DEFAULT_GATEWAY"
done

echo "macOS策略路由配置完成"

Save this script as a file (e.g., ~/wireguard-route.sh) and execute it manually after connecting to WireGuard:

1
2
chmod +x ~/wireguard-route.sh
sudo ~/wireguard-route.sh

Common Issues and Solutions

  1. Script Execution Failure

    • Check if the script has executable permissions
    • Ensure the interface name in the script is correct
  2. Routing Not Effective

    • Use ip route show to check the routing table
    • Ensure the Chinese IP list file exists and its content is correct
  3. Domestic Websites Still Slow

    • Check DNS settings, as DNS resolution might be going through foreign servers
    • You can use domestic anti-pollution DNS
  4. Unable to Access the Internet After Policy Routing

    • Check if the default route is correct
    • Ensure the AllowedIPs setting in the WireGuard configuration

With the above configuration, your device will achieve intelligent traffic splitting: domestic websites are accessed directly, while foreign websites are accessed through a three-layer tunnel, ensuring the stability of accessing foreign services without affecting the speed of accessing domestic websites.

Adding Multiple Clients

Important: Each Client Configuration is Limited to a Single Device

It is important to note that each WireGuard client configuration can only be used by one device at a time. Therefore, for each new device added, a new client configuration needs to be generated.

Steps: Adding a New Client

1. Generate New Client Keys on the US Server

1
2
3
4
5
6
7
8
cd /etc/wireguard

# 生成新客户端密钥对
wg genkey | tee client2_private.key | wg pubkey > client2_public.key

# 查看生成的密钥
echo "新客户端私钥: $(cat client2_private.key)"
echo "新客户端公钥: $(cat client2_public.key)"

2. Modify the WireGuard Configuration on the US Server

Edit the /etc/wireguard/wg0.conf file and add a new Peer section at the end:

1
sudo nano /etc/wireguard/wg0.conf

Add a new Peer section:

1
2
3
4
5
6
7
8
9
10
11
# 第一个客户端(原有配置)
[Peer]
PublicKey = <client-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.10.0.0/24

# 第二个客户端(新添加)
[Peer]
PublicKey = <client2-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.10.1.0/24

Note:

  • Each client needs to use a different IP address range (AllowedIPs)
  • You can also generate a new pre-shared key (PresharedKey) for each new client to enhance security

3. Reload the WireGuard Configuration on the US Server

1
2
3
4
5
sudo wg-quick down wg0
sudo wg-quick up wg0

# 或者使用以下命令重新加载配置(不断开现有连接)
sudo wg syncconf wg0 <(wg-quick strip wg0)

4. Create a New Client Configuration File

Create a new file named wg0-client2.conf:

1
2
3
4
5
6
7
8
9
10
11
12
[Interface]
PrivateKey = <client2-private-key>
Address = 10.10.1.1/16
DNS = 8.8.8.8, 8.8.4.4
MTU = 1280

[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <domestic-server-ip>:42371
PersistentKeepalive = 25

5. Distribute the New Configuration to the New Device

Transfer the wg0-client2.conf file to the new device and import it into the WireGuard client on the respective platform as mentioned earlier.

Performance Optimization: Choosing the Right Server Location

If you find the speed using the US server is slow, consider using servers in Japan or Singapore, which also allow access to OpenAI, Anthropic, and Google services, instead of the US server. Generally, users in northern China have faster access to Japanese servers, while users in southern China have faster access to Singapore servers. Such a replacement will not affect the use of most services and can significantly improve network experience and response speed.

Simply replace the US server in the above tutorial with a server in Japan or Singapore, and keep the other configuration steps unchanged. Choosing the right node location is an important step in optimizing the performance of the three-layer tunnel.

Comments

2025-03-14
  1. Why You Need a Three-Layer Tunnel
  2. Principles and Architecture
    1. What is a Three-Layer Tunnel?
    2. Technical Architecture
    3. Data Flow Transmission Process
    4. Network Performance Considerations
  3. Preparation
    1. Resources You Need
    2. Server Requirements
    3. Install Necessary Software
    4. UUID Generation and Management
  4. Detailed Configuration Steps
    1. Step 1: Configure the US Server
      1. 1.1 Generate WireGuard Keys
      2. 1.2 Create WireGuard Configuration File
      3. 1.3 Configure Xray
      4. 1.4 Start the Service
      5. 1.5 Enable IP Forwarding
      6. 1.6 Configure NAT
    2. Step 2: Configure the Domestic Server
      1. 2.1 Create V2Ray/Xray Configuration File
      2. 2.2 Start the Service
    3. Step 3: Configure CloudFlare Relay (Optional)
    4. Step 3: Configure CloudFlare Relay (Optional)
      1. 3.1 Register a CloudFlare Account and Add a Domain
      2. 3.2 Create DNS Records
      3. 3.3 Configure Nginx Reverse Proxy on the US Server
    5. Step 4: Generate WireGuard Client Configuration
    6. Step 5: Use on Different Devices
      1. 5.1 Windows Client
      2. 5.2 macOS Client
      3. 5.3 iOS Client
      4. 5.4 Android Client
      5. 5.5 Linux Client
      6. 5.6 OpenWRT Router
  5. Verification and Testing
    1. Connection Test
    2. Troubleshooting Guide
      1. Connection Issues
      2. View Logs
    3. Advanced Performance Optimization
  6. Policy Routing: Direct Access to Domestic Websites
    1. Preparing a List of Chinese IP Address Ranges
    2. Configuration on Linux Systems
      1. 1. Create Routing Scripts (Linux Systems)
      2. 2. Configure WireGuard to Use Scripts
      3. 3. Restart the WireGuard Service
      4. 4. Verify if Policy Routing is Effective
    3. Configuration on Mac Systems
    4. Common Issues and Solutions
  7. Adding Multiple Clients
    1. Important: Each Client Configuration is Limited to a Single Device
    2. Steps: Adding a New Client
      1. 1. Generate New Client Keys on the US Server
      2. 2. Modify the WireGuard Configuration on the US Server
      3. 3. Reload the WireGuard Configuration on the US Server
      4. 4. Create a New Client Configuration File
      5. 5. Distribute the New Configuration to the New Device
  8. Performance Optimization: Choosing the Right Server Location