# sshuttle: a transparent proxy over ssh, without admin rights on the remote side

> sshuttle turns an ordinary ssh login into a routed tunnel for TCP and DNS. It is aimed at engineers who need to reach a remote network but cannot or will not run a real VPN endpoint there.

**sshuttle/sshuttle** — Transparent proxy server that works as a poor man's VPN.  Forwards over ssh.  Doesn't require admin.  Works with Linux and MacOS.  Supports DNS tunneling.

- Repository: https://github.com/sshuttle/sshuttle
- Stars: 13,580 · Forks: 795
- Language: Python
- License: LGPL-2.1
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/sshuttle-sshuttle

## The gap sshuttle fills between ssh port forwarding and a full VPN

The README frames the problem as a specific combination of constraints: your client is Linux, FreeBSD, MacOS or Windows; you can reach a remote network over ssh; you may not have admin access on that remote network; and there is no usable VPN there, or the existing one uses IPsec or PPTP. The alternative people usually reach for, openssh port forwarding, requires one forward per host and port, which does not scale past a handful of services. openssh's PermitTunnel is disabled by default on servers, and the README notes it does TCP-over-TCP, which it links to a performance discussion in the documentation. sshuttle's claim is that it is the only program solving that exact case. The audience is therefore narrow and practical: developers and operators who already hold ssh credentials and want the remote subnets to look local, without a server-side install or a configuration change on the far end.

## How the tunnel actually moves packets

sshuttle does not create a network interface the way a VPN client does. It runs a local process that intercepts traffic destined for the subnets you name, then ships that traffic through the existing ssh connection to a small Python program it starts on the remote side. That remote program opens the real outbound connections on your behalf, so from the remote network's point of view the traffic originates from the ssh host itself. The README states that sshuttle supports DNS tunneling, which means name resolution can travel the same path rather than leaking to your local resolver. Two consequences follow from this design. First, the remote side needs a Python interpreter, because sshuttle uploads and runs its helper there. Second, because the transport is ssh, the tunnel inherits ssh's behaviour: authentication, host key checking, and whatever the ssh server allows. The pyproject.toml lists no runtime dependencies, so the client is pure Python plus whatever the underlying firewall mechanism requires. The documentation's how-it-works page is the place to read about the TCP-over-TCP performance question the README links to.

## Installing sshuttle and routing a first subnet

The README does not carry install instructions itself. It points to the installation page of the documentation at sshuttle.readthedocs.io, and the package is published under the name sshuttle. The project metadata declares a Python requirement of >=3.10 and <4.0, so an older interpreter will refuse the package. The entry point is registered in pyproject.toml as sshuttle = "sshuttle.cmdline:main".

```toml
[project.scripts]
sshuttle = "sshuttle.cmdline:main"
```

Once installed, that entry point is on your PATH. A first real run needs the ssh destination and the subnets you want routed, plus sshuttle's own options for DNS handling; the README gives no verbatim command line, so check the documentation page for the exact option spelling before you rely on it. What you should see is sshuttle connecting, then reporting that it has set up its local interception and is ready. Traffic to the subnets you named then leaves through the ssh host. Sshuttle can also be run as a service and configured through a config management system, per the README, which links to an external write-up on that pattern.

## Where sshuttle is the wrong tool

The design has a hard boundary: it forwards TCP and DNS. Anything that needs UDP does not travel through it, so a VPN replacement for VoIP, QUIC-heavy clients, or a game server will disappoint. The remote side must be able to run the uploaded Python helper. On a hardened host with a restricted shell, no writable temp directory, or no Python at all, sshuttle cannot start, and the README's premise that you need no admin access on the remote network does not remove that requirement. Locally, sshuttle needs enough privilege to install its interception rules; the project is explicit that it does not require admin in the sense of a remote account, not that the client side is unprivileged. The README also concedes the TCP-over-TCP performance issue is real enough to link to a dedicated explanation, so latency-sensitive interactive work over a lossy link is a case to think about before committing. Finally, sshuttle is a per-session tool. If your ssh connection drops, the tunnel goes with it, which is a different operational model from a VPN daemon that reconnects.

