Split-tunneling is a powerful technique for balancing performance, privacy, and granular control when using encrypted proxy protocols. For operators and developers deploying Trojan-based VPN setups, proper split-tunneling configuration can yield fast, reliable connections for sensitive traffic while leaving less critical flows on the direct path. This article dives into the technical details of implementing split-tunneling with Trojan (including trojan-go variants), covers routing and DNS hardening to prevent leaks, and offers practical configuration snippets and troubleshooting tips for Linux, Windows, macOS, and Android/iOS environments.
Why Split-Tunneling with Trojan?
Trojan is a TLS-based proxy that mimics HTTPS traffic to evade censorship and provide robust privacy. Compared to full-tunnel VPNs, split-tunneling lets you:
- Preserve bandwidth and lower latency by keeping non-sensitive traffic on a direct ISP route.
- Reduce server load and cost because only selected traffic traverses the Trojan server.
- Apply fine-grained policies — per-app or per-destination routing, improved access control for enterprise deployments.
Core Principles for Reliable Split-Tunneling
Before implementing, follow these principles:
- Policy-first routing: Decide routing by destination IP blocks, domains, or application identity (UID/GID on Linux).
- DNS control: Avoid leaks by forcing DNS queries for tunneled flows through private resolvers or the Trojan server.
- Mark and route: Use packet marking (iptables/ip rule/fwmark) or dedicated routing tables to separate flows.
- Authentication and certificate validation: Ensure TLS certs and SNI match to avoid man-in-the-middle attacks; pin certificates when possible.
trojan-go Client: Built-in Policy Features
trojan-go (a popular go-implementation) includes flexible routing and policy configuration. Use the client-side router section to define rules and bypass lists. A representative snippet:
<pre>{
“run_type”: “client”,
“local_addr”: “127.0.0.1”,
“local_port”: 1080,
“remote_addr”: “trojan.example.com”,
“remote_port”: 443,
“password”: [“your-password”],
“ssl”: {…},
“router”: {
“enabled”: true,
“bypass”: [
“geoip:CN”,
“domain:localhost”,
“domain:example.com”
],
“default_policy”: “proxy”,
“rules”: [
{“type”:”field”,”outboundTag”:”direct”,”domain”:[“geosite:category-ads”]},
{“type”:”field”,”outboundTag”:”proxy”,”domain”:[“geosite:google”,”domain:your-cdn.com”]}
]
}
}</pre>
Key points: Use geosite and geoip lists to bulk-bypass or proxy. The client can operate as a SOCKS5/HTTP proxy for per-app proxification tools or as a transparent intercept with system iptables rules.
Linux: IP Tables, Marks, and Multiple Routing Tables
On Linux servers or clients where you control networking, using iptables/ip rule and separate routing tables is the most robust approach for transparent split-tunneling.
Workflow
- Mark packets with iptables based on user, port, or process owner.
- Add ip rules to route marked packets through a separate routing table that sends traffic to the local Trojan client (e.g., SOCKS5) or directly re-routes to the remote Trojan server.
- Ensure DNS queries for marked packets are routed to a safe resolver (e.g., local dnsmasq binding to 127.0.0.1 that forwards to upstream via the tunnel).
Example: Marking and Routing
Assume trojan-go listens on 127.0.0.1:1080 (SOCKS5). Mark traffic from UID 1001 (specific app) and route via the local proxy using redsocks or iptables REDIRECT for transparent proxying.
<pre># Create a new routing table
echo “200 trojan” >> /etc/iproute2/rt_tables
Mark packets from user 1001
iptables -t mangle -A OUTPUT -m owner –uid-owner 1001 -j MARK –set-mark 0x1
Use ip rule to route marked packets using table ‘trojan’
ip rule add fwmark 0x1 table trojan
Add a default route in the trojan table to the local transparent proxy (e.g., redsocks)
ip route add default via 127.0.0.1 dev lo table trojan
</pre>
For transparent TCP interception (no SOCKS-aware apps), run a local transparent proxy (redsocks2, chinadns-ng + tproxy) and redirect marked traffic to the proxy port instead of changing routing directly. Use -m tproxy targets for UDP where supported.
Preventing DNS Leaks on Linux
Common mistake: apps still query the system resolver, leaking DNS to your ISP. Use these strategies:
- Run a local DNS resolver (dnsmasq/unbound) and configure it to forward via the Trojan tunnel (via TCP/DOH/DOH-over-proxy) for marked processes.
- Use iptables to redirect DNS (udp/53 tcp/53) from marked UIDs to the local resolver:
iptables -t nat -A OUTPUT -p udp --dport 53 -m owner --uid-owner 1001 -j DNAT --to-destination 127.0.0.1:5353. - Alternatively, set /etc/resolv.conf on per-network-namespace instances to point to an internal resolver.
Windows: Per-App Proxies and Route Overrides
Windows lacks native packet-marking by UID, so use per-application proxifiers or route rules:
- Use a GUI Trojan client (trojan-qt5) that exposes a local SOCKS/HTTP proxy and configure per-app proxy settings within applications that support it.
- For system-wide yet selective routing, add static route entries using
route ADDto route specific destination networks via the local gateway or VPN adapter. - Use third-party tools like Proxifier, ProxyCap, or Proxychains (for Windows equivalents) to define which apps use the local Trojan proxy. These tools let you specify domain/IP rules and chain to SOCKS5 listeners.
Tip: To avoid DNS leaks on Windows, either set apps to use the SOCKS/HTTP proxy for DNS resolution (many proxifiers provide this option) or configure the system to use a DNS server reachable only via the tunnel and bind the VPN adapter accordingly.
macOS: PF and Proxification
macOS can leverage PF (packet filter) rules and tools like Proxifier for per-app policies. A common approach:
- Run trojan-qt5 or trojan-go locally as a SOCKS5/HTTP proxy.
- Use Proxifier to route selected apps through that proxy; Proxifier supports DNS-through-proxy to avoid leaks.
- For advanced setups, use PF anchors to redirect traffic from certain processes or destination IPs to a local transparent proxy port.
Mobile: Android/iOS Strategies
On mobile devices you typically have two options:
- Use an app that supports Trojan protocol natively and has split-tunnel/policy features (some trojan clients based on V2RayNG/trojan-go provide domain/geo lists).
- Use the VPN API to create a local VPN that selectively tunnels traffic; Android VPN apps can implement per-app allowlists/blocklists, while iOS offers per-app VPN only for managed devices.
Performance Tuning and Server Considerations
To maximize throughput and reduce latency while using Trojan:
- Keep TLS on 1.3: TLS 1.3 offers lower handshake overhead and better resumption semantics.
- TLS session reuse: Enable session tickets/resumption on server and client to cut down on handshake time.
- Use HTTP/2 or WebSocket transports when helpful: trojan-go supports WebSocket; this can improve compatibility behind restrictive middleboxes.
- TCP stack tuning: Use TCP congestion control algorithms like BBR on Linux servers for better throughput in high-latency links.
- MTU tuning: Ensure the path MTU is correct to avoid fragmentation; lower MTU slightly for encapsulated flows if you see fragmentation.
- Multiplexing: trojan-go can multiplex connections (reduce TCP connection churn) — beneficial for high-connection-density clients.
Security Hardening
Split-tunneling inherently increases the attack surface because some traffic stays local. Harden your setup:
- Pin TLS certificates: Configure clients to validate server certificate fingerprints (where supported) to prevent rogue CAs.
- Enforce SNI/ALPN validation: Confirm SNI matches expected hostnames on both ends.
- Use a kill-switch: Implement fail-closed rules for sensitive UIDs or destination IPs — if the tunnel drops, block those flows locally.
- Log and monitor: Use connection logging (anonymized where needed) and probes to detect leaks or route failures. Tools like tcpdump, iperf, and vnstat are helpful.
Testing and Troubleshooting
Verify split-tunnel behavior carefully:
- Use
tracerouteandcurl --interfaceto confirm which path traffic takes. - Run
tcpdump -i any port 1080 or host trojan.example.comto see proxied vs direct flows. - Use DNSLeakTest or
digto verify DNS queries are routed through the intended resolver. - Monitor
ss/netstatfor socket states to spot excessive SYN/FIN churn or half-open connections that affect throughput.
Example Deployment Patterns
Two practical patterns:
- Per-application proxying: Use a local trojan client with SOCKS5 and configure only chosen apps to use it. Best for application-layer control and minimal network stack changes.
- Transparent routing by destination: Use iptables + ip rule + separate routing table to redirect traffic destined for particular IP ranges (e.g., blocked geonets) to the trojan client. Best for enterprise environments and devices you manage fully.
Implementing split-tunneling with Trojan gives you the flexibility to optimize both performance and privacy. Whether you choose per-app proxies, routing marks, or VPN-based per-app policies, the combination of TLS-based Trojan protocol, robust DNS handling, and system-level routing ensures secure, high-performance selective tunneling.
For deployment examples, advanced configuration snippets, and dedicated IP options to reduce server-side fingerprinting, visit Dedicated-IP-VPN at https://dedicated-ip-vpn.com/.