ProxyTcpReverse/README.md

18 KiB
Raw Blame History

Industrial NAT System for Remote PLC/SCADA Access# Industrial NAT System for Remote PLC/SCADA Access

This project creates a dynamic NAT system in WSL2 that allows PC2 to access PLC/SCADA devices on PC1's corporate network through a Linux intermediary server (PC3). It solves WSL2 and corporate VPN network limitations.This project creates a dynamic NAT system in WSL2 that allows PC2 to access PLC/SCADA devices on PC1's corporate network through a Linux intermediary server (PC3). It solves WSL2 and corporate VPN network limitations.

🎯 Industrial Network Architecture## 🎯 Industrial Network Architecture


PC1: Windows + ZeroTier + VPN GlobalConnect + WSL2PC1: Windows + ZeroTier + VPN GlobalConnect + WSL2

PC2: Windows + ZeroTier PC2: Windows + ZeroTier 

PC3: Linux Server: 91.99.210.72 with private keyPC3: Linux Server: 91.99.210.72 with private key


PC2 (Remote) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)PC2 (Remote) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)

     ↑               ↑                    ↑                    ↑     ↑               ↑                    ↑                    ↑

ZeroTier/Internet  SSH Tunnel      Reverse Tunnel      Corporate NetworkZeroTier/Internet  SSH Tunnel      Reverse Tunnel      Corporate Network

                   Intermediary    from WSL2           (GlobalConnect VPN)                   Intermediary    from WSL2           (GlobalConnect VPN)

Problem solved: PC1 is on a corporate VPN with access to PLCs but cannot open ports. PC2 needs remote access to those PLCs.Problem solved: PC1 is on a corporate VPN with access to PLCs but cannot open ports. PC2 needs remote access to those PLCs.

🏭 Industrial Use Cases## 🏭 Industrial Use Cases

  • VNC to PLCs - Remote graphical access to HMI screens- VNC to PLCs - Remote graphical access to HMI screens

  • Web Interfaces - Industrial device configuration - Web Interfaces - Industrial device configuration

  • Modbus TCP - Controller communication- Modbus TCP - Controller communication

  • SSH/Telnet - Terminal access to industrial equipment- SSH/Telnet - Terminal access to industrial equipment

  • Databases - Historians and SCADA systems- Databases - Historians and SCADA systems

  • OPC/SCADA - Industrial protocols- OPC/SCADA - Industrial protocols

System Features## System Features

  • Dynamic NAT - Connect to any IP:port without prior configuration- Dynamic NAT - Connect to any IP:port without prior configuration

  • SSH private key only - No complex SSL certificates needed - SSH private key only - No complex SSL certificates needed

  • Predefined industrial services - Automatic VNC, Modbus, HTTP, SSH- Predefined industrial services - Automatic VNC, Modbus, HTTP, SSH

  • Remote management from PC2 - Complete control via REST API- Remote management from PC2 - Complete control via REST API

  • Permanent system - Runs as service with auto-restart- Permanent system - Runs as service with auto-restart

  • Multiple simultaneous PLCs - Manages entire industrial plant- Multiple simultaneous PLCs - Manages entire industrial plant

📁 Project Structure## 📁 Project Structure


proxytcp/proxytcp/

├── Dockerfile                      # Industrial container image├── Dockerfile                      # Industrial container image

├── docker-compose.yml             # Service configuration├── docker-compose.yml             # Service configuration

├── requirements.txt               # Python dependencies├── requirements.txt               # Python dependencies

├── src/├── src/

│   └── industrial_nat_manager.py  # Main NAT system│   └── industrial_nat_manager.py  # Main NAT system

├── config/├── config/

│   └── nat_config.yaml            # Industrial configuration│   └── nat_config.yaml            # Industrial configuration

├── certs/                         # SSH private key (provided)├── certs/                         # SSH private key (provided)

│   └── ssh_private_key            # Your SSH private key│   └── ssh_private_key            # Your SSH private key

├── scripts/├── scripts/

│   ├── nat_client.py              # Client for PC2│   ├── nat_client.py              # Client for PC2

│   ├── industrial_manager.sh      # Automated management│   ├── industrial_manager.sh      # Automated management

│   └── generate_ssh_key.sh        # Key generator (optional)│   └── generate_ssh_key.sh        # Key generator (optional)

├── setup_permanent.sh             # Service configuration├── setup_permanent.sh             # Service configuration

└── logs/                          # System logs└── logs/                          # System logs

🚀 Complete Installation## 🚀 Complete Installation

Step 1: Setup PC1 (WSL2 Container)### Step 1: Setup PC1 (WSL2 Container)

