How I Finally Got My Own Japan VPS Proxy Working
I originally bought a Japan VPS for my blog, then realized I could also use it to run my own proxy. What I thought would be a quick side pro

How I Finally Got My Own Japan VPS Proxy Working
I originally bought a Japan VPS for my blog, then realized I could also use it to run my own proxy. What I thought would be a quick side project turned into a full day of trial and error, from older SS-style setups all the way to VLESS + Reality. This post is the cleaned-up version of everything that finally worked.
If you want a setup that is stable, hard to detect, and fully under your own control, this is the one I would recommend.
Why not just use a public proxy service?
Public services are easy, but they always came with tradeoffs that bothered me:
- Privacy: all your traffic goes through someone else's server.
- Reliability: a service can disappear overnight.
- Shared IP risk: once too many people abuse the same IP, everyone gets blocked together.
With your own VPS, the IP is yours, the traffic path is yours, and the operational risk is much easier to understand.
What this setup does
This stack is based on Xray-core with VLESS + Reality + XTLS-Vision, which is widely considered one of the strongest self-hosted proxy combinations available right now.
China sites such as Baidu, Taobao, and WeChat
-> direct connection, no proxy
Global sites such as Google, YouTube, and X
-> encrypted tunnel -> Japan VPS -> destination
Four key properties
| Feature | How it works | Why it matters |
|---|---|---|
| Traffic disguise | Reality | Your traffic looks like a normal HTTPS connection |
| Strong encryption | TLS 1.3 | Prevents middleboxes from reading or tampering with content |
| Full traffic support | XTLS-Vision | Handles HTTP, HTTPS, and UDP cleanly |
| Fingerprint camouflage | uTLS Chrome | Makes the TLS handshake look like real Chrome traffic |
Architecture at a glance
Windows PC
Clash Verge Rev
|- China traffic -> direct
`- Overseas traffic -> encrypted -> Japan VPS
Japan VPS
Xray-core
`- receives, unwraps, forwards, returns
Once you understand that split-routing model, the rest of the setup makes much more sense.
What you need before starting
Server side
| Requirement | Notes |
|---|---|
| Location | An overseas VPS such as Japan, Hong Kong, or Singapore |
| OS | Ubuntu 20.04 / 22.04 / 24.04 or Debian 11 / 12 |
| Spec | 1 vCPU and 512 MB RAM is enough for Xray itself |
| Access | root or sudo |
A disguise domain
Reality needs a real HTTPS site to impersonate.
Your chosen domain should:
- support TLS 1.3
- support HTTP/2
- stay reachable
- be hosted outside mainland China
Best option: if your VPS already serves a real HTTPS site such as your personal blog, use your own domain. That gives you the most control and the fewest surprises.
Client side
- Windows 10 or Windows 11, 64-bit
- normal access to domestic sites
Step 1: Install Xray on the VPS
Run the following on the VPS over SSH:
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
If the installation succeeds, you should see output similar to:
info: Xray v26.x.x is installed.
info: Enable and start the Xray service
Then verify it:
xray --version
systemctl status xray
Important paths:
| Path | Purpose |
|---|---|
/usr/local/bin/xray | binary |
/usr/local/etc/xray/config.json | main config file |
/var/log/xray/ | logs |
Step 2: Generate the required values
You need three important values for a Reality setup.
Generate the Reality key pair
xray x25519
You will get something like:
PrivateKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Password (PublicKey): yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
PrivateKey: server only, never leak itPublicKey: client side, safe to distribute to your own devices
Generate the user UUID
xray uuid
Example:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
This UUID must match on both server and client.
Generate the short ID
openssl rand -hex 8
Example:
a1b2c3d4e5f6a7b8
Save all three values somewhere before moving on.
Step 3: Configure the server
Open the config file:
nano /usr/local/etc/xray/config.json
Replace the entire file with this template and fill in your own values:
{
// Log settings: keep only warnings and errors to reduce noise
"log": {
// Log level: warning is enough for most normal setups
"loglevel": "warning"
},
// Inbounds: defines how clients connect to your VPS
"inbounds": [
{
// Listen on all network interfaces
"listen": "0.0.0.0",
// Port exposed to the client
"port": 8443,
// Inbound protocol: VLESS
"protocol": "vless",
// VLESS-specific settings
"settings": {
// Allowed client list
"clients": [
{
// Client UUID: must match the client config exactly
"id": "YOUR-UUID-HERE",
// Flow control used with Reality
"flow": "xtls-rprx-vision"
}
],
// VLESS always uses "none" here
"decryption": "none"
},
// Transport-layer settings
"streamSettings": {
// Transport network: TCP
"network": "tcp",
// Security layer: Reality
"security": "reality",
// Detailed Reality settings
"realitySettings": {
// Whether to expose extra debugging details in logs
"show": false,
// The real HTTPS destination Reality impersonates during handshake
"dest": "YOUR-DOMAIN:443",
// XTLS version parameter, usually left at 0
"xver": 0,
// Allowed server names the client is permitted to present
"serverNames": [
// Your disguise domain, for example blog.example.com
"YOUR-DOMAIN"
],
// Server private key generated by xray x25519
"privateKey": "YOUR-PRIVATE-KEY",
// List of accepted short IDs
"shortIds": [
// Primary short ID used by the client
"YOUR-SHORT-ID",
// Optional empty fallback entry often kept in sample configs
""
]
}
},
// Sniffing helps Xray identify the target protocol correctly
"sniffing": {
// Enable protocol sniffing
"enabled": true,
// Allow overrides for these protocol types
"destOverride": ["http", "tls", "quic"]
}
}
],
// Outbounds: defines how the server forwards traffic outward
"outbounds": [
{
// freedom means normal direct access to the destination
"protocol": "freedom",
// Tag name for future routing references
"tag": "direct"
},
{
// blackhole means drop the traffic
"protocol": "blackhole",
// Tag name typically used for blocked routes
"tag": "block"
}
]
}
Fill the placeholders like this:
| Placeholder | Replace with |
|---|---|
YOUR-UUID-HERE | the value from xray uuid |
YOUR-DOMAIN | your disguise domain, such as blog.example.com |
YOUR-PRIVATE-KEY | the PrivateKey from xray x25519 |
YOUR-SHORT-ID | the value from openssl rand -hex 8 |
Then validate and restart:
xray run -test -config /usr/local/etc/xray/config.json
systemctl restart xray
ss -tlnp | grep 8443
You want to see port 8443 listening successfully.
Step 4: Open the firewall
This is one of the easiest steps to forget.
For Ubuntu with UFW:
ufw allow 8443/tcp
ufw status | grep 8443
For iptables:
iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
iptables-save > /etc/iptables/rules.v4
Also remember that many VPS providers have a separate cloud firewall or security group. If 8443/tcp is not allowed there, the node will still be unreachable.
To test from Windows:
Test-NetConnection -ComputerName your.vps.ip -Port 8443
If TcpTestSucceeded is True, the port is reachable.
Step 5: Install the Windows client
Use Clash Verge Rev with the Mihomo core. Older Clash clients often do not support Reality properly.
Download the latest Windows release here:
Look for the 64-bit installer under Assets and install it normally.
Step 6: Configure the client
Create a config.yaml file with the following content and replace the placeholders:
mixed-port: 7890
allow-lan: false
mode: rule
log-level: warning
ipv6: false
dns:
enable: true
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
- https://8.8.8.8/dns-query
fallback-filter:
geoip: true
geoip-code: CN
proxies:
- name: Japan-VPS
type: vless
server: YOUR.VPS.IP
port: 8443
uuid: YOUR-UUID-HERE
flow: xtls-rprx-vision
tls: true
udp: true
network: tcp
reality-opts:
public-key: YOUR-PUBLIC-KEY
short-id: YOUR-SHORT-ID
servername: YOUR-DOMAIN
client-fingerprint: chrome
proxy-groups:
- name: Proxy
type: select
proxies:
- Japan-VPS
- DIRECT
rules:
- GEOSITE,private,DIRECT
- GEOIP,private,DIRECT,no-resolve
- GEOSITE,cn,DIRECT
- GEOIP,cn,DIRECT,no-resolve
- MATCH,Proxy
Import it into Clash Verge Rev, enable the profile, turn on system proxy, and keep the mode set to rule.
Step 7: Verify everything
Check latency
In Clash Verge Rev, go to the proxy page and test the Japan-VPS node.
- If you get a latency value such as
85 ms, the node is working. - If it times out, use the troubleshooting section below.
Check exit IP
Open https://ip.sb. If it shows a Japan IP, the tunnel is working.
Check direct routing for domestic sites
Open a domestic site such as https://www.baidu.com. It should stay fast because it is not supposed to go through the proxy.
Troubleshooting
Most failures come from a short list of issues.
Config syntax errors
If the server config fails validation, paste config.json into JSONLint and look for missing commas or non-standard quotes.
Node timeout
Check these in order:
systemctl status xray
ss -tlnp | grep 8443
ufw status | grep 8443
If those look fine, check the VPS provider's cloud firewall or security group.
Browser traffic works, but games do not
Enable TUN mode in Clash Verge Rev so it can capture system-wide traffic, including apps that do not respect the normal proxy settings.
Domestic sites become slow
Make sure the client is in rule mode, not global mode.
Ongoing maintenance
Upgrade Xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
systemctl restart xray
Watch logs
journalctl -u xray -f
Add more users
Add more entries to the clients array, each with its own UUID:
"clients": [
{
"id": "FIRST-USER-UUID",
"flow": "xtls-rprx-vision"
},
{
"id": "SECOND-USER-UUID",
"flow": "xtls-rprx-vision"
}
]
Then restart Xray:
systemctl restart xray
Final thoughts
After I got this running, it felt far more stable than any shared service I had used before. More importantly, it felt predictable. The IP is mine, the server is mine, and the traffic path is mine.
Reality is especially impressive because the handshake looks extremely close to a normal HTTPS connection. Combined with XTLS-Vision, the tunnel exposes very little extra signal compared with older proxy approaches.
If you already have an overseas VPS sitting idle, this setup is worth the effort. Once it is in place, it can stay useful for a very long time.
Quick parameter checklist
| Item | Source |
|---|---|
| VPS IP | your VPS control panel |
| Port | your chosen port, 8443 in this guide |
| UUID | xray uuid |
| PrivateKey | xray x25519 |
| PublicKey | xray x25519 |
| shortId | openssl rand -hex 8 |
| Disguise domain | any suitable TLS 1.3 + HTTP/2 domain |
Reader feedback
What should this post improve or add?
Leave a feature request, improvement idea, or follow-up topic. I review these regularly.
Latest suggestions
No suggestions yet. Be the first one.
For deduplication, only hashes of IP, browser info, and local fingerprint are stored. Raw IP is not stored.