Chaining WireGuard Configurations
Let’s say you have multiple WireGuard configurations and want to chain them together. In this post, we’ll demonstrate how to route traffic through multiple VPN servers using Xray-Core. Our example setup routes traffic through a VPS, then through Proton VPN, and finally through Cloudflare WARP. This creates a traffic flow: Client → VPS → Proton VPN → Cloudflare WARP → Internet.
Prerequisites
- A Server with root access
- Proton VPN subscription
- Basic understanding of WireGuard and networking concepts
Getting the Configurations
🔐 Proton VPN WireGuard Configuration
To get your Proton VPN WireGuard configuration:
- Log in to your Proton VPN dashboard
- Go to Downloads → WireGuard Configuration
- Select a server, generate the config, and download it
☁️ Cloudflare WARP Configuration
To generate a Cloudflare WARP WireGuard config:
-
Download the latest
wgcf
binary from the GitHub Releases page -
Extract and make the binary executable:
tar -xzf wgcf_*.tar.gz chmod +x wgcf
-
Register and generate a configuration:
./wgcf register ./wgcf generate
This creates wgcf-profile.conf
— your WARP WireGuard configuration.
Sample Configurations
Proton VPN Config (proton.conf)
[Interface]
# Bouncing = 10
# NetShield = 1
# Moderate NAT = off
# NAT-PMP (Port Forwarding) = off
# VPN Accelerator = on
PrivateKey = kOTPg8NrjXTvIMTHL4aLujsn0de4eKOaY7jrCffQNm0=
Address = 10.2.0.2/32, 2a07:b944::2:2/128
DNS = 10.2.0.1
[Peer]
# US-NY#460
PublicKey = ZZVNP1-7koLM6LPHsd89zOqW7TxWQHyc03wyRHbs82E=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 149.102.226.225:51820
Cloudflare WARP Config (warp.conf)
[Interface]
PrivateKey = qO2Bly_Luo96gNMoyX8WINOPHDmx-ouk4X4Ebt3eYXw=
Address = 172.16.0.2/32, 2606:4700:110:8980:9f47:7d49:48e3:5fab/128
DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
MTU = 1280
[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408
Setting Up Xray-Core
Installation
First, download and install Xray-Core:
# Download the latest release
wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip
unzip Xray-linux-64.zip
chmod +x xray
Configuration
Create the following chained.json
configuration file:
{
"log": {
"logLevel": "warning"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 51820,
"protocol": "wireguard",
"settings": {
"secretKey": "SERVER_PRIVATE_KEY_HERE",
"peers": [
{
"publicKey": "CLIENT_PUBLIC_KEY_HERE",
"allowedIPs": ["0.0.0.0/0"]
}
],
"mtu": 1420
},
"tag": "wireguard_in"
}
],
"outbounds": [
{
"protocol": "wireguard",
"tag": "warp",
"settings": {
"secretKey": "qO2Bly_Luo96gNMoyX8WINOPHDmx-ouk4X4Ebt3eYXw=",
"address": [
"172.16.0.2/32",
"2606:4700:110:8980:9f47:7d49:48e3:5fab/128"
],
"peers": [
{
"endpoint": "engage.cloudflareclient.com:2408",
"publicKey": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo="
}
],
"mtu": 1280
},
"streamSettings": {
"sockopt": {
"dialerProxy": "proton"
}
}
},
{
"protocol": "wireguard",
"tag": "proton",
"settings": {
"secretKey": "kOTPg8NrjXTvIMTHL4aLujsn0de4eKOaY7jrCffQNm0=",
"address": ["10.2.0.2/32", "2a07:b944::2:2/128"],
"peers": [
{
"endpoint": "149.102.226.225:51820",
"publicKey": "ZZVNP1-7koLM6LPHsd89zOqW7TxWQHyc03wyRHbs82E="
}
],
"mtu": 1420
}
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": ["wire_in"],
"outboundTag": "warp"
}
]
}
}
Client Configuration
Create a client configuration file to connect to your VPS:
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.1.0.2/24
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = YOUR_VPS_IP:51820
Note: Generate a new WireGuard key pair for the client:
wg genkey | tee client_private.key | wg pubkey > client_public.key
Running the Setup
-
Start Xray-Core on your VPS:
sudo ./xray -c chained.json
-
Configure firewall rules (if needed):
sudo ufw allow 51820/udp sudo ufw enable
-
Connect your client using any WireGuard client with the client configuration above.
How It Works
The traffic flow in this setup is:
- Client connects to your VPS via WireGuard
- VPS (Xray-Core) receives the traffic and routes it to the Proton VPN outbound
- Proton VPN forwards traffic to Cloudflare WARP (due to
dialerProxy
setting) - Cloudflare WARP sends traffic to the Internet
The dialerProxy: "proton"
setting in the WARP outbound configuration tells Xray-Core to establish the WARP connection through the Proton VPN tunnel, creating the desired chain.
Troubleshooting
Common Issues
- Connection refused: Check if Xray-Core is running and the port is open
- DNS resolution problems: Verify DNS settings in both configurations
- MTU issues: Try reducing MTU values if experiencing packet loss
- Key format errors: Ensure all keys end with
=
and are properly base64 encoded
Testing the Chain
You can verify the setup is working by checking your IP address:
curl ifconfig.me
The returned IP should be from Cloudflare’s range, indicating traffic is flowing through the complete chain.
Conclusion
This setup provides enhanced privacy by routing traffic through multiple VPN providers. The combination of Proton VPN and Cloudflare WARP offers both privacy protection and performance benefits.
In future posts, we’ll explore advanced setups including split tunneling, automatic failover, load balancing across multiple servers, and comprehensive DNS leak protection.