The Ultimate Stealth Proxy: Hiding Trojan-Go Inside a Live WordPress Blog
In the world of internet freedom, encryption is no longer enough; you need camouflage. This guide demonstrates how to deploy a Trojan-Go proxy behind a fully functional WordPress site, creating a setup that is statistically indistinguishable from a standard web service. By using Path Multiplexing, we ensure that your proxy traffic blends into the background noise of legitimate API calls and blog browsing.
I. Phase One: The Backend (Apache Decoy)
Apache will act as the “decoy” server, providing the real content that hides your proxy.
1. Install & Enable Modules
sudo apt update && sudo apt install apache2 -y # Enable modules for proxying and header manipulation sudo a2enmod proxy proxy_http headers rewrite
2. Configure Ports
Edit /etc/apache2/ports.conf using vim:
- Keep:
Listen 80andListen 1234(or your chosen internal port). - Remove/Comment:
Listen 443(This must be handled by Trojan-Go).
3. Create the VirtualHost
sudo vim /etc/apache2/sites-available/stealth-site.conf
<VirtualHost *:1234>
ServerName www.yourdomain.com
DocumentRoot /var/www/html/your_folder
# IMPORTANT: Trojan-Go handles decryption, so SSL is OFF here
SSLEngine off
# THE FIX: Tell WordPress the original request was HTTPS
# This prevents the infinite redirect loop
RequestHeader set X-Forwarded-Proto "https"
<Directory /var/www/html/your_folder>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
sudo a2ensite stealth-site.conf && sudo systemctl restart apache2
II. Phase Two: WordPress Compatibility Fix
WordPress will trigger a “Too Many Redirects” error if it doesn’t realize it’s behind a proxy.
Edit wp-config.php and insert this snippet at the very top, immediately after the <?php tag:
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$_SERVER['HTTPS'] = 'on';
}
define('WP_HOME', 'https://www.yourdomain.com/blog');
define('WP_SITEURL', 'https://www.yourdomain.com/blog');
III. Phase Three: The Proxy Gateway (Trojan-Go)
1. Configuration
Create /etc/trojan-go/config.json:
{
"run_type": "server",
"local_addr": "0.0.0.0",
"local_port": 443,
"remote_addr": "127.0.0.1",
"remote_port": 1234,
"password": ["your_password_here"],
"ssl": {
"cert": "/etc/letsencrypt/live/yourdomain.com/fullchain.pem",
"key": "/etc/letsencrypt/live/yourdomain.com/privkey.pem",
"sni": "yourdomain.com"
},
"websocket": {
"enabled": true,
"path": "/api/v2/updates"
}
}
2. Deploy the “Bait” Page
Create the actual directory for your secret path to satisfy manual probes:
mkdir -p /var/www/html/your_folder/api/v2/updates vim /var/www/html/your_folder/api/v2/updates/index.html
Insert: {"status":"online","message":"API endpoint active"}
IV. Phase Four: Troubleshooting (The “Field Manual”)
1. The SSL Conflict (Bad Request)
- Error: “Speaking plain HTTP to an SSL-enabled server port.”
- Fix: Certbot often creates
*-le-ssl.conffiles insites-enabled. You must disable them:sudo a2dissite *-le-ssl.conf. Only your custom port1234config should be active for that domain.
2. The Redirect Loop
- Fix: Ensure the PHP code in
wp-config.phpis at the absolute top. If it’s below the database definitions, it might be ignored. Clear your browser HSTS cache viachrome://net-internals/#hsts.
To ensure your server remains resilient after a reboot, you must wrap Trojan-Go in a Systemd service. This ensures the proxy starts automatically and restarts itself if it crashes.
Here is the final section to complete your deployment manual.
V. Phase Five: Persistence (Systemd Service)
Running the binary manually is for testing; for production, you need a background service.
1. Create the Service File
sudo vim /etc/systemd/system/trojan-go.service
2. Paste the Configuration
Copy and paste the following, ensuring the paths to your binary and config are correct:
[Unit] Description=Trojan-Go Proxy Server After=network.target nss-lookup.target [Service] Type=simple StandardError=journal # Change these paths if your binary or config are located elsewhere ExecStart=/usr/local/bin/trojan-go -config /etc/trojan-go/config.json Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
3. Enable and Start
# Reload systemd to recognize the new service sudo systemctl daemon-reload # Start the service now sudo systemctl start trojan-go # Enable the service to start on boot sudo systemctl enable trojan-go # Check the status to ensure it's "active (running)" sudo systemctl status trojan-go
VI. Final Verification Checklist
Before you close the terminal, run these three commands to ensure the “Invisible Proxy” is perfect:
- Check Port 443:
sudo ss -tulpn | grep :443It should be owned bytrojan-go. - Check Port 1234:
sudo ss -tulpn | grep :1234It should be owned byapache2. - Test the Decoy: Visit
https://yourdomain.com/api/v2/updatesin a browser.You should see your dummy JSON/HTML message, not a 404 or a Trojan error.
EX-I. Post-Deployment Summary
This setup creates a protocol-level illusion:
| Traffic Source | Request Type | Server Response | Visual Result |
| Censor/Auditor | HTTPS GET | Apache (via Trojan) | A real blog or API status page. |
| Shadowrocket | WebSocket Upgrade | Trojan-Go | A secure, high-speed tunnel. |
| Random Scanner | Direct IP Scan | Timeout/404 | No “Proxy” signature detected. |
By using X-Forwarded-Proto in Apache and $_SERVER['HTTPS'] = 'on' in WordPress, you’ve bridged the gap between a secure proxy gateway and a standard web application. You are now officially hiding in plain sight.
EX-II. Advanced Defense Analysis
Path Multiplexing & Behavioral Camouflage
The genius of this setup lies in the behavior of the /api/v2/updates path:
- Standard GET Request: Trojan-Go ignores it → Apache serves a JSON/HTML status page. (Status 200).
- Authorized WebSocket Handshake: Trojan-Go intercepts it → Tunnel opens. (Status 101).
Fingerprint Matching: Proxy traffic consists of long-lived WebSocket streams. By using an “API Updates” path, your long-lived connection is statistically explained away as a standard data sync between a client and a server. This is the ultimate “Double-Agent” configuration: real content as the best armor.
sudo certbot renew --post-hook "systemctl restart trojan-go apache2"