IMPORTANT: Execute these commands inside WSL2 on PC1IMPORTANT: Execute these commands inside WSL2 on PC1

bashbash

1. Clone the repository in WSL2# 1. Clone the repository in WSL2

git clone https://gitea.casaparma.dscloud.me/Miguel/ProxyTcpReverse.gitgit clone https://gitea.casaparma.dscloud.me/Miguel/ProxyTcpReverse.git

cd ProxyTcpReversecd ProxyTcpReverse

2. Verify SSH private key exists# 2. Verify SSH private key exists

ls -la certs/ssh_private_keyls -la certs/ssh_private_key

chmod 600 certs/ssh_private_keychmod 600 certs/ssh_private_key

3. Install Docker and Docker Compose in WSL2 (if not installed)# 3. Install Docker and Docker Compose in WSL2 (if not installed)

sudo apt updatesudo apt update

sudo apt install docker.io docker-compose -ysudo apt install docker.io docker-compose -y

sudo usermod -aG docker $USERsudo usermod -aG docker $USER

newgrp dockernewgrp docker

4. Build and configure the industrial container# 4. Build and configure the industrial container

docker-compose builddocker-compose build

5. Configure as permanent service (runs automatically)# 5. Configure as permanent service (runs automatically)

./setup_permanent.sh./setup_permanent.sh

System is now running automatically!# System is now running automatically!




### **Step 2: Configure PC3 (Intermediary Server)**### **Paso 2: Configurar PC3 (Servidor Intermediario)**

```bash```bash

# On PC3 (91.99.210.72), configure SSH for tunnels## 🚨 **Resolución de Problemas**

sudo nano /etc/ssh/sshd_config

### **Problemas Comunes**

# Add these lines:

GatewayPorts yes#### **1. Error de conexión SSH a PC3**

AllowTcpForwarding yes```bash

# Verificar clave SSH

# Restart SSHls -la certs/ssh_private_key

sudo systemctl restart sshchmod 600 certs/ssh_private_key



# Add public key (if not already done)# Probar conexión manual

mkdir -p ~/.sshssh -i certs/ssh_private_key miguefin@91.99.210.72

nano ~/.ssh/authorized_keys```

# (paste the public key corresponding to the private key in /certs)

chmod 600 ~/.ssh/authorized_keys#### **2. PLC no accesible desde PC2**

```bash

# Configure firewall# Verificar túnel SSH activo

sudo ufw allow 22docker exec proxytcp_proxy_1 ps aux | grep ssh

sudo ufw allow 9000:9999/tcp

```# Verificar configuración PC3

ssh -i certs/ssh_private_key miguefin@91.99.210.72 "sudo netstat -tlnp | grep :9"

### **Step 3: Test Connection**```

```bash

# From WSL2 on PC1, test SSH connection to PC3#### **3. Servicio no inicia automáticamente**

ssh -i certs/ssh_private_key miguefin@91.99.210.72```bash

# Verificar servicio systemd

# If successful, the industrial system is ready!sudo systemctl status industrial-nat-manager

```

# Ver logs del servicio

## 💻 **System Usage**sudo journalctl -u industrial-nat-manager -f



### **From PC2 (Remote) - Industrial Access**# Reiniciar servicio

sudo systemctl restart industrial-nat-manager

```bash```

# Copy the client to PC2

scp nat_client.py pc2@ip.of.pc2:/destination/path/#### **4. Puertos ocupados**

```bash

# On PC2, connect to PLCs using predefined services:# Verificar puertos en uso

docker exec proxytcp_proxy_1 netstat -tlnp

# 1. Connect to PLC via VNC (visualization)

python nat_client.py plc 10.1.33.11 vnc# Limpiar conexiones

docker restart proxytcp_proxy_1

# 2. Connect to PLC via Modbus TCP (data)```

python nat_client.py plc 10.1.33.11 modbus

### **Información de Red**

# 3. Connect to PLC web interface

python nat_client.py plc 10.1.33.11 http```

Flujo de Datos:

# 4. SSH access to industrial devicePC2 (Remoto) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)

python nat_client.py plc 10.1.33.15 ssh

Puertos Dinámicos: 9000-9999 en PC3

# 5. Custom connectionAPI de Control: Puerto 8080 en PC1

python nat_client.py connect 10.1.33.20 8080 --name "SCADA_Server"```

```

## 📚 **Documentación Adicional**

### **Advanced Management (PC1)**

- **PC3_SETUP.md** - Configuración detallada del servidor intermediario

```bash- **INDUSTRIAL_README.md** - Guía específica para uso industrial

