При разработке интеграций в 1С разработчики часто сталкиваются с ситуацией: при вызове кода из интерактивной формы файловый или файлообменный процесс отрабатывает идеально, но стоит вынести этот же код в регламентное или фоновое задание, как система выдает сетевую ошибку:
Ошибка работы с Интернет: ftp://leshpav.myjino.ru:21 FTP: unknown PASV reply.
Разберем детально, почему возникает эта ошибка, как устроена работа сетевого уровня 1С и какие есть проверенные способы решения этой проблемы.
Проанализируем архитектуру сетевого взаимодействия платформы 1С:Предприятие. Для работы с протоколом FTP платформа использует встроенные сетевые библиотеки (в частности, cURL). Ошибка FTP: unknown PASV reply генерируется сетевым клиентом в тот момент, когда 1С отправляет FTP-серверу команду перехода в пассивный режим (PASV), но полученный ответ сервера не может быть корректно разобран.
В стандартном пассивном режиме FTP-сервер в ответ на команду PASV должен вернуть строку формата:
227 Entering Passive Mode (IP1,IP2,IP3,IP4,Port1,Port2)
Если ответ сервера приходит в нестандартном формате, содержит имя хоста вместо IP-адреса, искажен сетевым экраном или заблокирован антивирусом, cURL выдает сообщение unknown PASV reply.
Выясним причину такого разного поведения системы при выполнении одного и того же кода:
rphost.exe на сервере 1С или отдельном фоновом процессе 1cv8.exe в файловой базе) от имени системной службы (например, USR1CV8, LOCAL SERVICE или SYSTEM).PASV возвращают внутренний (локальный) IP-адрес сетевой фермы. Интерактивная сессия ОС может сглаживать эти отклонения, а строгое фоновое окружение cURL в 1С выдает ошибку.Рассмотрев причины, перейдем к практическим способам решения этой проблемы.
По умолчанию конструктор FTPСоединение в 1С может использовать пассивный режим. Попробуем явно переключить режим соединения на активный или явно задать параметры пассивного режима.
Рассмотрим пример кода с явным переключением в активный режим:
// Задаем параметры подключения
СерверFTP = "leshpav.myjino.ru";
ПортFTP = 21;
ПользовательFTP = "my_user";
ПарольFTP = "my_password";
// Явно отключаем пассивный режим (переходим в активный режим)
ПассивныйРежим = Ложь;
Таймаут = 30;
Попытка
ФТП = Новый FTPСоединение(СерверFTP, ПортFTP, ПользовательFTP, ПарольFTP, , ПассивныйРежим, Таймаут);
// Выполнение операций с файлами
МассивФайлов = ФТП.НайтиФайлы("/");
Исключение
ЗаписьЖурналаРегистрации("FTP.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
Важно: При работе в активном режиме убедитесь, что на сервере и клиенте открыты порты 20 и 21, а также разрешены входящие соединения для процесса 1С.
Если фоновое задание выполняется в корпоративной сети, где используется прокси-сервер, автоматическое определение настроек может не сработать. В этом случае необходимо явно инициализировать объект FTPПрокси.
Посмотрим на пример установки соединения через прокси:
Прокси = Новый FTPПрокси;
Прокси.Сервер = "192.168.1.1";
Прокси.Порт = 8080;
Прокси.Пользователь = "proxy_user";
Прокси.Пароль = "proxy_pass";
// Передаем объект Прокси в конструктор FTPСоединение
ФТП = Новый FTPСоединение(СерверFTP, ПортFTP, ПользовательFTP, ПарольFTP, Прокси, Истина, 30);
Если проблему не удается решить изменением кода 1С, проанализируем настройки сетевого оборудования и операционной системы:
rphost.exe для клиент-серверной базы или 1cv8.exe для файловой базы) в список разрешенных программ брандмауэра Windows для всех типов сетей (доменная, частная, публичная).PASV, что приводит к ошибкам парсинга в cURL.Если встроенное FTPСоединение продолжает выдавать ошибку из-за особенностей хостинга или ограничений cURL платформы, надежным решением является вызов консольной утилиты. Утилита cURL входит в состав современных ОС Windows и поддерживает флаг --ftp-skip-pasv-ip, который игнорирует некорректные IP-адреса в ответах PASV.
Рассмотрим пример загрузки файла на FTP-сервер с помощью внешнего вызова cURL:
Функция ОтправитьФайлЧерезCurl(ИмяФайлаИсточника, ИмяФайлаПриемника, Сервер, Логин, Пароль) Экспорт
// Формируем команду cURL с флагом --ftp-skip-pasv-ip
Команда = СтрШаблон("curl --ftp-skip-pasv-ip --insecure -u %1:%2 -T ""%3"" ""ftp://%4/%5""",
Логин,
Пароль,
ИмяФайлаИсточника,
Сервер,
ИмяФайлаПриемника
);
// Выполняем команду в фоновом режиме
КодВозврата = 0;
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
ЗаписьЖурналаРегистрации("FTP.cURL", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка отправки файла. Код: " + КодВозврата);
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
Альтернативно можно использовать WinSCP в командном режиме с помощью сценариев (.txt), что обеспечивает полное логирование процесса обмена.
Протокол FTP является устаревающим и создает множество проблем при работе через NAT и сетевые экраны из-за необходимости открытия динамических портов. Более надежной архитектурной альтернативой является переход на HTTP/HTTPS.
Для работы с HTTP в 1С используются объекты HTTPСоединение и HTTPЗапрос. Они работают по фиксированным портам (80 или 443) и не подвержены проблемам с режимами PASV/PORT.
Проанализируем пример передачи файла по HTTP/HTTPS:
СерверHTTP = "leshpav.myjino.ru";
ЗаголовокЗапроса = Новый Соответствие;
ЗаголовокЗапроса.Вставить("Content-Type", "application/octet-stream");
Соединение = Новый HTTPСоединение(СерверHTTP, 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/api/upload?file=" + ИмяФайла, ЗаголовокЗапроса);
Запрос.УстановитьИмяФайлаТела(ПутьКФайлу);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
ЗаписьЖурналаРегистрации("HTTP.Ошибка", УровеньЖурналаРегистрации.Ошибка, , , "Код ответа: " + Ответ.КодСостояния);
КонецЕсли;
При появлении ошибки FTP: unknown PASV reply в фоновых заданиях 1С рекомендуется придерживаться следующего алгоритма:
ПассивноеСоединение в значение Ложь в коде 1С.rphost.exe / 1cv8.exe.cURL с ключом --ftp-skip-pasv-ip.