A comprehensive Go-based worker application for Docker containers that provides HTTP REST API and Socket.IO capabilities for file system operations, network utilities, and shell command execution.
- List Directory: Get files and directories in a path
- Create File: Create new files with content
- Delete: Remove files or directories
- Rename: Rename files or directories
- Copy: Copy files or directories
- Move: Move files or directories
- Read File: Read file contents
- Write File: Write content to files
- Create Directory: Create new directories
- Real-time File Watching: Monitor file changes via Socket.IO
- Download Files: Download files from URLs to specified paths
- Port Monitoring: Real-time monitoring of listening ports with change detection
- Current Port Status: Get currently listening ports for TCP/UDP protocols
- Command Execution: Execute shell commands with output capture
- Interactive Shells: Spawn interactive shell sessions via Socket.IO
- Real-time I/O: Send input and receive output in real-time
- Session Management: Manage multiple concurrent shell sessions
- Bearer Token Authentication: All API endpoints and Socket.IO connections require authentication
- Environment-based Configuration: Auth Token and other settings configurable via environment variables
- Debug Mode Control: Production-ready logging controls
- Build the Docker image:
docker build -t ccw .- Run the container with authentication:
# Production mode
docker run -d -p 8080:8080 -e AUTH_TOKEN="your-secure-token" --name worker ccw
# Debug mode
docker run -d -p 8080:8080 -e AUTH_TOKEN="your-secure-token" --name worker ccw --debug- Install dependencies:
go mod tidy- Set environment variables and run:
# Set required token
export AUTH_TOKEN="your-secure-token"
# Production mode (default)
go run *.go
# Debug mode
go run *.go --debugAll API endpoints (except /health) and Socket.IO connections require authentication using Bearer tokens.
AUTH_TOKEN: Required. The token used for Bearer token authentication
Include the Bearer token in the Authorization header:
curl -H "Authorization: Bearer your-secure-token" \
http://localhost:8080/api/fs/listdir?path=/homeInclude the token as a query parameter when connecting:
const socket = io('http://localhost:8080', {
query: {
token: 'your-secure-token'
}
});Authentication Responses:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: Token format incorrect (should be
Bearer <token>)
--debug: Enable debug mode with verbose logging (default: production mode)
AUTH_TOKEN: Required. Authentication token for API accessPORT: Server port (default: 8080)
Production Mode (default):
- Minimal logging output
- Optimized performance
- Set automatically when
--debugflag is not present
Debug Mode (--debug flag):
- Verbose request/response logging
- Detailed error information
- Development-friendly output
All endpoints below require the Authorization: Bearer <token> header unless otherwise specified.
List files and directories in a path.
- Query Parameters:
path(required) - Example:
curl -H "Authorization: Bearer your-secure-token" \
"http://localhost:8080/api/fs/listdir?path=/home/user"Create a new file.
curl -X POST http://localhost:8080/api/fs/create \
-H "Authorization: Bearer your-secure-token" \
-H "Content-Type: application/json" \
-d '{"path":"/path/to/file.txt","content":"file content"}'Delete a file or directory.
- Query Parameters:
path(required)
Rename a file or directory.
{
"old_path": "/old/path",
"new_path": "/new/path"
}Copy a file or directory.
{
"source": "/source/path",
"destination": "/destination/path"
}Move a file or directory.
{
"source": "/source/path",
"destination": "/destination/path"
}Read file contents.
- Query Parameters:
path(required)
Write content to a file.
{
"path": "/path/to/file.txt",
"content": "new content"
}Create a directory.
{
"path": "/path/to/directory"
}Download a file from URL.
curl -X POST http://localhost:8080/api/net/download \
-H "Authorization: Bearer your-secure-token" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/file.zip","path":"/local/path/file.zip"}'Get currently listening ports on the system.
- Query Parameters:
protocol(optional):tcp,udp, orboth(default:tcp)interface(optional): IP address to filter by, oranyfor all interfaces (default:127.0.0.1)
- Example:
curl -H "Authorization: Bearer your-secure-token" \
"http://localhost:8080/api/net/ports?protocol=both&interface=any"Response Example:
{
"success": true,
"message": "Current listening ports retrieved",
"data": {
"ports": [22, 80, 443, 8080],
"protocol": "both",
"interface": "any",
"count": 4
}
}Execute a shell command.
curl -X POST http://localhost:8080/api/shell/exec \
-H "Authorization: Bearer your-secure-token" \
-H "Content-Type: application/json" \
-d '{"command":"ls -la","args":["-la"],"env":{"VAR":"value"},"workdir":"/home/user","timeout":30}'Health check endpoint (no authentication required).
curl http://localhost:8080/healthSocket.IO connections must include the authentication token:
const socket = io('http://localhost:8080', {
query: {
token: 'your-secure-token'
}
});
// Handle authentication errors
socket.on('connect_error', (error) => {
console.error('Connection failed:', error.message);
});fs:watch- Start watching a directory for changes- Data:
"/path/to/watch"
- Data:
fs:unwatch- Stop watching a directory- Data:
"/path/to/unwatch"
- Data:
fs:change- File system change detectedfs:watching- Confirmation that watching startedfs:unwatched- Confirmation that watching stoppedfs:error- File system operation error
net:monitor:start- Start real-time port monitoring- Data:
protocol, interface, interval - Example:
socket.emit('net:monitor:start', 'both', '127.0.0.1', 2)
- Data:
net:monitor:stop- Stop port monitoring- Data:
protocol, interface - Example:
socket.emit('net:monitor:stop', 'both', '127.0.0.1')
- Data:
net:monitor:started- Port monitoring started- Data:
{ "protocol": "both", "interface": "127.0.0.1", "interval": 2, "timestamp": 1640995200 }
- Data:
net:monitor:stopped- Port monitoring stoppednet:port:changes- Port status changes detected- Data:
{ "changes": [ { "port": 8080, "status": "opened", "protocol": "tcp", "interface": "127.0.0.1", "timestamp": 1640995200 } ], "timestamp": 1640995200 }
- Data:
net:error- Network operation error
shell:spawn- Spawn interactive shell- Data:
"/bin/bash"(command)
- Data:
shell:input- Send input to shell- Data:
{sessionId: "uuid", input: "command\n"}
- Data:
shell:kill- Terminate shell session- Data:
"session-uuid"
- Data:
shell:spawned- Shell session createdshell:output- Shell output (stdout/stderr)shell:exit- Shell session endedshell:killed- Shell session terminatedshell:error- Shell operation error
// Connect to Socket.IO with authentication
const socket = io('http://localhost:8080', {
query: {
token: 'your-secure-token'
}
});
// Handle connection events
socket.on('connect', () => {
console.log('Connected successfully');
// Watch for file changes
socket.emit('fs:watch', '/home/user/documents');
});
socket.on('connect_error', (error) => {
console.error('Authentication failed:', error.message);
});
socket.on('fs:change', (data) => {
console.log('File changed:', data);
});
// Start port monitoring
socket.emit('net:monitor:start', 'both', '127.0.0.1', 2);
socket.on('net:monitor:started', (data) => {
console.log('Port monitoring started:', data);
});
socket.on('net:port:changes', (data) => {
data.changes.forEach(change => {
console.log(`Port ${change.port} ${change.status} on ${change.interface}`);
});
});
// Stop port monitoring
socket.emit('net:monitor:stop', 'both', '127.0.0.1');
// Spawn interactive shell
socket.emit('shell:spawn', '/bin/bash');
socket.on('shell:spawned', (data) => {
console.log('Shell spawned:', data.session_id);
// Send command to shell
socket.emit('shell:input', data.session_id, 'ls -la\n');
});
socket.on('shell:output', (data) => {
console.log('Shell output:', data.data);
});# Set access token for convenience
ACCESS_TOKEN="your-secure-token"
# List directory
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
"http://localhost:8080/api/fs/listdir?path=/home"
# Create file
curl -X POST http://localhost:8080/api/fs/create \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/tmp/test.txt","content":"Hello World"}'
# Download file
curl -X POST http://localhost:8080/api/net/download \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://httpbin.org/json","path":"/tmp/downloaded.json"}'
# Get current listening ports
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
"http://localhost:8080/api/net/ports?protocol=both&interface=any"
# Execute command
curl -X POST http://localhost:8080/api/shell/exec \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"command":"ls -la","workdir":"/tmp"}'
# Health check (no authentication required)
curl http://localhost:8080/healthThe network module uses a passive monitoring approach that reads from /proc/net/tcp and /proc/net/udp files to detect port changes without generating network traffic. This method:
- Efficient: No active port scanning, just file system reads
- Real-time: Configurable polling intervals (minimum 1 second)
- Selective: Monitor specific protocols (TCP, UDP, or both)
- Interface filtering: Monitor specific network interfaces or all
- Change detection: Only reports when ports open or close
- Protocol:
tcp,udp, orboth - Interface: IP address (
127.0.0.1,0.0.0.0) oranyfor all interfaces - Interval: Polling interval in seconds (minimum 1, recommended 2-5)
Each port change includes:
- Port number: The affected port
- Status:
openedorclosed - Protocol:
tcporudp - Interface: The network interface IP
- Timestamp: Unix timestamp of the change
version: '3.8'
services:
ccw:
build: .
ports:
- "8080:8080"
environment:
- AUTH_TOKEN=your-secure-token
- PORT=8080
# For debug mode, add:
# command: ["--debug"]
restart: unless-stoppedapiVersion: apps/v1
kind: Deployment
metadata:
name: ccw-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ccw
template:
metadata:
labels:
app: ccw
spec:
containers:
- name: ccw
image: ccw:latest
ports:
- containerPort: 8080
env:
- name: AUTH_TOKEN
valueFrom:
secretKeyRef:
name: ccw-secret
key: auth_token
- name: PORT
value: "8080"
# For debug mode:
# args: ["--debug"]
---
apiVersion: v1
kind: Secret
metadata:
name: ccw-secret
type: Opaque
stringData:
auth_token: "your-secure-token"- Authentication Required: All API endpoints (except health check) require Bearer token authentication
- Environment Variables: Store auth token and sensitive configuration in environment variables
- Token Security: Use strong, unique access token for the Bearer token
- HTTPS Recommended: Use HTTPS in production to protect authentication tokens in transit
- Container Security: The application runs as a non-root user in the Docker container
- File System Isolation: File operations are restricted to the container's file system
- Shell Security: Shell commands are executed with the application's user permissions
- Network Monitoring: Port monitoring only reads system information, doesn't perform network operations
- Connection Cleanup: Socket.IO connections are properly cleaned up on disconnect
- Debug Mode: Disable debug mode in production to prevent information leakage
.
├── main.go # Main application entry point with auth middleware
├── modules/
│ ├── filesystem.go # File system module implementation
│ ├── network.go # Network module implementation
│ └── shell.go # Shell module implementation
├── go.mod # Go module dependencies
├── Dockerfile # Docker container configuration
└── README.md # This documentation
# Build locally
go build
# Build Docker image
docker build -t ccw .
# Run with authentication
export AUTH_TOKEN="your-secure-token"
./ccw --debug# Test without authentication (should fail)
curl http://localhost:8080/api/fs/listdir?path=/
# Test with wrong token (should fail)
curl -H "Authorization: Bearer wrong-token" \
http://localhost:8080/api/fs/listdir?path=/
# Test with correct token (should succeed)
curl -H "Authorization: Bearer your-secure-token" \
http://localhost:8080/api/fs/listdir?path=/
# Health check (should work without auth)
curl http://localhost:8080/health- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Ensure authentication works correctly
- Test both debug and production modes
- Submit a pull request
MIT License