Skip to content

foxhackerzdevs/remote-exec-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Remote Exec Server & Client

License Python GitHub stars GitHub forks GitHub release (latest by date) GitHub all releases

Lightweight Python-based remote command execution system
One client script, multiple symlinks, BusyBox-style.

⚠️ WARNING
This software executes commands received over HTTP.
Never expose it directly to the public Internet without authentication, encryption, access controls, and proper isolation.

OverviewInstallationUsageSecurity ConsiderationsLicense


📖 Table of Contents


Overview

Remote Exec Server & Client is a minimal remote command execution framework written entirely with the Python standard library.

The project consists of:

  • server.py — receives HTTP requests and executes commands locally.
  • client.py — forwards command invocations and standard input to the server.
  • BusyBox-style symlink support — one client script can act as many commands depending on the name it is invoked under.

The design is intentionally lightweight, dependency-free, and easy to deploy.


🌱 Project Inspiration

The idea for Remote Exec Server & Client grew out of work on pari-gp-scripts, a collection of scripts for the PARI/GP number theory system.

While developing those scripts, I experimented with:

  • Symlink wrappers — one script acting as multiple commands, BusyBox‑style.
  • Lightweight tooling — keeping dependencies minimal and relying on the standard library.
  • Command forwarding — piping input into gp and other interpreters for quick execution.

These patterns sparked the realization that the same approach could be generalized: instead of just wrapping gp locally, why not design a framework where one client script can forward commands to a server over HTTP?

Thus, Remote Exec Server & Client was born — a minimal, dependency‑free system for remote command execution, inspired by the simplicity and flexibility of the PARI/GP scripting workflow.


Features

  • HTTP-based command forwarding
  • Standard input (stdin) forwarding
  • Command-line argument support
  • Real-time output streaming (chunked transfer encoding) — live progress bars and interactive output display correctly
  • BusyBox-style symlink invocation
  • Works with any executable installed on the server
  • No third-party dependencies
  • Cross-platform Python implementation
  • Minimal setup and deployment

Architecture

┌─────────────┐
│   Client    │
│  (symlink)  │
└──────┬──────┘
       │ HTTP POST
       ▼
┌─────────────┐
│   Server    │
│ server.py   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│ subprocess  │
│ execution   │
└─────────────┘
       │
       ▼
┌─────────────┐
│   Output    │
└─────────────┘

Visual Diagram

BusyBox-style Remote Exec Diagram


Requirements

  • Python 3.8+
  • Network connectivity between client and server

No external dependencies are required.


⚡ Quick Start

Start the server:

python server.py

Create a command symlink:

ln -s client.py gp

Execute a remote command:

echo "print(nextprime(100))" | ./gp -q

Installation

Server Setup

Copy server.py to the machine that will execute commands.

Run:

python server.py

Default listening address:

0.0.0.0:8000

Client Setup

Edit the server address:

host = "SERVER_IP:8000"

Make executable:

chmod +x client.py

Place in your PATH:

cp client.py ~/bin/

Create command aliases:

ln -s ~/bin/client.py ~/bin/gp
ln -s ~/bin/client.py ~/bin/python
ln -s ~/bin/client.py ~/bin/node

Each symlink name becomes the command executed remotely.


Configuration

Client

Set the server host:

host = "192.168.56.1:8000"

To enable HTTPS:

http.client.HTTPSConnection

instead of:

http.client.HTTPConnection

The server must also be configured for TLS.


Server

Bind only to localhost:

HTTPServer(("127.0.0.1", 8000), MyHandler)

Change port:

HTTPServer(("0.0.0.0", 9000), MyHandler)

Usage

Basic Execution

command_name [arguments]

With Standard Input

echo "input data" | command_name [arguments]

Using Symlinks

ln -s client.py python
ln -s client.py node
ln -s client.py gp

The invoked name determines the command sent to the server.


Protocol

The communication protocol is intentionally simple.

