feat(remote): add --local-proxy to send server requests through the client

A reverse tunnel over the remote connection: the server's service traffic leaves through the client's own network. Only the client dials. Adds the tunnel-test command.
This commit is contained in:
imSp4rky
2026-10-21 17:09:37 -06:00
parent afaff8e070
commit 23614fd938
13 changed files with 1242 additions and 13 deletions
+20
View File
@@ -207,6 +207,7 @@ order the service used, then renumbers the episodes into the order you asked for
| Flag | Description |
|---|---|
| `--proxy` | Proxy URI, a country or location code resolved from configured providers, or `provider:region` (e.g. `nordvpn:ca`, `gluetun:us`, `protonvpn:de:berlin`, `controld:yul`). |
| `--local-proxy` | With `--remote`, send the server's service requests through your machine's own connection. Works with no other proxy option. Check it first with `unshackle tunnel-test`. See [Proxies & VPN](proxies-and-vpn.md#send-the-servers-requests-through-your-machine). |
| `--no-proxy` | Force-disable all proxy use. |
| `--no-proxy-download` | Bypass the proxy for **all downloads** (manifest, licence, and auth stay proxied). |
| `--proxy-download` | Use a different proxy for **all downloads**, in the same forms as `--proxy` (manifest, licence, and auth stay on `--proxy`). |
@@ -250,6 +251,7 @@ unshackle logs in to the service before the search. A service that declares a se
|---|---|
| `-p`, `--profile` | Profile for credentials and cookies. |
| `--proxy` | Proxy URI, country or location code, or `provider:region` (e.g. `controld:ca`). |
| `--local-proxy` | With `--remote`, send the server's search requests through your machine's own connection. Works with no other proxy option. |
| `--no-proxy` | Force-disable all proxy use. |
| `--remote` | Search on a remote unshackle server. The server logs in to the service. unshackle sends it your credentials, cookies and cache for the profile, and saves the cache that the server sends back. A service that searches with no login gets none of them. |
| `--local` | Search with the local service code, also when the config sets `remote: true` for the service. |
@@ -285,6 +287,24 @@ The export file can be a `mediaexport` file from `dl --export`, an export from a
---
## `tunnel-test`
Check `--local-proxy` before a real `--remote` run. The command finds the IP address that this
machine exits from, opens a tunnel to the server, and makes the server look up its exit IP address
through the tunnel. It stops at the first step that fails.
```
unshackle tunnel-test [--server NAME]
```
| Flag | Description |
|---|---|
| `--server` | Name of the remote server from `remote_services` config, if you configure more than one. |
See [Proxies & VPN](proxies-and-vpn.md#send-the-servers-requests-through-your-machine).
---
## `setup`
Install the external tools and make a first config.
+71 -1
View File
@@ -22,11 +22,12 @@ a query to a real proxy URL: [basic static proxies](#basic-static-proxies),
## The `--proxy` flag
Four options on the `dl` command control proxying at download time:
Five options on the `dl` command control proxying at download time:
| Option | Effect |
|---|---|
| `--proxy` | The proxy to use. Either an explicit URI, or a query that unshackle resolves against your configured providers. |
| `--local-proxy` | With `--remote`, send the server's service requests through your machine's own connection. Works with no other proxy option. See [Send the server's requests through your machine](#send-the-servers-requests-through-your-machine). |
| `--no-proxy` | Force **all** proxy use off. No providers are initialised and no proxy query is resolved. |
| `--no-proxy-download` | Use the proxy for the manifest, licence, and authentication, but bypass it for the **downloads** themselves. |
| `--proxy-download` | Use `--proxy` for the manifest, licence, and authentication, and a different proxy for the **downloads**. Takes the same forms as `--proxy`. |
@@ -204,6 +205,75 @@ sees your own IP, but the service does not.
A `socks5://` proxy makes the DNS lookup of each host on your machine and gives no warning.
Use `socks5h://` to make the proxy do the DNS lookups too.
### Send the server's requests through your machine
With `--remote`, the server sends the service requests, and they leave from the server's own
connection. Add `--local-proxy` to send them through your machine's connection instead:
```shell
unshackle dl --remote --local-proxy EXAMPLE 81234567
```
A VPN app that covers your whole machine then also covers the server's requests, so the
service sees your VPN's IP address. `--local-proxy` needs `--remote` (or a service with
`remote: true`), and it works with no other proxy option: unshackle stops if you also give
`--proxy`, `--no-proxy`, `--proxy-download` or `--no-proxy-download`. A proxy option from the `dl`
config defaults does not count: `--local-proxy` turns it off for the run.
A `--proxy` on `localhost` or a loopback address, such as the local port of a VPN app, stops a
`--remote` run with `That proxy is on your machine, so --remote cannot use it`. Connect the VPN
app for the whole machine, then use `--local-proxy` without `--proxy`.
#### Test it first
`unshackle tunnel-test` checks the route before a real run. Add `--server <name>` to test a
server other than the default one:
```shell
unshackle tunnel-test
```
It does three steps, and it stops at the first one that fails:
1. It looks up the IP address that your machine exits from.
2. It opens a tunnel to the server.
3. It makes the server look up its exit IP address through the tunnel. That address must be
the same as in step 1, or in the same country when one lookup used IPv4 and the other IPv6.
It fails when the lookup left from the server's own address. It also shows how long one
lookup takes.
#### How the tunnel works
1. The client opens a WebSocket on the server, on the same host and port as the other
remote session requests. Only a client opens a tunnel. The server never connects to
a host for a client, so a tunnel gives no access to the server's network.
2. The server gives the service a SOCKS5 proxy on its loopback address, with a username and
password for that tunnel only. Another API key cannot use it.
3. The server sends each connection that the service opens through the tunnel. The client
connects to the host and relays the bytes.
The client logs `The server sends its requests through your connection on this machine`. You
do not configure ports: the server picks a free one, and your
machine opens none, because the client opens the connection to the server. A NAT router, a
firewall, or a Cloudflare tunnel in front of the server does not stop it.
The service traffic stays encrypted from the server to the service, so the client relays only
encrypted bytes. The client refuses to connect to `localhost`, and to a host name or IP address
that resolves only to a loopback, private or link-local address, so the server cannot reach
your local network.
!!! note "Each request crosses the tunnel twice"
A request from the server goes to your machine and then to the service, so it takes
longer than a request that the server sends directly. The segments do not go through the
tunnel: the client downloads them as before.
A service that uses a server account does not work with `--local-proxy`, because the server
logs in with its own account. If the tunnel drops, the client connects again, and a new request
from the server waits up to 10 seconds for it. A request that was in progress when the tunnel
dropped fails. The server closes a tunnel when its client has not connected for 60 seconds, and
the client then stops with `The tunnel to the server closed`. An API key can have 4 tunnels
open at once.
## Basic (static proxies)
The `Basic` proxy provider is pure static configuration, with no accounts and no network