Skip to content

awehttam/terminalgateway

Repository files navigation

Terminal Gateway

A web-based terminal that can connect to remote systems via SSH or Telnet using xterm.js and a Node.js proxy server.

Features

  • 🖥️ Full terminal emulation using xterm.js
  • 🔐 SSH connections with username/password authentication
  • 📡 Telnet connections
  • 🌐 WebSocket-based real-time communication
  • 📱 Responsive design that works on desktop and mobile
  • ⚡ Real-time terminal resizing
  • 🎨 Dark theme terminal interface

Installation

  1. Clone or download this project
  2. Install dependencies:
npm install

Configuration

Before running the server, you need to configure the allowed hosts and security settings.

Gateway Configuration

  1. Copy the example configuration:
cp config/gateway.json.example config/gateway.json
  1. Edit config/gateway.json to configure allowed hosts:
{
  "allowedHosts": [
    {
      "host": "your-server.example.com",
      "description": "My SSH Server",
      "protocols": ["ssh", "telnet"],
      "defaultPort": {
        "ssh": 22,
        "telnet": 23
      }
    }
  ],
  "security": {
    "requireHostValidation": true,
    "allowPrivateNetworks": false,
    "maxConnectionTime": 3600000,
    "connectionTimeout": 30000
  },
  "logging": {
    "logConnections": true,
    "logLevel": "info"
  }
}

Configuration Options

allowedHosts

  • host: The hostname or IP address to allow connections to
  • description: Human-readable description of the host
  • protocols: Array of allowed protocols (["ssh", "telnet"])
  • defaultPort: Default ports for each protocol

security

  • requireHostValidation: Whether to enforce the allowedHosts list (default: true)
  • allowPrivateNetworks: Allow connections to private IP ranges (default: false)
  • maxConnectionTime: Maximum connection time in milliseconds
  • connectionTimeout: Connection timeout in milliseconds

logging

  • logConnections: Whether to log connection attempts
  • logLevel: Logging level ("info", "warn", "error")

⚠️ Important: The server must be restarted after changing the configuration file.

PHP Client Configuration

The php/index.php file provides a standalone client that can be used independently. To configure it:

  1. Edit the connection settings in php/index.php:
// Pre-configured proxy server settings
const PROXY_HOST = 'localhost';  // Your gateway server host
const PROXY_PORT = 3000;         // Your gateway server port

// Remote SSH/Telnet host settings
const REMOTE_HOST = 'your-server.example.com';  // Target server
const REMOTE_PORT = 22;          // Target port (22 for SSH, 1337 for Telnet, etc.)
  1. Update the connection type (SSH or Telnet):
// For SSH connections
socket.emit('connect-ssh', {
    host: REMOTE_HOST,
    port: REMOTE_PORT,
    username: username,
    password: password
});

// For Telnet connections  
socket.emit('connect-telnet', {
    host: REMOTE_HOST,
    port: REMOTE_PORT
});

The PHP client includes all required assets locally (php/assets/) so it works without internet connectivity.

Usage

  1. Configure allowed hosts in config/gateway.json

  2. Start the server:

npm start
  1. Open your browser and go to http://localhost:3000

  2. Connect to a remote system:

    • SSH: Enter host, port (default 22), username, and password
    • Telnet: Enter host and port (default 23)

Note: Only hosts listed in allowedHosts with the appropriate protocols will be permitted to connect.

Development

For development with auto-restart:

npm run dev

Example Connections

SSH Examples

  • Linux Server: user@example.com:22
  • Raspberry Pi: pi@192.168.1.100:22
  • Cloud Instance: ubuntu@ec2-xxx.amazonaws.com:22

Telnet Examples

  • Star Wars ASCII: towel.blinkenlights.nl:23
  • Weather Service: rainmaker.wunderground.com:3000
  • Local Router: 192.168.1.1:23

Production Deployment

For production use, it's recommended to run the Terminal Gateway behind a reverse proxy for TLS termination and additional security.

Caddy Configuration

Create a Caddyfile:

terminal.yourdomain.com {
    reverse_proxy localhost:3000
    
    # Optional: Add authentication
    # basicauth {
    #     user $2a$14$...hashed-password...
    # }
}

Start Caddy:

caddy run --config Caddyfile

Nginx Configuration

Create /etc/nginx/sites-available/terminal-gateway:

