gcli-control 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gcli_control-0.1.0/PKG-INFO +143 -0
- gcli_control-0.1.0/README.md +114 -0
- gcli_control-0.1.0/gcli/__init__.py +6 -0
- gcli_control-0.1.0/gcli/__main__.py +104 -0
- gcli_control-0.1.0/gcli/client.py +362 -0
- gcli_control-0.1.0/gcli/colors.py +85 -0
- gcli_control-0.1.0/gcli/crypto.py +51 -0
- gcli_control-0.1.0/gcli/host.py +215 -0
- gcli_control-0.1.0/gcli/npoint.py +60 -0
- gcli_control-0.1.0/gcli/protocol.py +246 -0
- gcli_control-0.1.0/gcli/utils.py +240 -0
- gcli_control-0.1.0/gcli_control.egg-info/PKG-INFO +143 -0
- gcli_control-0.1.0/gcli_control.egg-info/SOURCES.txt +18 -0
- gcli_control-0.1.0/gcli_control.egg-info/dependency_links.txt +1 -0
- gcli_control-0.1.0/gcli_control.egg-info/entry_points.txt +2 -0
- gcli_control-0.1.0/gcli_control.egg-info/requires.txt +1 -0
- gcli_control-0.1.0/gcli_control.egg-info/top_level.txt +1 -0
- gcli_control-0.1.0/pyproject.toml +46 -0
- gcli_control-0.1.0/setup.cfg +4 -0
- gcli_control-0.1.0/tests/test_integration.py +241 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gcli-control
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Remote access tool via npoint.io - encrypted command relay using AES-256-GCM
|
|
5
|
+
Author: gcli contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gcli-control/gcli
|
|
8
|
+
Project-URL: Repository, https://github.com/gcli-control/gcli
|
|
9
|
+
Project-URL: Issues, https://github.com/gcli-control/gcli/issues
|
|
10
|
+
Keywords: remote-access,npoint,encrypted,ssh,aes256
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: System :: Systems Administration
|
|
25
|
+
Classifier: Topic :: Security :: Cryptography
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
Requires-Dist: cryptography>=41.0
|
|
29
|
+
|
|
30
|
+
# gcli
|
|
31
|
+
|
|
32
|
+
Remote access tool via [npoint.io](https://npoint.io) — encrypted command relay using AES-256-GCM.
|
|
33
|
+
|
|
34
|
+
## How It Works
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
┌──────────┐ commands ┌─────────────┐ commands ┌──────────┐
|
|
38
|
+
│ gcli ssh │ ───────────────> │ npoint.io │ ───────────────> │gcli host │
|
|
39
|
+
│ (client) │ <─────────────── │ (JSON bin) │ <─────────────── │ (daemon) │
|
|
40
|
+
└──────────┘ results └─────────────┘ results └──────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
1. **`gcli host`** starts a background daemon that polls npoint.io for encrypted commands
|
|
44
|
+
2. **`gcli ssh`** connects interactively, sends encrypted commands, and polls for results
|
|
45
|
+
3. All payloads are encrypted with **AES-256-GCM** — the password never leaves your machine
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
### Install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install cryptography
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Host (on the remote machine)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Start the daemon (runs in background)
|
|
59
|
+
python -m gcli host --password MySecret123
|
|
60
|
+
|
|
61
|
+
# Or run in foreground for debugging
|
|
62
|
+
python -m gcli host --password MySecret123 --foreground
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Client (on your local machine)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Connect to the host
|
|
69
|
+
python -m gcli ssh --password MySecret123
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Stop the host
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
python -m gcli stop
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## SSH Commands
|
|
79
|
+
|
|
80
|
+
Once connected, you have a full interactive REPL:
|
|
81
|
+
|
|
82
|
+
| Command | Description |
|
|
83
|
+
|---------|-------------|
|
|
84
|
+
| Any text | Execute shell command on remote host |
|
|
85
|
+
| `:help` | Show available commands |
|
|
86
|
+
| `:info` | Show remote system info (hostname, OS, user, IP) |
|
|
87
|
+
| `:ping` | Ping remote host and show latency |
|
|
88
|
+
| `:upload <local> <remote>` | Upload a file to the remote host |
|
|
89
|
+
| `:download <remote> <local>` | Download a file from the remote host |
|
|
90
|
+
| `:timeout <seconds>` | Set exec command timeout |
|
|
91
|
+
| `:history` | Show recent command history |
|
|
92
|
+
| `:exit` | Disconnect and close session |
|
|
93
|
+
|
|
94
|
+
## Security
|
|
95
|
+
|
|
96
|
+
- **AES-256-GCM** encryption with PBKDF2 key derivation (600K iterations)
|
|
97
|
+
- Password is never transmitted — only encrypted payloads flow through npoint.io
|
|
98
|
+
- Each message gets a unique random nonce (prevents identical plaintext detection)
|
|
99
|
+
- Built-in tamper detection (GCM authentication tag)
|
|
100
|
+
|
|
101
|
+
## Cross-Platform
|
|
102
|
+
|
|
103
|
+
| Platform | Background Detach | Process Management |
|
|
104
|
+
|----------|-------------------|-------------------|
|
|
105
|
+
| Windows | `CREATE_NO_WINDOW` subprocess | `tasklist` / `taskkill` |
|
|
106
|
+
| Linux | Double-fork + `setsid` | `kill` / `os.kill` |
|
|
107
|
+
| macOS | Double-fork + `setsid` | `kill` / `os.kill` |
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Custom npoint bin (both host and client must use the same bin)
|
|
113
|
+
python -m gcli host --password MySecret --bin YOUR_NPOINT_BIN_ID
|
|
114
|
+
python -m gcli ssh --password MySecret --bin YOUR_NPOINT_BIN_ID
|
|
115
|
+
|
|
116
|
+
# Adjust polling speed (default: 2s host, 1s client)
|
|
117
|
+
python -m gcli host --password MySecret --poll-interval 1.0
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Architecture
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
gcli/
|
|
124
|
+
├── __main__.py # CLI entry point (argparse)
|
|
125
|
+
├── __init__.py
|
|
126
|
+
├── crypto.py # AES-256-GCM encrypt/decrypt (PBKDF2 key derivation)
|
|
127
|
+
├── npoint.py # npoint.io API wrapper with retry logic
|
|
128
|
+
├── protocol.py # Document structure, read/write, race-condition safe appends
|
|
129
|
+
├── host.py # Daemon: poll → decrypt → execute → encrypt → respond
|
|
130
|
+
├── client.py # SSH REPL: send → poll → display (tab completion)
|
|
131
|
+
├── utils.py # PID management, process detach, command execution
|
|
132
|
+
└── colors.py # Cross-platform terminal colours (Win/Linux/macOS)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Requirements
|
|
136
|
+
|
|
137
|
+
- Python 3.8+
|
|
138
|
+
- `cryptography` package
|
|
139
|
+
- Internet connection (for npoint.io)
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# gcli
|
|
2
|
+
|
|
3
|
+
Remote access tool via [npoint.io](https://npoint.io) — encrypted command relay using AES-256-GCM.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌──────────┐ commands ┌─────────────┐ commands ┌──────────┐
|
|
9
|
+
│ gcli ssh │ ───────────────> │ npoint.io │ ───────────────> │gcli host │
|
|
10
|
+
│ (client) │ <─────────────── │ (JSON bin) │ <─────────────── │ (daemon) │
|
|
11
|
+
└──────────┘ results └─────────────┘ results └──────────┘
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
1. **`gcli host`** starts a background daemon that polls npoint.io for encrypted commands
|
|
15
|
+
2. **`gcli ssh`** connects interactively, sends encrypted commands, and polls for results
|
|
16
|
+
3. All payloads are encrypted with **AES-256-GCM** — the password never leaves your machine
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install cryptography
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Host (on the remote machine)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Start the daemon (runs in background)
|
|
30
|
+
python -m gcli host --password MySecret123
|
|
31
|
+
|
|
32
|
+
# Or run in foreground for debugging
|
|
33
|
+
python -m gcli host --password MySecret123 --foreground
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Client (on your local machine)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Connect to the host
|
|
40
|
+
python -m gcli ssh --password MySecret123
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Stop the host
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python -m gcli stop
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## SSH Commands
|
|
50
|
+
|
|
51
|
+
Once connected, you have a full interactive REPL:
|
|
52
|
+
|
|
53
|
+
| Command | Description |
|
|
54
|
+
|---------|-------------|
|
|
55
|
+
| Any text | Execute shell command on remote host |
|
|
56
|
+
| `:help` | Show available commands |
|
|
57
|
+
| `:info` | Show remote system info (hostname, OS, user, IP) |
|
|
58
|
+
| `:ping` | Ping remote host and show latency |
|
|
59
|
+
| `:upload <local> <remote>` | Upload a file to the remote host |
|
|
60
|
+
| `:download <remote> <local>` | Download a file from the remote host |
|
|
61
|
+
| `:timeout <seconds>` | Set exec command timeout |
|
|
62
|
+
| `:history` | Show recent command history |
|
|
63
|
+
| `:exit` | Disconnect and close session |
|
|
64
|
+
|
|
65
|
+
## Security
|
|
66
|
+
|
|
67
|
+
- **AES-256-GCM** encryption with PBKDF2 key derivation (600K iterations)
|
|
68
|
+
- Password is never transmitted — only encrypted payloads flow through npoint.io
|
|
69
|
+
- Each message gets a unique random nonce (prevents identical plaintext detection)
|
|
70
|
+
- Built-in tamper detection (GCM authentication tag)
|
|
71
|
+
|
|
72
|
+
## Cross-Platform
|
|
73
|
+
|
|
74
|
+
| Platform | Background Detach | Process Management |
|
|
75
|
+
|----------|-------------------|-------------------|
|
|
76
|
+
| Windows | `CREATE_NO_WINDOW` subprocess | `tasklist` / `taskkill` |
|
|
77
|
+
| Linux | Double-fork + `setsid` | `kill` / `os.kill` |
|
|
78
|
+
| macOS | Double-fork + `setsid` | `kill` / `os.kill` |
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Custom npoint bin (both host and client must use the same bin)
|
|
84
|
+
python -m gcli host --password MySecret --bin YOUR_NPOINT_BIN_ID
|
|
85
|
+
python -m gcli ssh --password MySecret --bin YOUR_NPOINT_BIN_ID
|
|
86
|
+
|
|
87
|
+
# Adjust polling speed (default: 2s host, 1s client)
|
|
88
|
+
python -m gcli host --password MySecret --poll-interval 1.0
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Architecture
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
gcli/
|
|
95
|
+
├── __main__.py # CLI entry point (argparse)
|
|
96
|
+
├── __init__.py
|
|
97
|
+
├── crypto.py # AES-256-GCM encrypt/decrypt (PBKDF2 key derivation)
|
|
98
|
+
├── npoint.py # npoint.io API wrapper with retry logic
|
|
99
|
+
├── protocol.py # Document structure, read/write, race-condition safe appends
|
|
100
|
+
├── host.py # Daemon: poll → decrypt → execute → encrypt → respond
|
|
101
|
+
├── client.py # SSH REPL: send → poll → display (tab completion)
|
|
102
|
+
├── utils.py # PID management, process detach, command execution
|
|
103
|
+
└── colors.py # Cross-platform terminal colours (Win/Linux/macOS)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Requirements
|
|
107
|
+
|
|
108
|
+
- Python 3.8+
|
|
109
|
+
- `cryptography` package
|
|
110
|
+
- Internet connection (for npoint.io)
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
gcli — remote access tool via npoint.io.
|
|
3
|
+
|
|
4
|
+
Commands:
|
|
5
|
+
gcli host [--password P] [--bin ID] [--poll-interval N]
|
|
6
|
+
gcli ssh [--password P] [--bin ID]
|
|
7
|
+
gcli stop [--bin ID]
|
|
8
|
+
"""
|
|
9
|
+
import argparse
|
|
10
|
+
import sys
|
|
11
|
+
import getpass
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
from .host import start_daemon, stop_daemon, DEFAULT_BIN_ID, DEFAULT_POLL
|
|
15
|
+
from .client import SSHSession
|
|
16
|
+
from .colors import banner, info, error
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger("gcli")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def cmd_host(args):
|
|
22
|
+
"""Start the gcli host daemon."""
|
|
23
|
+
password = args.password
|
|
24
|
+
if not password:
|
|
25
|
+
password = getpass.getpass("Password: ")
|
|
26
|
+
|
|
27
|
+
print(info(f"[gcli] Starting host daemon (bin={args.bin})..."))
|
|
28
|
+
start_daemon(
|
|
29
|
+
password=password,
|
|
30
|
+
bin_id=args.bin,
|
|
31
|
+
poll_interval=args.poll_interval,
|
|
32
|
+
foreground=args.foreground,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def cmd_ssh(args):
|
|
37
|
+
"""Connect to a remote gcli host."""
|
|
38
|
+
password = args.password
|
|
39
|
+
if not password:
|
|
40
|
+
password = getpass.getpass("Password: ")
|
|
41
|
+
|
|
42
|
+
print(banner())
|
|
43
|
+
session = SSHSession(
|
|
44
|
+
password=password,
|
|
45
|
+
bin_id=args.bin,
|
|
46
|
+
)
|
|
47
|
+
session.repl()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def cmd_stop(args):
|
|
51
|
+
"""Stop a running gcli daemon."""
|
|
52
|
+
stop_daemon(bin_id=args.bin)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main():
|
|
56
|
+
parser = argparse.ArgumentParser(
|
|
57
|
+
prog="gcli",
|
|
58
|
+
description="Remote access tool via npoint.io — encrypted command relay",
|
|
59
|
+
)
|
|
60
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
61
|
+
|
|
62
|
+
# ---- gcli host ----
|
|
63
|
+
host_parser = subparsers.add_parser("host", help="Start the background host daemon")
|
|
64
|
+
host_parser.add_argument("-p", "--password", default=None, help="Encryption password")
|
|
65
|
+
host_parser.add_argument("-b", "--bin", default=DEFAULT_BIN_ID, help="npoint.io bin ID")
|
|
66
|
+
host_parser.add_argument("--poll-interval", type=float, default=DEFAULT_POLL,
|
|
67
|
+
help="Poll interval in seconds (default: 2.0)")
|
|
68
|
+
host_parser.add_argument("--foreground", action="store_true",
|
|
69
|
+
help="Run in foreground (don't detach)")
|
|
70
|
+
|
|
71
|
+
# ---- gcli ssh ----
|
|
72
|
+
ssh_parser = subparsers.add_parser("ssh", help="Connect to a remote gcli host")
|
|
73
|
+
ssh_parser.add_argument("-p", "--password", default=None, help="Encryption password")
|
|
74
|
+
ssh_parser.add_argument("-b", "--bin", default=DEFAULT_BIN_ID, help="npoint.io bin ID")
|
|
75
|
+
|
|
76
|
+
# ---- gcli stop ----
|
|
77
|
+
stop_parser = subparsers.add_parser("stop", help="Stop the host daemon")
|
|
78
|
+
stop_parser.add_argument("-b", "--bin", default=DEFAULT_BIN_ID, help="npoint.io bin ID")
|
|
79
|
+
|
|
80
|
+
args = parser.parse_args()
|
|
81
|
+
|
|
82
|
+
if not args.command:
|
|
83
|
+
print(banner())
|
|
84
|
+
parser.print_help()
|
|
85
|
+
sys.exit(1)
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
if args.command == "host":
|
|
89
|
+
print(banner())
|
|
90
|
+
cmd_host(args)
|
|
91
|
+
elif args.command == "ssh":
|
|
92
|
+
cmd_ssh(args)
|
|
93
|
+
elif args.command == "stop":
|
|
94
|
+
cmd_stop(args)
|
|
95
|
+
except KeyboardInterrupt:
|
|
96
|
+
print(f"\n{error('[gcli] Interrupted.')}")
|
|
97
|
+
sys.exit(130)
|
|
98
|
+
except Exception as e:
|
|
99
|
+
logger.error("Fatal error: %s", e)
|
|
100
|
+
sys.exit(1)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
if __name__ == "__main__":
|
|
104
|
+
main()
|