## sshuttle against a plain ssh tunnel, and against a real VPN

The nearest alternative is the ssh tunnel you already have. An ssh -L forward is one listening port mapped to one destination host and port, configured in advance. sshuttle instead matches on destination subnets at the network layer, so any host and any TCP port inside a routed range works without a new forward, and DNS can be included. That is the whole difference in approach: static per-service port mapping versus dynamic routing by destination address. A conventional VPN such as WireGuard or OpenVPN takes a third approach, terminating a tunnel at a server that holds a routable address and a configured peer, which gives you UDP and a persistent interface but requires control of the server side. sshuttle deliberately trades that control away to avoid needing it. If you do have server-side control and need UDP or a stable always-on link, the VPN is the better fit; if you have only ssh and a set of subnets, sshuttle is the shorter path.

## Maintenance, upgrade cost and the LGPL-2.1 licence

The repository is not archived, and the last push was on 2026-09-21. Releases are infrequent rather than continuous: v1.3.0 in February 2025, v1.3.1 in March 2025, and v1.3.2 in August 2025. The declared Python range is 3.10 through 3.12 in the classifiers, with requires-python capping below 4.0, so a Python 3.13 or later environment is outside what pyproject.toml currently declares. Upgrading is a package upgrade with no runtime dependencies to reconcile, which keeps the cost low; the risk sits in the Python version ceiling and in any change to which local firewall method the tool selects on your platform. The licence is LGPL-2.1, and the classifiers describe it as LGPLv2 or later. That is a weak copyleft: if you redistribute sshuttle itself or a modified version, the licence terms attach to that code. Running it as a client to reach your own infrastructure is not distribution. This is a summary of what the repository states, not legal advice; get counsel if you plan to bundle or modify it.

## Conclusion

Adopt sshuttle when you have ssh access to a network and need TCP plus DNS routed through it without touching the remote configuration, and when a per-host ssh -L forward is too much bookkeeping. Do not adopt it if you need UDP, if the remote side forbids the Python interpreter it uploads, or if you need a persistent always-on tunnel that survives session loss without supervision. Before rolling it out, verify that the remote host has a Python interpreter available, that your local kernel supports the firewall method sshuttle picks, and which subnets and DNS resolver you intend to route.

## FAQ

### What is sshuttle used for?

It routes TCP traffic and DNS from your machine through an ssh connection to a remote network, so remote subnets behave as if they were local. The README positions it for cases where you have ssh access but no usable VPN on the far side.

### Is sshuttle safe?

The README does not make a security claim, and it gives no audit or threat model. What can be said is that traffic travels inside ssh, so it inherits ssh's authentication and host key checking, and that sshuttle runs a helper program on the remote host.

### Can I install sshuttle on Windows?

The README lists Windows among the supported client platforms, alongside Linux, FreeBSD and MacOS. It gives no Windows-specific install steps and defers installation to the documentation site.

### How do I install sshuttle on Ubuntu?

The README does not carry per-distribution instructions; it points to the installation page of the documentation. The package is named sshuttle, and pyproject.toml requires Python 3.10 or later and below 4.0.

### How does sshuttle differ from an ssh tunnel?

An ssh tunnel maps one local port to one destination host and port, configured in advance. sshuttle instead intercepts traffic by destination subnet, so any TCP port on any host inside the routed range works without a new forward, and DNS can be routed too.

## Sources

- [Issues](https://github.com/sshuttle/sshuttle/issues)
- [License: LGPL-2.1](https://github.com/sshuttle/sshuttle/blob/master/LICENSE)
- [README](https://github.com/sshuttle/sshuttle/blob/master/README.md)
- [Releases](https://github.com/sshuttle/sshuttle/releases)
- [sshuttle/sshuttle on GitHub](https://github.com/sshuttle/sshuttle)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sshuttle-sshuttle
