diff --git a/vm1/aseftp/.gitkeep b/vm1/aseftp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/vm1/docker-compose.yml b/vm1/docker-compose.yml index 0a9a862..eae1be7 100644 --- a/vm1/docker-compose.yml +++ b/vm1/docker-compose.yml @@ -89,37 +89,18 @@ services: FTP_EXTERNAL_IP: ${VIP:-192.168.1.210} volumes: - app-logs:/app/logs + - ./aseftp:/app/aseftp - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro networks: - app-network + ports: + - "40000-40499:40000-40499" expose: - "21" - - "40000-40249" - labels: - logging: "promtail" - ftp-server-1b: - build: . - container_name: ftp-server-1b - restart: unless-stopped - command: ["python", "-m", "src.ftp_csv_receiver"] - environment: - DB_HOST: ${VIP:-192.168.1.210} - FTP_INSTANCE_ID: 7 - TZ: Europe/Rome - FTP_PASSIVE_PORT: "40250" - FTP_EXTERNAL_IP: ${VIP:-192.168.1.210} - volumes: - - app-logs:/app/logs - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - networks: - - app-network - expose: - - "21" - - "40250-40499" labels: logging: "promtail" + haproxy: image: haproxy:2.8-alpine container_name: haproxy @@ -130,8 +111,6 @@ services: - app-network ports: - "21:21" - - "3306:3306" - - "40000-40499:40000-40499" - "8404:8404" labels: logging: "promtail" diff --git a/vm1/env/ftp.ini b/vm1/env/ftp.ini index af27fe8..9967ef6 100644 --- a/vm1/env/ftp.ini +++ b/vm1/env/ftp.ini @@ -4,7 +4,7 @@ [ftpserver] service_port = 21 firstPort = 40000 - proxyAddr = 0.0.0.0 + proxyAddr = 192.168.1.210 portRangeWidth = 500 virtpath = /app/aseftp/ adminuser = admin|87b164c8d4c0af8fbab7e05db6277aea8809444fb28244406e489b66c92ba2bd|/app/aseftp/|elradfmwMT diff --git a/vm1/haproxy.cfg b/vm1/haproxy.cfg index 78c3045..48671ca 100644 --- a/vm1/haproxy.cfg +++ b/vm1/haproxy.cfg @@ -30,24 +30,4 @@ frontend ftp_control backend ftp_servers mode tcp - balance roundrobin server ftp1 ftp-server-1:21 check - server ftp1b ftp-server-1b:21 check - -frontend ftp_passive_1 - bind *:40000-40249 - mode tcp - default_backend ftp_passive_1_backend - -backend ftp_passive_1_backend - mode tcp - server ftp1 ftp-server-1:40000 check port 21 - -frontend ftp_passive_1b - bind *:40250-40499 - mode tcp - default_backend ftp_passive_1b_backend - -backend ftp_passive_1b_backend - mode tcp - server ftp1b ftp-server-1b:40250 check port 21 diff --git a/vm1/src/ftp_csv_receiver.py b/vm1/src/ftp_csv_receiver.py index 6fd0050..f00ee1f 100755 --- a/vm1/src/ftp_csv_receiver.py +++ b/vm1/src/ftp_csv_receiver.py @@ -29,6 +29,9 @@ logger = logging.getLogger(__name__) class ASEHandler(FTPHandler): """Custom FTP handler that extends FTPHandler with custom commands and file handling.""" + # Permetti connessioni dati da indirizzi IP diversi (importante per NAT/proxy) + permit_foreign_addresses = True + def __init__(self: object, conn: object, server: object, ioloop: object = None) -> None: """Initializes the handler, adds custom commands, and sets up command permissions. @@ -155,13 +158,27 @@ def main(): handler = ASEHandler handler.cfg = cfg handler.authorizer = authorizer - handler.masquerade_address = cfg.proxyaddr + + # Set masquerade address only if configured (importante per HA con VIP) + # Questo è l'IP che il server FTP pubblicherà ai client per le connessioni passive + if cfg.proxyaddr and cfg.proxyaddr.strip(): + handler.masquerade_address = cfg.proxyaddr + logger.info(f"FTP masquerade address configured: {cfg.proxyaddr}") + else: + logger.info("FTP masquerade address not configured - using server's default IP") # Set the range of passive ports for the FTP server - _range = list(range(cfg.firstport, cfg.firstport + cfg.portrangewidth)) - handler.passive_ports = _range + passive_ports_range = list(range(cfg.firstport, cfg.firstport + cfg.portrangewidth)) + handler.passive_ports = passive_ports_range + # Log configuration logger.info(f"Starting FTP server on port {cfg.service_port} with DatabaseAuthorizer") + logger.info( + f"FTP passive ports configured: {cfg.firstport}-{cfg.firstport + cfg.portrangewidth - 1} " + f"({len(passive_ports_range)} ports)" + ) + logger.info(f"FTP permit_foreign_addresses: {handler.permit_foreign_addresses}") + logger.info(f"Database connection: {cfg.dbuser}@{cfg.dbhost}:{cfg.dbport}/{cfg.dbname}") # Create and start the FTP server server = FTPServer(("0.0.0.0", cfg.service_port), handler) diff --git a/vm1/src/load_ftp_users.py b/vm1/src/load_ftp_users.py index 07cfff5..453f719 100644 --- a/vm1/src/load_ftp_users.py +++ b/vm1/src/load_ftp_users.py @@ -17,7 +17,7 @@ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %( logger = logging.getLogger(__name__) # Configurazione server FTP -FTP_CONFIG = {"host": "localhost", "user": "admin", "password": "batt1l0", "port": 2121} +FTP_CONFIG = {"host": "192.168.1.210", "user": "admin", "password": "batt1l0", "port": 21} def connect_ftp() -> FTP: diff --git a/vm1/src/utils/config/loader_ftp_csv.py b/vm1/src/utils/config/loader_ftp_csv.py index 0c5c767..41b63e9 100644 --- a/vm1/src/utils/config/loader_ftp_csv.py +++ b/vm1/src/utils/config/loader_ftp_csv.py @@ -1,5 +1,6 @@ """set configurations""" +import os from configparser import ConfigParser from . import ENV_PARENT_PATH @@ -10,15 +11,21 @@ class Config: """ Initializes the Config class by reading configuration files. It loads settings from 'ftp.ini' and 'db.ini' for FTP server, CSV, logging, and database. + Environment variables override INI file settings for Docker deployments. """ c = ConfigParser() c.read([f"{ENV_PARENT_PATH}/env/ftp.ini", f"{ENV_PARENT_PATH}/env/db.ini"]) - # FTP setting + # FTP setting (with environment variable override for Docker) self.service_port = c.getint("ftpserver", "service_port") - self.firstport = c.getint("ftpserver", "firstPort") - self.proxyaddr = c.get("ftpserver", "proxyAddr") + + # FTP_PASSIVE_PORTS: override della porta iniziale del range passivo + self.firstport = int(os.getenv("FTP_PASSIVE_PORTS", c.getint("ftpserver", "firstPort"))) + + # FTP_EXTERNAL_IP: override dell'IP pubblicizzato (VIP per HA) + self.proxyaddr = os.getenv("FTP_EXTERNAL_IP", c.get("ftpserver", "proxyAddr")) + self.portrangewidth = c.getint("ftpserver", "portRangeWidth") self.virtpath = c.get("ftpserver", "virtpath") self.adminuser = c.get("ftpserver", "adminuser").split("|") @@ -33,12 +40,12 @@ class Config: # LOG setting self.logfilename = c.get("logging", "logFilename") - # DB setting - self.dbhost = c.get("db", "hostname") - self.dbport = c.getint("db", "port") - self.dbuser = c.get("db", "user") - self.dbpass = c.get("db", "password") - self.dbname = c.get("db", "dbName") + # DB setting (with environment variable override for Docker) + self.dbhost = os.getenv("DB_HOST", c.get("db", "hostname")) + self.dbport = int(os.getenv("DB_PORT", c.getint("db", "port"))) + self.dbuser = os.getenv("DB_USER", c.get("db", "user")) + self.dbpass = os.getenv("DB_PASSWORD", c.get("db", "password")) + self.dbname = os.getenv("DB_NAME", c.get("db", "dbName")) self.max_retries = c.getint("db", "maxRetries") # Tables diff --git a/vm2/aseftp/.gitkeep b/vm2/aseftp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/vm2/docker-compose.yml b/vm2/docker-compose.yml index 9354c01..a1fef28 100644 --- a/vm2/docker-compose.yml +++ b/vm2/docker-compose.yml @@ -63,40 +63,21 @@ services: FTP_EXTERNAL_IP: ${VIP:-192.168.1.210} volumes: - app-logs:/app/logs + - ./aseftp:/app/aseftp - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro networks: - app-network + ports: + - "40000-40499:40000-40499" expose: - "21" - - "40000-40249" - labels: - logging: "promtail" - ftp-server-2b: - build: . - container_name: ftp-server-2b - restart: unless-stopped - command: ["python", "-m", "src.ftp_csv_receiver"] - environment: - DB_HOST: ${VIP:-192.168.1.210} - FTP_INSTANCE_ID: 8 - TZ: Europe/Rome - FTP_PASSIVE_PORT: "40250" - FTP_EXTERNAL_IP: ${VIP:-192.168.1.210} - volumes: - - app-logs:/app/logs - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - networks: - - app-network - expose: - - "21" - - "40250-40499" labels: logging: "promtail" + haproxy: image: haproxy:2.8-alpine - container_name: haproxy-backup + container_name: haproxy restart: unless-stopped volumes: - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro @@ -104,8 +85,6 @@ services: - app-network ports: - "21:21" - - "3306:3306" - - "40000-40499:40000-40499" - "8404:8404" labels: logging: "promtail" diff --git a/vm2/env/ftp.ini b/vm2/env/ftp.ini index af27fe8..9967ef6 100644 --- a/vm2/env/ftp.ini +++ b/vm2/env/ftp.ini @@ -4,7 +4,7 @@ [ftpserver] service_port = 21 firstPort = 40000 - proxyAddr = 0.0.0.0 + proxyAddr = 192.168.1.210 portRangeWidth = 500 virtpath = /app/aseftp/ adminuser = admin|87b164c8d4c0af8fbab7e05db6277aea8809444fb28244406e489b66c92ba2bd|/app/aseftp/|elradfmwMT diff --git a/vm2/haproxy.cfg b/vm2/haproxy.cfg index 18c10b6..20f3b82 100644 --- a/vm2/haproxy.cfg +++ b/vm2/haproxy.cfg @@ -30,24 +30,4 @@ frontend ftp_control backend ftp_servers mode tcp - balance roundrobin server ftp2 ftp-server-2:21 check - server ftp2b ftp-server-2b:21 check - -frontend ftp_passive_2 - bind *:40000-40249 - mode tcp - default_backend ftp_passive_2_backend - -backend ftp_passive_2_backend - mode tcp - server ftp2 ftp-server-2:40000 check port 21 - -frontend ftp_passive_2b - bind *:40250-40499 - mode tcp - default_backend ftp_passive_2b_backend - -backend ftp_passive_2b_backend - mode tcp - server ftp2b ftp-server-2b:40250 check port 21 diff --git a/vm2/src/ftp_csv_receiver.py b/vm2/src/ftp_csv_receiver.py index 6fd0050..f00ee1f 100755 --- a/vm2/src/ftp_csv_receiver.py +++ b/vm2/src/ftp_csv_receiver.py @@ -29,6 +29,9 @@ logger = logging.getLogger(__name__) class ASEHandler(FTPHandler): """Custom FTP handler that extends FTPHandler with custom commands and file handling.""" + # Permetti connessioni dati da indirizzi IP diversi (importante per NAT/proxy) + permit_foreign_addresses = True + def __init__(self: object, conn: object, server: object, ioloop: object = None) -> None: """Initializes the handler, adds custom commands, and sets up command permissions. @@ -155,13 +158,27 @@ def main(): handler = ASEHandler handler.cfg = cfg handler.authorizer = authorizer - handler.masquerade_address = cfg.proxyaddr + + # Set masquerade address only if configured (importante per HA con VIP) + # Questo è l'IP che il server FTP pubblicherà ai client per le connessioni passive + if cfg.proxyaddr and cfg.proxyaddr.strip(): + handler.masquerade_address = cfg.proxyaddr + logger.info(f"FTP masquerade address configured: {cfg.proxyaddr}") + else: + logger.info("FTP masquerade address not configured - using server's default IP") # Set the range of passive ports for the FTP server - _range = list(range(cfg.firstport, cfg.firstport + cfg.portrangewidth)) - handler.passive_ports = _range + passive_ports_range = list(range(cfg.firstport, cfg.firstport + cfg.portrangewidth)) + handler.passive_ports = passive_ports_range + # Log configuration logger.info(f"Starting FTP server on port {cfg.service_port} with DatabaseAuthorizer") + logger.info( + f"FTP passive ports configured: {cfg.firstport}-{cfg.firstport + cfg.portrangewidth - 1} " + f"({len(passive_ports_range)} ports)" + ) + logger.info(f"FTP permit_foreign_addresses: {handler.permit_foreign_addresses}") + logger.info(f"Database connection: {cfg.dbuser}@{cfg.dbhost}:{cfg.dbport}/{cfg.dbname}") # Create and start the FTP server server = FTPServer(("0.0.0.0", cfg.service_port), handler) diff --git a/vm2/src/utils/config/loader_ftp_csv.py b/vm2/src/utils/config/loader_ftp_csv.py index 0c5c767..41b63e9 100644 --- a/vm2/src/utils/config/loader_ftp_csv.py +++ b/vm2/src/utils/config/loader_ftp_csv.py @@ -1,5 +1,6 @@ """set configurations""" +import os from configparser import ConfigParser from . import ENV_PARENT_PATH @@ -10,15 +11,21 @@ class Config: """ Initializes the Config class by reading configuration files. It loads settings from 'ftp.ini' and 'db.ini' for FTP server, CSV, logging, and database. + Environment variables override INI file settings for Docker deployments. """ c = ConfigParser() c.read([f"{ENV_PARENT_PATH}/env/ftp.ini", f"{ENV_PARENT_PATH}/env/db.ini"]) - # FTP setting + # FTP setting (with environment variable override for Docker) self.service_port = c.getint("ftpserver", "service_port") - self.firstport = c.getint("ftpserver", "firstPort") - self.proxyaddr = c.get("ftpserver", "proxyAddr") + + # FTP_PASSIVE_PORTS: override della porta iniziale del range passivo + self.firstport = int(os.getenv("FTP_PASSIVE_PORTS", c.getint("ftpserver", "firstPort"))) + + # FTP_EXTERNAL_IP: override dell'IP pubblicizzato (VIP per HA) + self.proxyaddr = os.getenv("FTP_EXTERNAL_IP", c.get("ftpserver", "proxyAddr")) + self.portrangewidth = c.getint("ftpserver", "portRangeWidth") self.virtpath = c.get("ftpserver", "virtpath") self.adminuser = c.get("ftpserver", "adminuser").split("|") @@ -33,12 +40,12 @@ class Config: # LOG setting self.logfilename = c.get("logging", "logFilename") - # DB setting - self.dbhost = c.get("db", "hostname") - self.dbport = c.getint("db", "port") - self.dbuser = c.get("db", "user") - self.dbpass = c.get("db", "password") - self.dbname = c.get("db", "dbName") + # DB setting (with environment variable override for Docker) + self.dbhost = os.getenv("DB_HOST", c.get("db", "hostname")) + self.dbport = int(os.getenv("DB_PORT", c.getint("db", "port"))) + self.dbuser = os.getenv("DB_USER", c.get("db", "user")) + self.dbpass = os.getenv("DB_PASSWORD", c.get("db", "password")) + self.dbname = os.getenv("DB_NAME", c.get("db", "dbName")) self.max_retries = c.getint("db", "maxRetries") # Tables