server {
    listen 443 ssl http2;
    server_name terminal.yourdomain.com;
    
    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name terminal.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/terminal-gateway /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Apache Configuration

Create /etc/apache2/sites-available/terminal-gateway.conf:

<VirtualHost *:443>
    ServerName terminal.yourdomain.com
    
    SSLEngine on
    SSLCertificateFile /path/to/your/certificate.crt
    SSLCertificateKeyFile /path/to/your/private.key
    
    ProxyPreserveHost On
    ProxyRequests Off
    
    # WebSocket support
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "ws://localhost:3000/$1" [P,L]
    
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # Set headers for WebSocket
    ProxyPassReverse / http://localhost:3000/
    ProxyPass /socket.io/ http://localhost:3000/socket.io/
    ProxyPassReverse /socket.io/ http://localhost:3000/socket.io/
</VirtualHost>

# Redirect HTTP to HTTPS
<VirtualHost *:80>
    ServerName terminal.yourdomain.com
    Redirect permanent / https://terminal.yourdomain.com/
</VirtualHost>

Enable required modules and site:

sudo a2enmod ssl rewrite proxy proxy_http proxy_wstunnel
sudo a2ensite terminal-gateway
sudo systemctl reload apache2

Environment Variables

For production, set these environment variables:

export NODE_ENV=production
export PORT=3000
export HOST=localhost

Automatic Startup

Option 1: Cron with @reboot (Simple)

  1. Make the startup script executable:
chmod +x start-gateway.sh
  1. Edit the script to set the correct path:
nano start-gateway.sh
# Change /path/to/terminalgateway to /home/webterminal
  1. Add to crontab:
crontab -e
# Add this line:
@reboot /home/webterminal/start-gateway.sh

Option 2: Systemd User Service (Recommended for Linux)

  1. Create the user systemd directory and copy the service file:
mkdir -p ~/.config/systemd/user
cp terminal-gateway.service ~/.config/systemd/user/
  1. Edit the service file to set the correct path:
nano ~/.config/systemd/user/terminal-gateway.service
# Update WorkingDirectory=/home/webterminal
  1. Enable lingering (allows service to run without user login):
sudo loginctl enable-linger $USER
  1. Enable and start the user service:
systemctl --user daemon-reload
systemctl --user enable terminal-gateway
systemctl --user start terminal-gateway
  1. Check service status:
systemctl --user status terminal-gateway
journalctl --user -u terminal-gateway -f

Benefits of user service:

  • Runs under your user account (no need for dedicated user)
  • Survives user logout (with lingering enabled)
  • Uses your home directory path automatically
  • Easier to manage and debug

Option 3: PM2 Process Manager (Cross-platform)

  1. Install PM2 globally:
npm install -g pm2
  1. Start the application:
pm2 start ecosystem.config.js --env production
  1. Save PM2 configuration:
pm2 save
pm2 startup
# Follow the instructions to enable startup on boot
  1. Manage the process:
pm2 status
pm2 logs terminal-gateway
pm2 restart terminal-gateway
pm2 stop terminal-gateway

Option 4: Docker (Containerized)

Create a Dockerfile:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
USER node
CMD ["npm", "start"]

Build and run:

docker build -t terminal-gateway .
docker run -d --name terminal-gateway -p 3000:3000 terminal-gateway

With Docker Compose (docker-compose.yml):

version: '3.8'
services:
  terminal-gateway:
    build: .
    ports:
      - "3000:3000"
    restart: unless-stopped
    volumes:
      - ./config:/app/config:ro

Security Notes

⚠️ Important: This tool requires additional security considerations for production use:

  • Configure the gateway.json allowedHosts list appropriately
  • Use HTTPS/WSS connections (via reverse proxy)
  • Implement proper authentication at the reverse proxy level
  • Add rate limiting
  • Consider using SSH keys instead of passwords
  • Monitor and log connections
  • Keep the server updated

Architecture

  • Frontend: HTML5 + xterm.js + Socket.IO client
  • Backend: Node.js + Express + Socket.IO + SSH2 + Telnet-client
  • Communication: WebSocket for real-time terminal data

Browser Support

  • Chrome/Chromium 60+
  • Firefox 55+
  • Safari 11+
  • Edge 79+

Dependencies

  • express: Web server framework
  • socket.io: Real-time WebSocket communication
  • ssh2: SSH client implementation
  • telnet-client: Telnet client implementation
  • xterm: Terminal emulator for the web

License

MIT License

About

Node and PHP terminal (telnet, ssh) gateway for the web

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

 
 
 

Contributors