ts-proxy is a userspace Tailscale client that provides TCP/UDP port-forwarding and SOCKS5 proxy with UDP support. Full cone NAT and no UDP-over-TCP for SOCKS5 UDP (as long as Tailscale is not falling back on DERP).
Usage of ts-proxy:
-debug
enable debug mode
-dual-socks value
Combination of "Tailnet SOCKS" and "Serve SOCKS"
-ephemeral
use ephemeral node
-fwd-socks value
Forward SOCKS: 'bind_addr=tailscale_addr'
-hostname string
Tailscale device hostname (default "ts-proxy")
-serve-socks value
Serve SOCKS: 'bind_addr[,outaddr_config...]'
-tags string
comma-separated tags
-tailnet-socks value
Serve Tailnet SOCKS: 'bind_addr'
-tcp value
TCP forward rule: 'bind_addr=connect_addr'
-tcp-timeout int
TCP timeout in seconds (default 1100)
-tsnet-dir string
Directory for Tailscale credentials
-udp value
UDP forward rule: 'bind_addr=connect_addr'
-udp-timeout int
UDP timeout in seconds (default 330)
bind_addr, connect_addr, and tailscale_addr share basically the same syntax: host:port.
If a host string ends with .tshost, it will be replaced by the corresponding IP(v4) address using Tailscale DNS.
.tshost can be a shorthand for [hostname].tshost.
SOCKS and forward options can be specified multiple times.
-tcp-timeout sets the TCP timeout in SOCKS5. -udp-timeout sets the UDP timeout for both UDP port forwarding and SOCKS5 UDP Associate.
-tsnet-dir and -hostname are Tailscale-specific options.
If addresses (possibly resolved from .tshost) are within the Tailscale IP range (100.64.0.0/10 or fd7a:115c:a1e0::/64), they will be bound or connected via Tailscale.
bind_addr accepts a port-only specification (e.g., :8080). connect_addr accepts a domain specification (e.g., example.com:80).
Port forwarding between two local addresses or two Tailscale addresses is also possible (though less useful).
For TCP forwarding, using =TLS= instead of = enables TLS termination. You must enable HTTPS in the Tailscale Admin Console for this to work.
Serves a SOCKS5 proxy. bind_addr can be followed by a comma-separated list of outaddr_config entries, which specify outgoing addresses for the SOCKS5 proxy.
Each outaddr_config must follow the scope=ip syntax, where scope is one of: tcp4, tcp6, udp4, udp6, ip4 (sets both tcp4 and udp4), or ip6 (sets both tcp6 and udp6).
Either udp4 or udp6 can be set to disabled to avoid potential performance issues with delayedUDPConn.
Serves a SOCKS5 proxy on bind_addr that forwards traffic to an upstream SOCKS5 proxy specified by tailscale_addr.
bind_addr has the same syntax as in -tcp and -udp. tailscale_addr must be a Tailscale address.
Serves a SOCKS5 proxy on bind_addr that forwards traffic to Tailnet. bind_addr has the same syntax as in -tcp and -udp. Traffic whose destination is not Tailscale address is routed via local network.
A combination of -serve-socks and -tailnet-socks. Similar to -tailnet-socks, but accepts outgoing address configuration.
In UDP, delayedUDPConn is always used and disabled is not allowed in udp4 or udp6.
tsnet (which is used in ts-proxy) accepts some environment variables relating auth key, oauth client, etc. See tsnet documentation for detail.
ts-proxy -hostname pc1 -serve-socks :1080,tcp4=10.0.0.1 -tcp pc1.tshost:1234=127.0.0.1:5678 -udp :1234=pc2.tshost:5678
tsnet handles all Tailscale connectivity. https://github.com/txthinking/socks5 with minor customizations is used for the SOCKS5 server/client.
Due to golang/go#40569, net.Interface() and net.InterfaceAddrs() do not work correctly on newer Android versions. This tool uses https://github.com/wlynxg/anet to resolve this issue. In Android, anet has to be run/built with -ldflags "-checklinkname=0" to avoid this error: link: github.com/wlynxg/anet: invalid reference to net.zoneCache.
Additionally, a small patch is applied to enable TLS certificate requests, which are currently disabled in the Tailscale library. This can also be set up by go.work (this is useful when ts-proxy is used as library).
The latest Tailscale release has a bug ( tailscale/tailscale#18829 ), where tsnet can't connect to itself. It's already fixed but not released. This is fixed in ts-proxy binary release. See GitHub Actions configuration for detail.
- HTTP Proxy support
- SOCKS5 authentication