# View system status- **config/nat_config.yaml** - Referencia de configuración completa

docker exec proxytcp_proxy_1 python -c "

import aiohttp, asyncio## 🤝 **Soporte**

async def status():

    async with aiohttp.ClientSession() as session:Este sistema está diseñado para entornos industriales que requieren acceso remoto a PLCs y sistemas SCADA a través de limitaciones de red corporativa. 

        async with session.get('http://localhost:8080/status') as resp:

            print(await resp.json())**Casos de uso típicos:**

asyncio.run(status())- Monitoreo remoto de plantas industriales

"- Mantenimiento de equipos desde ubicaciones remotas  

- Acceso a HMI/SCADA sin VPN corporativa

# Interactive management- Gestión de múltiples PLCs simultáneamente

./scripts/industrial_manager.sh

---

# View system logs

docker logs proxytcp_proxy_1 -f🏭 **Sistema NAT Industrial para Acceso Remoto a PLCs/SCADA** 🏭

🔧 Industrial Configuration### Paso 3: Configurar Sistema Permanente (PC1)


### **Configuration File (`config/nat_config.yaml`)**# Instalar como servicio permanente

./setup_permanent.sh

```yaml

# PC3 server configuration# ¡El sistema queda funcionando automáticamente!

ssh_server:```

  host: "91.99.210.72"

  port: 22## <20> **Uso del Sistema**

  user: "miguefin"

  key_file: "/app/certs/ssh_private_key"### **Desde PC2 (Remoto) - Acceso Industrial**



# Predefined industrial services```bash

services:# Copiar el cliente a PC2

  vnc:scp nat_client.py pc2@ip.del.pc2:/ruta/destino/

    port: 5900

    description: "Remote access to HMI screens"# En PC2, conectar a PLCs usando servicios predefinidos:

  modbus:

    port: 502# 1. Conectar a PLC via VNC (visualización)

    description: "Modbus TCP protocol"python nat_client.py plc 10.1.33.11 vnc

  http:

    port: 80# 2. Conectar a PLC via Modbus TCP (datos)

    description: "Device web interfaces"python nat_client.py plc 10.1.33.11 modbus

  ssh:

    port: 22# 3. Conectar a interfaz web del PLC

    description: "SSH access to devices"python nat_client.py plc 10.1.33.11 http



# Dynamic port configuration# 4. Acceso SSH a dispositivo industrial

nat:python nat_client.py plc 10.1.33.15 ssh

  port_range: [9000, 9999]

  bind_host: "0.0.0.0"# 5. Conexión personalizada

```python nat_client.py connect 10.1.33.20 8080 --name "Servidor_SCADA"

🚨 Troubleshooting

Gestión Avanzada (PC1)

Common Issues


#### **1. SSH connection error to PC3**# Ver estado del sistema

```bashdocker exec proxytcp_proxy_1 python -c "

# Verify SSH keyimport aiohttp, asyncio

ls -la certs/ssh_private_keyasync def status():

chmod 600 certs/ssh_private_key    async with aiohttp.ClientSession() as session:

        async with session.get('http://localhost:8080/status') as resp:

# Test manual connection            print(await resp.json())

ssh -i certs/ssh_private_key miguefin@91.99.210.72asyncio.run(status())

```"



#### **2. PLC not accessible from PC2**# Gestión interactiva

```bash./scripts/industrial_manager.sh

# Verify active SSH tunnel

docker exec proxytcp_proxy_1 ps aux | grep ssh# Ver logs del sistema

docker logs proxytcp_proxy_1 -f

# Verify PC3 configuration```

ssh -i certs/ssh_private_key miguefin@91.99.210.72 "sudo netstat -tlnp | grep :9"

```## 🔧 **Configuración Industrial**



#### **3. Service doesn't start automatically**### **Archivo de Configuración (`config/nat_config.yaml`)**

```bash

# Verify systemd service```yaml

sudo systemctl status industrial-nat-manager# Configuración del servidor PC3

ssh_server:

# View service logs  host: "91.99.210.72"

sudo journalctl -u industrial-nat-manager -f  port: 22

  user: "miguefin"

# Restart service  key_file: "/app/certs/ssh_private_key"

sudo systemctl restart industrial-nat-manager

```# Servicios industriales predefinidos

services:

#### **4. Ports occupied**  vnc:

```bash    port: 5900

# Check ports in use    description: "Acceso remoto a pantallas HMI"

docker exec proxytcp_proxy_1 netstat -tlnp  modbus:

    port: 502

# Clean connections    description: "Protocolo Modbus TCP"

