Split-tunneling with Shadowsocks allows you to route only selected traffic through the proxy while keeping other traffic on the direct network path. For site owners, enterprises, and developers this approach improves performance, reduces bandwidth costs, and minimizes latency for local services while still protecting or bypassing specific flows. The following guide provides a practical, technical, step-by-step walkthrough covering server-side and client-side configuration, iptables/ip rule examples, domain/IP-based splitting techniques, and troubleshooting tips.
Prerequisites and architecture overview
Before you begin, ensure you have the following in place:
- A working Shadowsocks server (any modern implementation: shadowsocks-libev, go-shadowsocks2, or equivalent) on a public IP.
- Access (root or sudo) to the server and to the client machines where you will implement split-tunneling rules.
- Basic Linux networking knowledge for iptables, ip rule, ip route, and netfilter TPROXY if you need transparent proxying.
- Client-side Shadowsocks apps or generic SOCKS5-capable apps (Proxifier, proxychains-ng, system proxy settings, or mobile apps such as Shadowsocks-android/Shadowrocket).
High-level approaches for split-tunneling with Shadowsocks:
- Application-level proxying — Configure specific applications to use the local SOCKS5 proxy created by the Shadowsocks client (simplest, per-application control).
- System-level proxying — Use OS-level proxy settings or tools like Proxifier/ProxyCap to direct selected apps through SOCKS5.
- Transparent proxy (redirect/TPROXY) — Redirect selected traffic (by IP, port, or domain) to a local redirector (ss-redir) using iptables + ip rule, making split-tunnel transparent to apps.
- DNS-driven split — Resolve specific domains to IP sets and route those IPs via ipset + iptables to the Shadowsocks path (useful for domain-based selection).
Server-side essentials
Server configuration is usually minimal for split-tunneling because most selection is done client-side. Still, ensure the server is optimized:
- Run a recent shadowsocks server (example using shadowsocks-libev):
/etc/shadowsocks-libev/config.json (example)
{“server”:”0.0.0.0″,”server_port”:8388,”password”:”your_password_here”,”method”:”chacha20-ietf-poly1305″,”timeout”:300,”fast_open”:false}
- Enable UDP relay support if you need UDP for games or VoIP (shadowsocks-libev supports UDP relay).
- Consider running with a plugin (like v2ray-plugin) when you need obfuscation.
- Open the server port in the firewall and ensure MTU/MSS settings are appropriate for client networks.
Client-side: application-level split (simplest)
This option is best when you can configure individual applications to use SOCKS5. Common use cases: browsers, curl, SSH tunnels, or custom apps.
- Run the Shadowsocks client which provides a local SOCKS5 listener, typically 127.0.0.1:1080.
- Configure applications to use SOCKS5 proxy 127.0.0.1:1080. Example for curl:
curl --socks5-hostname 127.0.0.1:1080 https://example.com
- Browsers: you can configure Firefox directly to use SOCKS5 for specific profiles or use browser extensions to toggle proxy rules.
- For Windows: use Proxifier/Proxifier-like tools to create rules that route traffic from selected executables through 127.0.0.1:1080.
- macOS: ProxyCap or Proxifier for macOS provides similar per-app routing.
Client-side: system-level split with Proxifier / proxychains
If you need dozens of apps proxied selectively and your OS lacks fine-grained per-app proxying, third-party tools are efficient.
- Install Proxifier (Windows/macOS) or proxychains-ng (Linux). Configure the proxy entry: SOCKS5 127.0.0.1:1080.
- Create rules by process name, destination IP range, or port. Example Proxifier rule: certain.exe -> route via Shadowsocks SOCKS5; all other apps -> direct.
- proxychains-ng config (Linux) can chain selective commands; prefix a command with proxychains4 to route that command through SOCKS5.
Transparent split-tunneling with iptables + ss-redir (advanced)
Transparent proxying is useful when you cannot change app proxy settings. The client machine redirects selected IP ranges or ipset entries to a local transparent proxy (ss-redir) or redirector that forwards via the Shadowsocks SOCKS5 tunnel.
Install necessary components
- shadowsocks-libev (ss-local and ss-redir)
- ipset for IP sets
- iptables with TPROXY modules or legacy REDIRECT depending on requirements
Example: create ipset and iptables rules to route traffic for a target IP set
Create an ipset containing IP ranges you want to send through Shadowsocks (e.g., foreign CDN IPs):
ipset create gfwlist hash:net
Add entries:
ipset add gfwlist 203.0.113.0/24
Start ss-redir locally (assumes you use ss-redir listening on 127.0.0.1:12345):
ss-redir -c /etc/shadowsocks-libev/config.json -u -l 12345
Set up iptables REDIRECT (works for TCP):
iptables -t nat -N SHADOWSOCKS
iptables -t nat -A SHADOWSOCKS -m set --match-set gfwlist dst -p tcp -j REDIRECT --to-ports 12345
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS
Notes:
- REDIRECT is simpler but only handles TCP. For UDP you need TPROXY and more complex routing with policy routing tables and ip rule.
- Exclude local networks to avoid redirecting LAN traffic (example rule to bypass 10.0.0.0/8, 192.168.0.0/16).
TPROXY for UDP + advanced transparent proxying
When you need UDP transparency (DNS, VoIP), use TPROXY. Overview of steps:
- Load kernel modules: xt_TPROXY, nf_tproxy_core, x_tables, xt_socket.
- Create a new routing table and ip rule:
ip rule add fwmark 0x1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
- Mark packets in mangle table and redirect to tproxy port:
iptables -t mangle -N SHADOWSOCKS
iptables -t mangle -A PREROUTING -p udp -m set --match-set gfwlist dst -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p udp -m set --match-set gfwlist dst -j TPROXY --on-port 12345 --on-ip 127.0.0.1
Run a TPROXY-capable local forwarder (for example, redsocks2 compiled with TPROXY support or a specialized local plugin) listening on 127.0.0.1:12345 and forwarding to the Shadowsocks server.
Domain-based split using DNS + ipset
When selection is domain-driven (e.g., all traffic to example.com), resolving domains to IPs and pushing them into ipset is a robust approach. The typical pipeline:
- Run a DNS resolver (dnsmasq/pdnsd/unbound) configured to resolve and capture the IPs for specific domains.
- A script monitors DNS responses and populates ipset with resolved addresses (commonly used with a “gfwlist” or custom domain list).
- iptables uses the ipset to redirect traffic to ss-redir or to mark packets for TPROXY routing.
Example small script approach (pseudo):
– Query domain list periodically with dig; add returned IPs to ipset (with TTL refresh).
Client-specific examples
Windows
- Install Shadowsocks for Windows (provides local SOCKS5 at 127.0.0.1:1080).
- For per-application rules use Proxifier: add a proxy server entry pointing to 127.0.0.1:1080, then create rules by process name or destination IP range.
- To do system-wide split, configure Proxifier rules: “Bypass LAN and local addresses,” add rules to redirect only selected remote IP ranges through the SOCKS5 proxy.
macOS
- Use ShadowsocksX-NG (provides system proxy toggle) and set up proxy modes: Global, Auto (PAC), or Manual. You can generate a PAC file for fine-grained domain rules.
- Proxifier for macOS gives per-app control if PAC files are insufficient.
Linux
- Use ss-local + proxychains-ng for per-command routing.
- For transparent split, use ss-redir + ipset + iptables as shown above. systemd services can manage ss-redir and ipset population scripts.
Android
- Shadowsocks-android supports “Bypass LAN & China” and provides per-app routing on rooted devices via VPN mode or via iptables redirect on rooted devices.
- Non-root users can use the built-in VPN mode: it captures all traffic and selectively routes traffic by domain/IP inside the app’s configuration (route rules or bypass lists).
iOS
- Shadowrocket or Quantumult provide per-domain rules and allow split-tunneling. Use rule lists to route by domain, IP CIDR, or GeoIP.
- iOS requires these apps to manage VPN-like tunnels; App Store restrictions mean options may vary by region.
DNS considerations and preventing leaks
DNS leaks can expose which domains clients are requesting. To prevent leaks:
- Configure client DNS to use an encrypted DNS (DoH/DoT) over the Shadowsocks tunnel or a local DNS resolver that forwards sensitive queries through the tunnel.
- In transparent setups, route DNS queries for domains in your ipset through the proxy by matching destination port 53 in iptables, or use TPROXY for UDP DNS.
- Alternatively, use dnscrypt-proxy or a local Unbound configured to forward through the SOCKS5 tunnel.
Testing and troubleshooting
Checklist to validate your split-tunnel configuration:
- Check that ss-local or ss-redir is running:
ss -lntp | grep ss-localorss -lntp | grep ss-redir. - Verify ipset contents:
ipset list gfwlist. - Check iptables chains:
iptables -t nat -Sandiptables -t mangle -S. - Use tcpdump to confirm traffic flows:
tcpdump -i any host X.X.X.Xand verify packets hit the REDIRECT/TPROXY port. - Test DNS resolution for targeted domains and ensure resolved IPs are in ipset and routed correctly.
Common issues and fixes:
- Packets not redirected: ensure PREROUTING rules are correct and no earlier rule accepts packets. Use
iptables -t nat -L -n -vto view counts. - UDP missing: implement TPROXY and appropriate ip rule/IP route table entries.
- Local network access broken: add bypass rules for RFC1918 ranges and local subnets.
- Connection resets or MTU issues: lower MTU or enable MSS clamping on iptables for TCP flows.
Security and performance tuning
Security tips:
- Use modern cipher suites (e.g., chacha20-ietf-poly1305 or AES-GCM variants) and strong passwords.
- Rotate server keys periodically and monitor server logs for anomalies.
Performance tips:
- Enable TCP Fast Open and tune buffer sizes if supported by your kernel and Shadowsocks build.
- On busy clients, use ipset for mass route matching instead of many individual iptables rules.
- For high-latency links, consider UDP-based forwarding or TCP acceleration tools inside the tunnel.
Split-tunneling with Shadowsocks is a flexible solution that balances privacy, performance, and accessibility. Choose the method—application-level, system-level, transparent, or DNS-driven—that best matches your environment and control requirements. For complex deployments, combine domain-based ipset population with TPROXY for full TCP/UDP coverage and use robust DNS forwarding to avoid leaks.
For more in-depth guides and downloadable scripts tailored to common server distributions, visit Dedicated-IP-VPN at https://dedicated-ip-vpn.com/. Dedicated-IP-VPN provides resources for server hardening, routing scripts, and best practices that complement this walkthrough.