# 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 PC1**IMPORTANT:** 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)** ```bash ### **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## � **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** ```bash #### **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 ```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.