375 lines
9.8 KiB
Markdown
375 lines
9.8 KiB
Markdown
# Sistema NAT Industrial para Acceso a PLCs/SCADA
|
||
|
||
Este proyecto crea un **sistema NAT dinámico** en WSL2 que permite a PC2 acceder a dispositivos PLC/SCADA en la red corporativa de PC1 a través de un servidor Linux intermediario (PC3). Soluciona las limitaciones de red de WSL2 y VPNs corporativas.
|
||
|
||
## 🎯 **Arquitectura de Red Industrial**
|
||
|
||
```
|
||
PC2 (Remoto) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)
|
||
↑ ↑ ↑ ↑
|
||
ZeroTier/Internet SSH Tunnel Túnel Reverso Red Corporativa
|
||
Intermediario desde WSL2 (GlobalConnect VPN)
|
||
```
|
||
|
||
**Problema resuelto:** PC1 está en una VPN corporativa con acceso a PLCs pero no puede abrir puertos. PC2 necesita acceder a esos PLCs remotamente.
|
||
|
||
## 🏭 **Casos de Uso Industriales**
|
||
|
||
- **VNC a PLCs** - Acceso gráfico remoto a pantallas HMI
|
||
- **Interfaces Web** - Configuración de dispositivos industriales
|
||
- **Modbus TCP** - Comunicación con controladores
|
||
- **SSH/Telnet** - Acceso terminal a equipos industriales
|
||
- **Bases de datos** - Historiadores y sistemas SCADA
|
||
- **OPC/SCADA** - Protocolos industriales
|
||
|
||
## ✨ **Características del Sistema**
|
||
|
||
- ✅ **NAT Dinámico** - Conecta a cualquier IP:puerto sin configuración previa
|
||
- ✅ **Solo clave SSH privada** - No necesita certificados SSL complejos
|
||
- ✅ **Servicios industriales predefinidos** - VNC, Modbus, HTTP, SSH automáticos
|
||
- ✅ **Gestión desde PC2** - Control remoto completo via API REST
|
||
- ✅ **Sistema permanente** - Se ejecuta como servicio, auto-reinicio
|
||
- ✅ **Múltiples PLCs simultáneos** - Gestiona toda la planta industrial
|
||
|
||
## 📁 Estructura del Proyecto
|
||
|
||
```
|
||
proxytcp/
|
||
├── Dockerfile # Imagen del contenedor industrial
|
||
├── docker-compose.yml # Configuración de servicios
|
||
├── requirements.txt # Dependencias Python
|
||
├── src/
|
||
│ └── industrial_nat_manager.py # Sistema NAT principal
|
||
├── config/
|
||
│ └── nat_config.yaml # Configuración industrial
|
||
├── certs/ # Clave SSH privada
|
||
│ └── ssh_private_key # Tu clave SSH generada
|
||
├── scripts/
|
||
│ ├── nat_client.py # Cliente para PC2
|
||
│ ├── industrial_manager.sh # Gestión automatizada
|
||
│ └── generate_ssh_key.sh # Generador de claves
|
||
├── setup_permanent.sh # Configuración como servicio
|
||
└── logs/ # Logs del sistema
|
||
```
|
||
|
||
## 🚀 **Instalación Completa**
|
||
|
||
### **Paso 1: Generar Clave SSH (PC1)**
|
||
```bash
|
||
# Generar nueva clave SSH específica
|
||
./scripts/generate_ssh_key.sh
|
||
```
|
||
|
||
### **Paso 2: Configurar PC3 (Servidor Intermediario)**
|
||
```bash
|
||
## 🚨 **Resolución de Problemas**
|
||
|
||
### **Problemas Comunes**
|
||
|
||
#### **1. Error de conexión SSH a PC3**
|
||
```bash
|
||
# Verificar clave SSH
|
||
ls -la certs/ssh_private_key
|
||
chmod 600 certs/ssh_private_key
|
||
|
||
# Probar conexión manual
|
||
ssh -i certs/ssh_private_key miguefin@91.99.210.72
|
||
```
|
||
|
||
#### **2. PLC no accesible desde PC2**
|
||
```bash
|
||
# Verificar túnel SSH activo
|
||
docker exec proxytcp_proxy_1 ps aux | grep ssh
|
||
|
||
# Verificar configuración PC3
|
||
ssh -i certs/ssh_private_key miguefin@91.99.210.72 "sudo netstat -tlnp | grep :9"
|
||
```
|
||
|
||
#### **3. Servicio no inicia automáticamente**
|
||
```bash
|
||
# Verificar servicio systemd
|
||
sudo systemctl status industrial-nat-manager
|
||
|
||
# Ver logs del servicio
|
||
sudo journalctl -u industrial-nat-manager -f
|
||
|
||
# Reiniciar servicio
|
||
sudo systemctl restart industrial-nat-manager
|
||
```
|
||
|
||
#### **4. Puertos ocupados**
|
||
```bash
|
||
# Verificar puertos en uso
|
||
docker exec proxytcp_proxy_1 netstat -tlnp
|
||
|
||
# Limpiar conexiones
|
||
docker restart proxytcp_proxy_1
|
||
```
|
||
|
||
### **Información de Red**
|
||
|
||
```
|
||
Flujo de Datos:
|
||
PC2 (Remoto) → PC3 (91.99.210.72) → PC1 (WSL2+VPN) → PLCs/SCADA (10.1.33.x)
|
||
|
||
Puertos Dinámicos: 9000-9999 en PC3
|
||
API de Control: Puerto 8080 en PC1
|
||
```
|
||
|
||
## 📚 **Documentación Adicional**
|
||
|
||
- **PC3_SETUP.md** - Configuración detallada del servidor intermediario
|
||
- **INDUSTRIAL_README.md** - Guía específica para uso industrial
|
||
- **config/nat_config.yaml** - Referencia de configuración completa
|
||
|
||
## 🤝 **Soporte**
|
||
|
||
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.
|
||
|
||
**Casos de uso típicos:**
|
||
- Monitoreo remoto de plantas industriales
|
||
- Mantenimiento de equipos desde ubicaciones remotas
|
||
- Acceso a HMI/SCADA sin VPN corporativa
|
||
- Gestión de múltiples PLCs simultáneamente
|
||
|
||
---
|
||
|
||
🏭 **Sistema NAT Industrial para Acceso Remoto a PLCs/SCADA** 🏭
|
||
```
|
||
|
||
### **Paso 3: Configurar Sistema Permanente (PC1)**
|
||
```bash
|
||
# Instalar como servicio permanente
|
||
./setup_permanent.sh
|
||
|
||
# ¡El sistema queda funcionando automáticamente!
|
||
```
|
||
|
||
## <20> **Uso del Sistema**
|
||
|
||
### **Desde PC2 (Remoto) - Acceso Industrial**
|
||
|
||
```bash
|
||
# Copiar el cliente a PC2
|
||
scp nat_client.py pc2@ip.del.pc2:/ruta/destino/
|
||
|
||
# En PC2, conectar a PLCs usando servicios predefinidos:
|
||
|
||
# 1. Conectar a PLC via VNC (visualización)
|
||
python nat_client.py plc 10.1.33.11 vnc
|
||
|
||
# 2. Conectar a PLC via Modbus TCP (datos)
|
||
python nat_client.py plc 10.1.33.11 modbus
|
||
|
||
# 3. Conectar a interfaz web del PLC
|
||
python nat_client.py plc 10.1.33.11 http
|
||
|
||
# 4. Acceso SSH a dispositivo industrial
|
||
python nat_client.py plc 10.1.33.15 ssh
|
||
|
||
# 5. Conexión personalizada
|
||
python nat_client.py connect 10.1.33.20 8080 --name "Servidor_SCADA"
|
||
```
|
||
|
||
### **Gestión Avanzada (PC1)**
|
||
|
||
```bash
|
||
# Ver estado del sistema
|
||
docker exec proxytcp_proxy_1 python -c "
|
||
import aiohttp, asyncio
|
||
async def status():
|
||
async with aiohttp.ClientSession() as session:
|
||
async with session.get('http://localhost:8080/status') as resp:
|
||
print(await resp.json())
|
||
asyncio.run(status())
|
||
"
|
||
|
||
# Gestión interactiva
|
||
./scripts/industrial_manager.sh
|
||
|
||
# Ver logs del sistema
|
||
docker logs proxytcp_proxy_1 -f
|
||
```
|
||
|
||
## 🔧 **Configuración Industrial**
|
||
|
||
### **Archivo de Configuración (`config/nat_config.yaml`)**
|
||
|
||
```yaml
|
||
# Configuración del servidor PC3
|
||
ssh_server:
|
||
host: "91.99.210.72"
|
||
port: 22
|
||
user: "miguefin"
|
||
key_file: "/app/certs/ssh_private_key"
|
||
|
||
# Servicios industriales predefinidos
|
||
services:
|
||
vnc:
|
||
port: 5900
|
||
description: "Acceso remoto a pantallas HMI"
|
||
modbus:
|
||
port: 502
|
||
description: "Protocolo Modbus TCP"
|
||
http:
|
||
port: 80
|
||
description: "Interfaces web de dispositivos"
|
||
ssh:
|
||
port: 22
|
||
description: "Acceso SSH a dispositivos"
|
||
|
||
# Configuración de puertos dinámicos
|
||
nat:
|
||
port_range: [9000, 9999]
|
||
bind_host: "0.0.0.0"
|
||
```
|
||
|
||
## 🔧 Tipos de Servicios Disponibles
|
||
|
||
### 1. Servicio HTTP
|
||
Responde con JSON y información de la conexión:
|
||
```bash
|
||
# En el contenedor Docker expone puerto 3000
|
||
# En el servidor Linux se accede por puerto 3000
|
||
curl http://91.99.210.72:3000
|
||
```
|
||
|
||
### 2. Servicio Echo
|
||
Útil para pruebas de conectividad:
|
||
```bash
|
||
# Usando telnet o netcat
|
||
echo "Hello World" | nc 91.99.210.72 7000
|
||
```
|
||
|
||
### 3. Servicios Personalizados
|
||
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
|
||
```bash
|
||
# 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
|
||
```bash
|
||
# 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
|
||
```bash
|
||
# 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
|
||
```bash
|
||
# Ver qué proceso usa el puerto
|
||
sudo netstat -tulpn | grep :PUERTO
|
||
|
||
# Eliminar proxy existente
|
||
./scripts/manage_proxy.sh remove PUERTO
|
||
```
|
||
|
||
### Proxy no funciona
|
||
```bash
|
||
# 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
|
||
```bash
|
||
# Estado general
|
||
./scripts/manage_proxy.sh status
|
||
|
||
# Conexiones detalladas
|
||
docker exec tcp-proxy-container netstat -an
|
||
```
|
||
|
||
### Métricas de Uso
|
||
```python
|
||
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
|
||
```bash
|
||
#!/bin/bash
|
||
# backup_config.sh
|
||
tar -czf "backup_$(date +%Y%m%d_%H%M%S).tar.gz" config/ certs/
|
||
```
|
||
|
||
### Script de Monitoreo
|
||
```python
|
||
#!/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. |