This commit is contained in:
2025-11-02 11:14:40 +01:00
parent 6cfccbefd2
commit 8f5c0a5016
13 changed files with 84 additions and 118 deletions

0
vm1/aseftp/.gitkeep Normal file
View File

View File

@@ -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"

2
vm1/env/ftp.ini vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

0
vm2/aseftp/.gitkeep Normal file
View File

View File

@@ -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"

2
vm2/env/ftp.ini vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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