docker restart proxytcp_proxy_1  http:

```    port: 80

    description: "Interfaces web de dispositivos"

### **Network Information**  ssh:

    port: 22

```    description: "Acceso SSH a dispositivos"

Data Flow:

PC2 (Remote) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)# Configuración de puertos dinámicos

nat:

Dynamic Ports: 9000-9999 on PC3  port_range: [9000, 9999]

Control API: Port 8080 on PC1  bind_host: "0.0.0.0"

📚 Additional Documentation## 🔧 Tipos de Servicios Disponibles

  • PC3_SETUP.md - Detailed intermediary server configuration### 1. Servicio HTTP

  • INDUSTRIAL_README.md - Industrial-specific usage guideResponde con JSON y información de la conexión:

  • config/nat_config.yaml - Complete configuration reference```bash

En el contenedor Docker expone puerto 3000

🤝 Support# En el servidor Linux se accede por puerto 3000

curl http://91.99.210.72:3000

This system is designed for industrial environments requiring remote access to PLCs and SCADA systems through corporate network limitations.```

Typical use cases:### 2. Servicio Echo

  • Remote monitoring of industrial plantsÚtil para pruebas de conectividad:

  • Equipment maintenance from remote locations ```bash

  • HMI/SCADA access without corporate VPN# Usando telnet o netcat

  • Managing multiple PLCs simultaneouslyecho "Hello World" | nc 91.99.210.72 7000


---

### 3. Servicios Personalizados

🏭 **Industrial NAT System for Remote PLC/SCADA Access** 🏭Puedes crear tus propios servicios modificando `ssh_proxy_manager.py`

## 💡 Casos de Uso Comunes

### 1. API de Desarrollo
```bash
# Exponer API del contenedor al mundo
./scripts/manage_proxy.sh add 8000 8000
# Acceso: http://91.99.210.72:8000

2. Servicio de Pruebas

# Servicio echo para verificar conectividad
./scripts/manage_proxy.sh add 9999 9999  
# Prueba: echo "test" | nc 91.99.210.72 9999

3. Múltiples Servicios

# Web frontend
./scripts/manage_proxy.sh add 3000 3000

# API backend  
./scripts/manage_proxy.sh add 8000 8000

# WebSocket
./scripts/manage_proxy.sh add 9000 9000

🐛 Resolución de Problemas

El contenedor no inicia

# Verificar logs
docker logs tcp-proxy-container

# Verificar certificados
ls -la certs/

Error de conexión SSL

  • Verifica que los certificados son válidos
  • Confirma que el servidor remoto acepta tu certificado
  • Revisa los logs para detalles del error

Puerto ya en uso

# Ver qué proceso usa el puerto
sudo netstat -tulpn | grep :PUERTO

# Eliminar proxy existente
./scripts/manage_proxy.sh remove PUERTO

Proxy no funciona

# Verificar estado
./scripts/manage_proxy.sh status

# Probar conexión manual
telnet localhost PUERTO_LOCAL

🔐 Seguridad

  • Los certificados se montan como solo lectura
  • El contenedor ejecuta con usuario no-root
  • Las conexiones usan SSL/TLS end-to-end
  • Los logs no registran datos sensibles

📊 Monitoreo

Verificar Conexiones Activas

# Estado general
./scripts/manage_proxy.sh status

# Conexiones detalladas
docker exec tcp-proxy-container netstat -an

Métricas de Uso

import requests

status = requests.get('http://localhost:8080/status').json()
print(f"Total conexiones: {status['total_connections']}")

for proxy in status['proxies']:
    print(f"Puerto {proxy['local_port']}: {proxy['connections']} conexiones activas")

🚦 Scripts de Automatización

Script de Backup de Configuración

#!/bin/bash
# backup_config.sh
tar -czf "backup_$(date +%Y%m%d_%H%M%S).tar.gz" config/ certs/

Script de Monitoreo

#!/usr/bin/env python3
# monitor.py
import time
import requests
from datetime import datetime

while True:
    try:
        status = requests.get('http://localhost:8080/status', timeout=5).json()
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print(f"[{timestamp}] Proxies: {len(status['proxies'])}, Conexiones: {status['total_connections']}")
    except Exception as e:
        print(f"Error: {e}")
    time.sleep(30)

📝 Licencia

Este proyecto es de uso libre para fines personales y educativos.

🤝 Contribuciones

Para reportar problemas o sugerir mejoras, crea un issue en el repositorio del proyecto.


¡Listo para usar! El sistema está configurado para conectar automáticamente con tu servidor Linux usando los certificados proporcionados.