Request

POST /python script.py arg1 arg2 HTTP/1.1
Host: server:8000
Content-Type: text/plain

Request body:

stdin data goes here

Server Processing

cmd_parts = shlex.split(raw_path)
process = subprocess.Popen(cmd_parts, stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.stdin.write(stdin_data)
process.stdin.close()  # signal EOF to the subprocess

Output is streamed to the client line by line as the subprocess produces it, using HTTP chunked transfer encoding — rather than waiting for the process to exit and sending the full output at once.


Response

The response uses Transfer-Encoding: chunked. Each line of stdout is sent as a separate chunk as soon as it's produced, so long-running or interactive commands (e.g. progress bars) display in real time on the client rather than appearing all at once at the end.

Success:

stdout output (streamed line by line)

Failure (appended as a final chunk if the process exits non-zero):

Error:
stderr output

Examples

Remote PARI/GP

echo "print(nextprime(100))" | gp -q

Remote Python

echo "print('Hello World')" | python

Remote Node.js

echo "console.log('hello from node')" | node

Pass Arguments

echo "hello" | python script.py arg1 arg2

Security Considerations

This project provides remote command execution capability and should be treated accordingly.

Risks

  • Arbitrary command execution
  • Remote code execution (RCE)
  • Unauthorized access
  • Resource exhaustion
  • Data exposure

Recommended Protections

Command Whitelisting

ALLOWED = {"python", "gp", "node"}

if cmd_parts[0] not in ALLOWED:
    output = f"Command not allowed: {cmd_parts[0]}"
    return

Network Restrictions

  • VPN access only
  • SSH tunnels
  • Firewall allowlists
  • Private networks

Authentication

Implement one or more of:

  • API keys
  • Bearer tokens
  • Mutual TLS
  • Basic authentication

Isolation

Run commands:

  • Inside Docker containers
  • Inside restricted user accounts
  • Inside sandboxes

Encryption

Use HTTPS/TLS whenever traffic crosses untrusted networks.


Troubleshooting

Connection Refused

Verify:

python server.py

Check:

  • Server is running
  • Correct IP address
  • Correct port
  • Firewall configuration

Command Not Found

Verify the executable exists:

which python
which node
which gp

Empty Output

Check:

  • Server logs
  • Command stdout/stderr behavior
  • Input handling

Wrong Host

Verify:

host = "SERVER_IP:8000"

Project Structure

.
├── client.py
├── server.py
├── README.md
├── LICENSE
├── CONTRIBUTING.md
└── docs/
    └── diagram.png

Limitations

Current implementation intentionally remains minimal.

  • No authentication
  • No TLS support by default
  • No concurrency (single request handled at a time)
  • No request validation
  • No rate limiting
  • No audit logging
  • No file transfer support

Future Improvements

  • HTTPS/TLS support
  • API-key authentication
  • Mutual TLS
  • Built-in command whitelists
  • Async request handling
  • Docker deployment
  • Audit logging
  • Request signing
  • Rate limiting
  • File upload/download support

Contributing

Contributions are welcome.

Potential contribution areas:

  • Security enhancements
  • Protocol improvements
  • Testing
  • Documentation
  • Containerization
  • Performance optimization

Feel free to open issues, submit pull requests, or fork the project.

See CONTRIBUTING.md for guidelines on documentation, security, development, and the contribution flow.


License

SPDX-License-Identifier: MIT

This project is licensed under the MIT License — see the repository LICENSE file for the full text:

LICENSE


🔗 See also

  • PARI/GP Scripts
    A collection of Bash wrappers for PARI/GP number theory experiments that inspired the design of this project.

About

Lightweight HTTP server and client pair for remote command execution. Inspired by the BusyBox model: one client script invoked under multiple names via symlinks, each forwarding to a different command on the server. Original use case: run gp (PARI/GP) remotely from a machine that doesn’t have it installed.

Topics

Resources

License

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages