This article provides a concise yet technically rich walkthrough for installing and securing an obfuscation plugin for a Trojan-based VPN setup. It targets site operators, enterprise administrators and developers who need a fast, repeatable deployment path that balances obfuscation effectiveness with production-hardening. The instructions assume a Linux server (Debian/Ubuntu family) and a basic working installation of Trojan. Where appropriate, commands and configuration snippets are provided for immediate copy-paste use.
Why use an obfuscation plugin with Trojan?
Trojan already mimics HTTPS and is resilient against simple DPI, but pairing it with an obfuscation plugin adds an extra layer of protocol disguise. Obfuscation plugins can:
- Mask the VPN traffic as ordinary HTTP(S) or WebSocket streams.
- Provide additional randomization and padding to reduce fingerprintability.
- Help pass middleboxes that rely on protocol signatures or simple heuristics.
Common plugin choices include v2ray-plugin (WebSocket/HTTP modes) and simple-obfs (HTTP/TLS modes). This guide uses generic plugin options so you can adapt to the specific binary you prefer.
Prerequisites
Before beginning, ensure you have:
- A public IPv4 address and domain name pointed at the server.
- Root or sudo access on the server.
- Trojan server binary installed and functional (test without plugin first).
- Certbot (or another ACME client) to manage TLS certificates.
- Basic firewall rules configured (allow SSH, ports for Trojan and HTTPS).
Install essential packages
On Debian/Ubuntu:
sudo apt update && sudo apt install -y curl wget build-essential git certbot ufw
Install and configure the obfuscation plugin
Choose your plugin and install it. Example: v2ray-plugin (server mode) from prebuilt releases or package manager. If you prefer simple-obfs, compile or install the release binary.
Example: v2ray-plugin installation
Download the latest release and extract:
wget https://github.com/shadowsocks/v2ray-plugin/releases/download/vX.Y.Z/v2ray-plugin-linux-amd64-vX.Y.Z.tar.gz
tar -xzf v2ray-plugin-linux-amd64-vX.Y.Z.tar.gz
sudo mv v2ray-plugin_linux_amd64 /usr/local/bin/v2ray-plugin && sudo chmod +x /usr/local/bin/v2ray-plugin
Plugin configuration options
Common plugin options to pass to the Trojan server include:
- mode: “server” for server-side obfuscation.
- server: bind address (usually 0.0.0.0).
- upstream: backend transport if using reverse proxy chain.
- path: WebSocket path for v2ray-plugin in ws mode (e.g., /static/).
- tls: whether the plugin itself performs TLS (usually false when Trojan already handles TLS).
- loglevel: debug/info/warn for troubleshooting.
For WebSocket obfuscation via v2ray-plugin, an example Trojan server-side snippet (pseudoconfig pattern) typically includes a plugin command line such as:
"plugin": "/usr/local/bin/v2ray-plugin", "plugin_opts": "server;path=/ws;loglevel=info"
TLS and certificates
Maintain TLS termination at Trojan to preserve its HTTPS-like behavior. Use Certbot to fetch production certificates and configure auto-renewal.
Example certbot command for standalone mode (if no webserver is running on port 80):
sudo certbot certonly --standalone -d vpn.example.com --agree-tos -m admin@example.com --non-interactive
Point Trojan’s certificate fields in its config to the Certbot-managed files (commonly under /etc/letsencrypt/live/vpn.example.com/):
- cert: fullchain.pem
- key: privkey.pem
Trojan configuration with plugin
Below is a conservative, production-oriented sample of relevant JSON fragments to add into Trojan’s config. Adjust paths, port numbers and UUIDs to match your environment.
(Place this inside the server “local” or appropriate listening block as your Trojan distribution expects.)
{
"run_type": "server",
"local_addr": "0.0.0.0",
"local_port": 443,
"remote_addr": "127.0.0.1",
"remote_port": 80,
"password": ["YOUR-UUID-OR-PASSWORD"],
"ssl": {
"cert": "/etc/letsencrypt/live/vpn.example.com/fullchain.pem",
"key": "/etc/letsencrypt/live/vpn.example.com/privkey.pem",
"fallback_port": 80
},
"plugin": "/usr/local/bin/v2ray-plugin",
"plugin_opts": "server;path=/ws;host=vpn.example.com;loglevel=info"
}
Notes: Use the plugin’s host/path parameters to align with the domain and any reverse proxy you might run. If you choose to front Trojan with Nginx, be careful to avoid duplicating TLS termination — either terminate TLS in Nginx and run Trojan in TCP mode on a different port, or let Trojan handle TLS and configure Nginx as a plain TCP/stream proxy.
Systemd service and process management
For reliability, run the plugin-managed Trojan as a systemd service. Create a service unit that starts Trojan and supervises its process. Example unit fragment:
[Unit]
Description=trojan server
After=network.target
Group=trojan
ExecStart=/usr/bin/trojan -c /etc/trojan/config.json
Restart=on-failure
LimitNOFILE=65535 [Install] WantedBy=multi-user.target
Create a dedicated system user (non-login) for trojan to minimize blast radius:
sudo useradd -r -s /usr/sbin/nologin trojan
Reload systemd and enable the service:
sudo systemctl daemon-reload
sudo systemctl enable --now trojan.service
Firewall and SELinux
Open the Trojan port and restrict other services:
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp
sudo ufw enable
If your distro enforces SELinux, ensure the trojan binary and plugin have appropriate contexts or run with a policy that permits network binding and reading of certificate files. For troubleshooting, check audit logs and use audit2allow to craft a minimal policy.
Verification and testing
Start with simple checks:
- Confirm the plugin process is running:
ps aux | grep v2ray-plugin - Check certificate and TLS handshake:
openssl s_client -connect vpn.example.com:443 -servername vpn.example.com - Use a trojan client configured with matching plugin options (ws path, host) and test connectivity.
Network-level verification:
- Use tcpdump to inspect traffic fingerprint:
sudo tcpdump -i eth0 host vpn.example.com and port 443 -w /tmp/trojan.pcap - Confirm that traffic resembles HTTP(S)/WebSocket rather than raw encrypted tunnels.
Troubleshooting common issues
Problem: Client cannot connect or handshake fails.
- Confirm UUID/password match exactly between server and client.
- Verify plugin options (path/host) are identical.
- Check certificates are valid and not expired.
Problem: High CPU usage or instability.
- Enable plugin loglevel=info or debug temporarily and inspect logs for repeated errors.
- Consider using a prebuilt binary optimized for your CPU architecture (avoid generic builds that trigger emulation).
Problem: DPI still detects the traffic.
- Tweak plugin padding/randomization options (if available).
- Use more advanced disguises: combine WebSocket with legitimate-looking HTTP headers and valid TLS ALPN values (e.g., h2,http/1.1).
- Run Trojan behind a real webserver (Nginx) and use stream proxying to make the upstream traffic appear identical to an actual web application.
Security hardening
Make your deployment production-grade with these extra measures:
- Harden TLS: disable weak ciphers, prefer ECDHE suites, enable TLS 1.2 and 1.3 only, configure strong ECDSA/RSA keys.
- Fail2ban: ban repeated failed connections to the service port to reduce brute-force attempts.
- Least privilege: run processes as unprivileged users and restrict file permissions on keys (600).
- Logging: forward plugin and trojan logs to a centralized logging system (syslog/ELK) for analysis.
- Monitoring: use Prometheus node_exporter + Blackbox exporter to probe availability and latency.
Performance tuning
For high-throughput scenarios, tune both OS and network stack:
- Enable BBR:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr - Increase file descriptor limits for the trojan user: update /etc/security/limits.conf and systemd unit’s LimitNOFILE.
- Adjust kernel network buffers: increase net.core.rmem_max and net.core.wmem_max as needed.
- Set TCP keepalive and disable Nagle only if it helps latency-sensitive workloads.
Operational notes
Automate certificate renewal hooks to gracefully reload the trojan service after cert update:
sudo crontab -e
Add a line:
0 3 * certbot renew --post-hook "systemctl reload trojan.service"
Maintain an upgrade process for the plugin binary and trojan. Test upgrades in a staging environment before production rollout, and keep a rollback plan and snapshot of the VM/container.
Finally, always keep an accurate inventory of domain names, certificate expiration dates and active user credentials so you can revoke or rotate them quickly if a breach or leak is suspected.
For detailed enterprise deployment patterns, additional reverse-proxy integration examples, and template systemd units, visit Dedicated-IP-VPN at https://dedicated-ip-vpn.com/.