I would like to present a project I have been working on called nTask to distribute tasks across different computers:
Table Of Contents
What is nTask Link to heading
nTask is a versatile program that uses API communications and WebSocket to distribute tasks, whether they are commands or programs, among different computers. The main idea behind nTask is to allow clients to send task requests to a manager, which then assigns these tasks to available workers. The workers execute the tasks and send the results back to the manager, which then stores the data in a database. Additionally, nTask can also send the output to a designated URL or API for further integration with other programs.
In this blog post, I will walk you through the process of installing, configuring, and using nTask with a practical example. If you need more information, you can visit the nTask GitHub repository:
Installation and Configuration Link to heading
To get started with nTask, I recommend using my preferred method, which involves using Docker Compose for the server and database installation, and a manual installation on a VPS for the worker. This setup allows for greater flexibility when it comes to adding new tools or dependencies to nTask workers in the future.
Installing and Configuring the Manager Link to heading
To install the manager component of nTask, follow these steps:
-
Install nTask:
go install github.com/r4ulcl/nTask@latest
-
Clone the nTask repository:
git clone github.com/r4ulcl/nTask
-
Generate a new SSL certificate by running the following command:
cd nTask bash generateCert.sh
This will create the necessary SSL certificate files.
-
Open the
docker-compose.yml
file and update the MySQL username and password.
version: '3.4'
services:
manager:
image: r4ulcl/ntask-manager
#build:
# context: .
# dockerfile: ./manager/Dockerfile
restart: unless-stopped
container_name: nTask_manager
ports:
- 8080:8080
depends_on:
- db
env_file: .env
command: manager --swagger --verbose --debug
volumes:
- ./manager.conf:/config/manager.conf
- ./ssh.conf:/config/ssh.conf
- ./output/:/config/output/
- ./certs/:/config/certs/
- ./ssh_key:/config/ssh_key
db:
image: mysql
command: --default-authentication-plugin=caching_sha2_password
restart: unless-stopped
#ports:
# - 3306:3306
environment:
MYSQL_ROOT_PASSWORD: your_password_root
MYSQL_USER: your_username
MYSQL_PASSWORD: your_password
MYSQL_DATABASE: manager
volumes:
- ./db:/var/lib/mysql
-
Edit the
manager.conf
file and make the following changes:- Update the
users
section with the OAuth credentials for each user. - Update the
workers
section with the OAuth key for the workers. You can generate multiple OAuth keys for different workers if needed. - Modify the
statusCheckSeconds
value to specify the time interval (in seconds) between each check of the workers. - Adjust the
StatusCheckDown
value to define the time, in seconds, to wait before permanently removing a worker from the database if it doesn’t respond. - Update the
dbUsername
anddbPassword
values to match the MySQL credentials specified in thedocker-compose.yml
file. - Optionally, set a
diskPath
to store the task execution information when it is completed.
- Update the
{
"users": {
"user1" : "WLJ2xVQZ5TXVw4qEznZDnmEEV",
"user2" : "WLJ2xVQZ5TXVw4qEznZDnmEE2",
"user3" : "WLJ2xVQZ5TXVw4qEznZDnmEE3"
},
"workers": {
"workers" : "IeH0vpYFz2Yol6RdLvYZz62TFMv5FF"
},
"statusCheckSeconds": 10,
"StatusCheckDown": 360,
"port": "8080",
"dbUsername" : "your_username",
"dbPassword" : "your_password",
"dbHost" : "db",
"dbPort" : "3306",
"dbDatabase" : "manager",
"diskPath": "./output",
"certFolder": "./certs/manager/"
}
Installing and Configuring the Worker Link to heading
To install the worker component of nTask, follow these steps:
-
Install Go on your client machine. You can use this script I created to automate the installation.
-
Once Go is installed, run the following command to download and install nTask:
go install github.com/r4ulcl/nTask@latest
-
Copy the
ca-cert.pem
file from the manager folder. -
Create the
worker.conf
file and update the following information:- Set the number of
iddleThreads
to specify the number of threads to run in parallel on this worker. - Specify the IP address and port of the manager in the
managerIP
andmanagerPort
fields. - Set the
managerOauthToken
to the OAuth token needed to connect to the manager. - Update the
insecureModules
andmodules
fields to define the custom modules you want to use in your tasks. - Set the
CA
config with the path toca-cert.pem
.
- Set the number of
{
"name": "",
"iddleThreads": 2,
"managerIP" : "nTask_manager",
"managerPort" : "8080",
"managerOauthToken": "IeH0vpYFz2Yol6RdLvYZz62TFMv5FF",
"CA": "./certs/ca-cert.pem",
"insecureModules": false,
"modules": {
"sleep": "/usr/bin/sleep",
"curl": "/usr/bin/curl",
"cat": "/usr/bin/cat",
"echo": "/usr/bin/echo",
"grep": "/usr/bin/grep",
"rm": "/usr/bin/rm",
"nmap": "nmap",
"nmapIPs": "bash ./worker/modules/nmapIPs.sh",
"touch": "/usr/bin/touch",
"exec": ""
}
}
Secure SSH Tunnel Configuration (Optional) Link to heading
For added security, you can use an SSH tunnel to access the manager without exposing the port to the internet. To do this, follow these steps:
- Create a
ssh.conf
file with the worker information using the following format:
{
"ipPort": {
"<IP1>" : "<PORT1>",
"<IP2>" : "<PORT2>"
},
"sshUsername": "root",
"privateKeyPath": "./ssh_key",
"privateKeyPassword": ""
}
Replace <IP1>
, <PORT1>
, <IP2>
, <PORT2>
, etc. with the actual IP addresses and ports of the workers.
-
Update the
docker-compose.yml
file to include thessh.conf
andssh_key
volumes:- ./ssh.conf:/config/ssh.conf - ~/.ssh/ssh_key:/config/ssh_key
This will ensure that the SSH configuration is shared with the Docker container.
Note: Make sure to replace
~/.ssh/ssh_key
with the actual path to your SSH private key file.With this configuration, the manager will establish an SSH connection with the workers and forward the local port
8080
for secure access without exposing it to the internet.
Usage examples Link to heading
Now that you have completed the installation and configuration steps, let’s dive into some usage examples using the scripts provided in the nTask repository.
Simple Example Link to heading
The first example uses the scriptExample.sh
script, which shows how to use a bash script as a module. This script executes the nmapIPs
module, which runs a bash script which execute an nmap
command with the -sn
option to scan for IPs and then applies a grep filter to extract only the relevant IPs.
In this script we have functions to send tasks by POST to the manager and functions to get tasks and wait for them to finish. First the variables are configured with the token, the nTask manager IP, etc.
# ...
# Define vars
## oauth token, IP, port, range to scan
oauthToken="WLJ2xVQZ5TXVw4qEznZDnmEE2"
nTaskIP="127.0.0.1"
nTaskPort="8080"
scanRange="127.0.0.1/28"
url="https://$nTaskIP:$nTaskPort"
# Array to store task IDs
task_ids=()
Once this is done you run the nmapIPs
module, which does an nmap ping only scan and returns the list of active IPs. And it waits for the task to run with its ID.
# Connect to Manager
## Send nmap ping only range
command="{\"module\": \"nmapIPs\", \"args\": \"$scanRange\"}"
task_data="{\"command\": [$command],\"priority\": 0}"
task_id=$(send_post_request "$url/task" "$oauthToken" "$task_data")
# add task_id to array
task_ids+=("$task_id")
echo task_ids: $task_ids
for task in "${task_ids[@]}"; do
echo "$task"
done
# Wait for task done
OUTPUTS=($(wait_tasks $url $oauthToken "${task_ids[@]}"))
# ...
Once this is done the result of the task is displayed.
As you can see in the output, the script successfully retrieves the list of IPs.
You can modify this script by changing the command in the following line (line 91):
command="{\"module\": \"curl\", \"args\": \"ipinfo.io\"}"
Advanced Example Link to heading
For a more advanced example, you can try the scriptExampleAdvanced.sh
script. This script builds upon the previous example by scanning each IP obtained from the first task using nmap
. This way, you can start with a range of IP addresses, filter out the up ones, and scan them using multiple workers.
So after getting the response from the first command we run the following to scan each IP separately.
# ...
# For each IP execute nmap again but complete as a task
for IP in `echo -e $OUTPUT` ; do
echo $IP
command="{\"module\": \"nmap\", \"args\": \"$IP\"}"
task_data="{\"command\": [$command],\"priority\": 0}"
task_id=$(send_post_request "$url/task" "$oauthToken" "$task_data")
echo task_ids: $task_id
# add task_id to array
task_ids+=("$task_id")
done
# Wait for task done
OUTPUTS=($(wait_tasks $url $oauthToken "${task_ids[@]}"))
# ...
Here we can see the output of the script:
Executing the Same Task in Multiple Workers Link to heading
In some scenarios, you may want to execute the same task in all or a specific list of workers. To demonstrate this functionality, you can use the scriptExample1command.sh
script. This script uses curl
to retrieve the public IP of each worker.
Basically the process is to get the workers that are connected and create a task for each of them.
# ...
WORKERS=$(get_workers "$url/worker" "$oauthToken")
echo "$WORKERS" | jq
# Get all workers and send the same task to each
for row in $(echo "${WORKERS}" | jq -r '.[] | @base64'); do
_jq() {
echo ${row} | base64 --decode | jq -r ${1}
}
NAME=$(_jq '.name')
command="{\"module\": \"curl\", \"args\": \"-s ipinfo.io/ip\"}"
task_data="{\"command\": [$command],\"priority\": 0, \"workerName\": \"$NAME\"}"
task_id=$(send_post_request "$url/task" "$oauthToken" "$task_data")
echo task_id $task_id
# add task_id to array
task_ids+=("$task_id")
done
# Wait for task done
OUTPUTS=($(wait_tasks $url $oauthToken "${task_ids[@]}"))
# ...
Here we can see the output of the script:
Future Plans Link to heading
In the near future, I plan to integrate nTask with the DigitalOcean API to enable seamless connections and automatic management of workers. Stay tuned for updates!