Сейчас будет немного боли и радости от победы над FTP. Мы много и упорно работаем со СМЭВ3. Никакой магии: обычный SOAP поверх HTTP, быстро, надёжно - все банки и гос. учреждения знают, как это делается. И вдруг (никогда такого не было, и вот опять) оказалось, что нам надо забирать большие файлы с FTP, предоставляемого СМЭВ.
Дисклеймер: постарайтесь воздерживаться от использования FTP - это технология немного устарела и не отвечает современным требованиям удобства и безопасности.
Тем не менее, надо - значит надо. СМЭВ располагается в защищенной инфраструктуре электронного правительства, куда мы ходим через шлюзы, расположенные в определённой инфраструктуре. В этих шлюзах нет ничего необычного - HTTP, балансировка, отказоустойчивость через избыточность.
В чём проблема?
Шлюзы есть, прокси есть, с чего бы нам бояться FTP? Оказывается, бояться есть с чего - FTP использует не один порт, а множество динамически открываемых, причём есть особенный режим (active), когда сервер инициирует соединение к клиенту - это еще со стародавних времён, когда никакого NAT не было.
В результате мы не можем работать с этим FTP "по простому" - нам требуется как-то обеспечить сетевую связность и наши любимые и привычные инструменты нам в этом помочь не могут 😠 . Надо думать.
FTP (англ. File Transfer Protocol) — протокол передачи файлов по сети, появившийся в 1971 году задолго до HTTP и даже до TCP/IP, благодаря чему является одним из старейших прикладных протоколов. Изначально FTP работал поверх протокола NCP, на сегодняшний день широко используется для распространения ПО и доступа к удалённым хостам.
Дополнительной особенностью в нашем случае является не просто наличие шлюза, через который необходимо обращаться в СМЭВ, а целых 2:
- Gateway 1 - внутри облака
- Gateway 2 - в специальной инфраструктуре с сетевой связностью со СМЭВ
вот так выглядит наш каскад проксей:
Решение
Если есть проблема, то должно быть и решение. Так и оказалось - есть несколько (наверное даже много) программных продуктов, связанных с проксированием FTP:
- 3proxy - целый набор проксей. Прочитали доку, запустили - не завелось.
- Squid - большой, надёжный, кеширующий прокси, на все случаи жизни. Для нас оказался слишком избыточен в настройке. И в контексте FTP практически нет документации.
- ftp-proxy (ftpproxy) - стандартный пакет в дистрибутиве Debian/Ubuntu, и он взлетел со свитом.
Поскольку всё наше облако оркестрируется с помощью Nomad, то и этот компонент мы завернули docker.
Dockerfile
FROM debian:bullseye-slim
RUN apt-get update
RUN apt-get install -y \
ftp-proxy gettext
RUN mkdir -p /tmp/logs/
ADD ./ftp-proxy.conf.in /tmp/ftp-proxy.conf.in
ENV DESTINATION_ADDRESS=127.0.0.1
ENV DESTINATION_PORT=21
ENV PROXY_PORT=21
ENV PROXY_LOG_LEVEL=DBG
EXPOSE 21
CMD envsubst < /tmp/ftp-proxy.conf.in > /etc/proxy-suite/ftp-proxy.conf && exec /usr/sbin/ftp-proxy -n -d
ftp-proxy.conf
В конфиге можно задать миллион других настроек, но в нашем случае достаточно только этого:
[-Global-]
DestinationAddress ${DESTINATION_ADDRESS}
DestinationPort ${DESTINATION_PORT}
Port ${PROXY_PORT}
LogDestination | cat
LogLevel ${PROXY_LOG_LEVEL}
nomad
Мы катаем джобы с помощью ансибла и используем его шаблонизацию, так что тут я приведу уже финальный результат препроцессинга:
variable "instance" {
type = string
default = "prod"
}
job "ftp-proxy-prod" {
datacenters = ["zone-a", "zone-b", "zone-c"]
namespace = "default"
constraint {
attribute = "${meta.gate}"
value = "true"
}
update {
max_parallel = 1
health_check = "checks"
min_healthy_time = "10s"
healthy_deadline = "3m"
progress_deadline = "6m"
auto_revert = true
auto_promote = false
canary = 0
}
type = "system"
group "ftp-proxy" {
network {
port "ftp" {
static = 21
host_network = "private"
}
}
task "ftp-proxy-prod" {
driver = "docker"
kill_timeout = "30s"
leader = true
env {
DESTINATION_ADDRESS = "10.0.0.34"
DESTINATION_PORT = "8878"
PROXY_PORT = "21"
PROXY_LOG_LEVEL = "DBG"
}
restart {
attempts = 3
interval = "5m"
delay = "15s"
mode = "fail"
}
config {
image = "YOURIMAGE:latest"
force_pull = true
network_mode = "host"
auth {
username = "USER"
password = "PASS"
}
}
service {
name = "prod-ftp"
tags = [ "ftp-proxy", "prod" ]
port = "ftp"
check {
type = "tcp"
port = "ftp"
interval = "2s"
timeout = "5s"
}
check_restart {
limit = 3
grace = "10s"
ignore_warnings = false
}
}
logs {
max_files = 5
max_file_size = 50
}
resources {
memory = 100
memory_max = 200
cpu = 200
}
}
}
}
nomad job run -detach ftp-proxy.hcl
Конец
Всем спасибо - всё работает, но если у кого-то есть замечания, связанные с данным решением - мы с огромным интересом их рассмотрим 🤞.
Top comments (0)