18 KiB
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
bash
bash
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
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.