Metadata-Version: 2.4
Name: ssh-tunnel-gateway
Version: 0.1.6
Summary: SSH tunnel server + agent with reverse port forwarding
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.29
Requires-Dist: requests>=2.31
Requires-Dist: cryptography>=41

# ssh-tunnel-gateway

Single Python package that ships both the server and agent CLIs.

## Install

On the gateway server host:

```bash
pip install ssh-tunnel-gateway
```

On each agent host:

```bash
pip install ssh-tunnel-gateway
```

## Quick Start (ProxyJump)

1. On the gateway server host, start server:

```bash
API_KEY="change-me" ssh-tunnel-server
```

With default public reverse bind (`AGENT_REVERSE_BIND_HOST=0.0.0.0`), gateway `sshd_config` must include:
- `AllowTcpForwarding remote`
- `GatewayPorts clientspecified`

2. On the agent host, start agent:

```bash
ssh-tunnel-agent --api-key change-me --endpoint http://<gateway_host>:12000
```

3. Get `port_b` from the agent side:
- Foreground mode prints a log line with `port_b`.
- Foreground logs also print:
  - `ssh_user`: tunnel login user returned by server.
  - `jump_user`: ProxyJump user returned by server.
  - `agent_user_hint`: defaults to local `$USER` on the agent host.
- Session file is always written to `${STATE_DIR}/session.json` (default `./data/session.json`):

```bash
cat ./data/session.json
```

Get only `port_b`:

```bash
python3 -c 'import json; print(json.load(open("./data/session.json"))["port_b"])'
```

4. Add user SSH config (`~/.ssh/config`):

```sshconfig
Host GWServer
    HostName <gateway_public_ip_or_dns>
    User <gateway_ssh_user>
    Port 22

Host AgentServer
    HostName localhost
    User <agent_ssh_user>
    Port <port_b_from_agent_session_json>
    ProxyJump GWServer
```

5. Connect:

```bash
ssh AgentServer
```

## Server Usage

Foreground:

```bash
API_KEY="change-me" ssh-tunnel-server
```

Systemd mode:

```bash
API_KEY="change-me" ssh-tunnel-server -d
```

## Agent Usage

Foreground:

```bash
ssh-tunnel-agent --api-key change-me --endpoint http://server:12000
```

If `--agent-id` is not provided, agent generates a UUID once and caches it locally for future restarts.
Agent writes current session info (including `port_b`) to `${STATE_DIR}/session.json` by default.

Default reverse bind host is `0.0.0.0` (public bind on gateway).
Use `--reverse-bind-host 127.0.0.1` if you want loopback-only bind for strict bastion usage.
If not set, agent follows the server-provided reverse bind host.

Systemd mode:

```bash
ssh-tunnel-agent -d --api-key change-me --endpoint http://server:12000
```

In `-d` mode, register/startup failures exit immediately so systemd can restart the unit.

## Systemd Usage

Server unit (`/etc/systemd/system/ssh-tunnel-server.service`):

```ini
[Unit]
Description=ssh-tunnel-gateway server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=gw-tunnel
WorkingDirectory=/opt/ssh-tunnel
EnvironmentFile=/etc/ssh-tunnel/server.env
ExecStart=/usr/local/bin/ssh-tunnel-server -d
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Example server env (`/etc/ssh-tunnel/server.env`):

```bash
API_KEY=change-me
SERVER_PORT=12000
SSH_USER=gw-tunnel
SSH_JUMP_USER=li
SSH_PUBLIC_HOST=gateway.example.com
AUTHORIZED_KEYS_PATH=/home/gw-tunnel/.ssh/authorized_keys
AGENT_REVERSE_BIND_HOST=0.0.0.0
```

Agent unit (`/etc/systemd/system/ssh-tunnel-agent.service`):

```ini
[Unit]
Description=ssh-tunnel-gateway agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/ssh-tunnel
EnvironmentFile=/etc/ssh-tunnel/agent.env
ExecStart=/usr/local/bin/ssh-tunnel-agent -d
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Example agent env (`/etc/ssh-tunnel/agent.env`):

```bash
API_KEY=change-me
API_URL=http://<gateway_host>:12000
SSH_HOST=<gateway_host>
SSH_PORT=22
LOCAL_TARGET_HOST=127.0.0.1
LOCAL_TARGET_PORT=22
```

Enable and start:

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now ssh-tunnel-server
sudo systemctl enable --now ssh-tunnel-agent
```
