В процессе интеграции 1С с внешними информационными системами часто возникает задача безопасной передачи данных. Стандартный протокол FTP постепенно уходит в прошлое из-за отсутствия шифрования, и клиенты все чаще требуют передачи данных по защищенному каналу SSH (SFTP). Однако здесь разработчики сталкиваются с важным техническим ограничением платформы «1С:Предприятие».
Стандартный объект платформы FTPСоединение поддерживает работу по протоколам FTP и FTPS (FTP поверх SSL/TLS), но он абсолютно не поддерживает протокол SFTP (SSH File Transfer Protocol). Это совершенно разные протоколы, работающие на разных сетевых портах (21/990 для FTP/FTPS и обычно 22 для SFTP/SSH). Попытка подключиться к SFTP-серверу с помощью FTPСоединение неизбежно приведет к ошибке соединения. Для организации выгрузки по классическому протоколу можно использовать решение для файлового обмена с сайтом по FTP.
В этой статье мы подробно и по шагам разберем самые надежные, бесплатные и проверенные на практике способы реализации отправки файлов из 1С по протоколу SSH (SFTP) как для операционных систем семейства Windows, так и для Linux-серверов.
---
Этот способ является одним из самых популярных и стабильных для серверов под управлением ОС Windows. Мы будем использовать бесплатную и многофункциональную утилиту WinSCP, которая предоставляет собственную сборку .NET библиотеки (WinSCPnet.dll). Эту библиотеку можно зарегистрировать в операционной системе в качестве COM-объекта, что позволит нам управлять передачей файлов напрямую из кода 1С с возможностью перехвата и обработки ошибок.
Рассмотрим пошагово процесс настройки и интеграции:
WinSCPnet.dll.
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe "C:\Program Files (x86)\WinSCP\WinSCPnet.dll" /codebase /tlb
После успешной регистрации библиотеки мы можем обратиться к ней из кода 1С. Проанализируем пример кода для отправки файла на удаленный SFTP-сервер:
&НаСервере
Процедура ОтправитьФайлПоSFTP_WinSCP_COM(ПутьКЛокальномуФайлу, ИмяФайлаНаСервере)
// Инициализируем настройки подключения к SFTP-серверу
Попытка
НастройкиСессии = Новый COMОбъект("WinSCP.SessionOptions");
Исключение
ВызватьИсключение "Не удалось создать COM-объект WinSCP.SessionOptions. Проверьте регистрацию библиотеки WinSCPnet.dll в системе! " + ОписаниеОшибки();
КонецПопытки;
// Заполняем параметры подключения
НастройкиСессии.Protocol = 1; // 1 соответствует протоколу SFTP
НастройкиСессии.HostName = "sftp.example.com";
НастройкиСессии.PortNumber = 22;
НастройкиСессии.UserName = "sftp_user";
НастройкиСессии.Password = "SuperSecurePassword123";
// Важный параметр безопасности: отпечаток ключа хоста (HostKey Fingerprint).
// Он необходим, чтобы предотвратить атаку типа "Man-in-the-middle".
// Его можно узнать при первом ручном подключении к серверу через графический интерфейс WinSCP.
НастройкиСессии.SshHostKeyFingerprint = "ssh-ed25519 256 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx";
// Создаем объект сессии
Сессия = Новый COMОбъект("WinSCP.Session");
Попытка
// Открываем соединение с сервером
Сессия.Open(НастройкиСессии);
// Настраиваем параметры передачи файлов
ПараметрыПередачи = Новый COMОбъект("WinSCP.TransferOptions");
ПараметрыПередачи.TransferMode = 1; // 1 - Бинарный режим передачи данных (Binary)
// Отправляем файл на удаленный сервер
// Первый параметр: локальный путь к файлу
// Второй параметр: удаленная папка на сервере (обязательно закрывать слэшем)
// Третий параметр: Ложь (не удалять исходный локальный файл после передачи)
// Четвертый параметр: объект настроек передачи
РезультатПередачи = Сессия.PutFiles(ПутьКЛокальномуФайлу, "/upload/", Ложь, ПараметрыПередачи);
// Проверяем, успешно ли прошла отправка файлов
РезультатПередачи.Check();
ЗаписьЖурналаРегистрации("Отправка SFTP", УровеньЖурналаРегистрации.Информация, , , "Файл успешно отправлен: " + ИмяФайлаНаСервере);
Исключение
// В случае ошибок обязательно записываем подробное описание в журнал регистрации
ТекстОшибки = "Ошибка при передаче файла по SFTP: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Отправка SFTP", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонечныеУсилия:
// Гарантированно закрываем сессию и освобождаем ресурсы, даже если возникла ошибка
Если Сессия.Opened Тогда
Сессия.Dispose();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Преимущества данного подхода: Полный контроль процесса передачи на стороне 1С, возможность тонкой настройки параметров сессии, перехват исключений через стандартную конструкцию Попытка... Исключение, отсутствие необходимости в создании временных файлов-скриптов.
---
Если по каким-то причинам политика безопасности вашей компании запрещает регистрацию сторонних COM-компонент на сервере приложений 1С, мы можем использовать WinSCP в режиме командной строки. Этот способ также ориентирован на операционные системы Windows.
Идея заключается в том, что мы динамически формируем текстовый файл, содержащий инструкции для консольного клиента WinSCP, сохраняем его во временный каталог, а затем запускаем WinSCP в фоновом режиме с передачей этого скрипта в качестве аргумента.
Разберем детально этот алгоритм на примере кода:
&НаСервере
Процедура ОтправитьФайлПоSFTP_WinSCP_CLI(ПутьКЛокальномуФайлу, ИмяФайлаНаСервере)
// Путь к исполняемому консольному файлу WinSCP.com (не .exe, а именно .com для CLI)
ПутьКWinSCP = "C:\Program Files (x86)\WinSCP\WinSCP.com";
// Генерируем уникальные имена для файлов скрипта и логов
ПутьКФайлуСкрипта = ПолучитьИмяВременногоФайла("txt");
ПутьКФайлуЛогов = ПолучитьИмяВременногоФайла("log");
// Формируем команды для выполнения внутри сессии WinSCP
ТекстСкрипта = Новый ТекстовыйДокумент;
ТекстСкрипта.ДобавитьСтроку("option batch abort"); // Прерывать выполнение при возникновении любых ошибок
ТекстСкрипта.ДобавитьСтроку("option confirm off"); // Отключить любые интерактивные подтверждения
// Формируем строку подключения: sftp://логин:пароль@хост:порт -hostkey="отпечаток"
ШаблонПодключения = "open sftp://sftp_user:SuperSecurePassword123@sftp.example.com:22 -hostkey=""ssh-ed25519 256 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx""";
ТекстСкрипта.ДобавитьСтроку(ШаблонПодключения);
// Команда отправки файла: put "локальный_путь" "удаленный_путь"
КомандаОтправки = СтрШаблон("put ""%1"" ""/upload/%2""", ПутьКЛокальномуФайлу, ИмяФайлаНаСервере);
ТекстСкрипта.ДобавитьСтроку(КомандаОтправки);
// Завершаем сеанс WinSCP
ТекстСкрипта.ДобавитьСтроку("exit");
// Записываем файл скрипта в кодировке UTF-8 или ANSI (WinSCP корректно работает с UTF-8)
ТекстСкрипта.Записать(ПутьКФайлуСкрипта, КодировкаТекста.UTF8);
// Формируем строку запуска консольного приложения с передачей скрипта и лог-файла
ПараметрыЗапуска = СтрШаблон("/script=""%1"" /log=""%2""", ПутьКФайлуСкрипта, ПутьКФайлуЛогов);
// Запускаем процесс в синхронном режиме (третий параметр "Истина" заставляет 1С ждать окончания выполнения)
Попытка
КодВозврата = ЗапуститьПриложение(ПутьКWinSCP + " " + ПараметрыЗапуска, , Истина);
Исключение
ВызватьИсключение "Не удалось запустить утилиту WinSCP.com: " + ОписаниеОшибки();
КонецПопытки;
// Анализируем результаты работы
Если КодВозврата <> 0 Тогда
// Считываем лог-файл для понимания причины падения
ЛогФайл = Новый ТекстовыйДокумент;
ЛогФайл.Прочитать(ПутьКФайлуЛогов, КодировкаТекста.UTF8);
ТекстЛогов = ЛогФайл.ПолучитьТекст();
ТекстОшибки = "Ошибка передачи файла по SFTP через CLI! Код возврата: " + КодВозврата + Символы.ПС + ТекстЛогов;
ЗаписьЖурналаРегистрации("Отправка SFTP CLI", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
// Очищаем временные файлы перед выходом из процедуры при возникновении ошибки
УдалитьФайлы(ПутьКФайлуСкрипта);
УдалитьФайлы(ПутьКФайлуЛогов);
ВызватьИсключение ТекстОшибки;
КонецЕсли;
// Очищаем временные файлы в случае успеха
УдалитьФайлы(ПутьКФайлуСкрипта);
УдалитьФайлы(ПутьКФайлуЛогов);
ЗаписьЖурналаРегистрации("Отправка SFTP CLI", УровеньЖурналаРегистрации.Информация, , , "Файл успешно отправлен методом CLI.");
КонецПроцедуры
Преимущества данного подхода: Не требует регистрации DLL в реестре Windows, легко переносится между серверами, прост в отладке (всегда можно открыть текстовый лог-файл и посмотреть детальный процесс взаимодействия с удаленным сервером).
---
Если сервер 1С работает под управлением операционной системы Linux, предыдущие способы нам не подойдут, так как WinSCP ориентирован исключительно на среду Windows. В этом случае на помощь приходит современная разработка отечественного сообщества 1С — Открытый Пакет Интеграций (OPI / OpenIntegrations).
Это открытый фреймворк для 1С, поставляемый в виде удобного расширения базы данных или набора внешних компонент. В состав OPI входит мощная кроссплатформенная Native API внешняя компонента для работы по протоколам SSH и SFTP, которая одинаково стабильно работает как на серверах под Windows, так и на CentOS, Debian, Ubuntu и других дистрибутивах Linux.
Рассмотрим, как выглядит отправка файлов с использованием OPI. Компонента пакета абстрагирует разработчика от низкоуровневых операций, предоставляя лаконичный и понятный интерфейс общего модуля:
&НаСервере
Процедура ОтправитьФайлПоSFTP_OPI(ПутьКЛокальномуФайлу, ИмяФайлаНаСервере)
// Настраиваем структуру параметров подключения к удаленному SSH-серверу
ПараметрыПодключения = Новый Структура;
ПараметрыПодключения.Вставить("Адрес", "sftp.example.com");
ПараметрыПодключения.Вставить("Порт", 22);
ПараметрыПодключения.Вставить("Пользователь", "sftp_user");
ПараметрыПодключения.Вставить("Пароль", "SuperSecurePassword123");
// OPI также позволяет авторизоваться по приватному SSH-ключу вместо пароля,
// что является наиболее надежным стандартом в среде Linux-администрирования.
// ПараметрыПодключения.Вставить("ПутьККлючу", "/home/usr1cv8/.ssh/id_rsa");
// ПараметрыПодключения.Вставить("ПарольКлюча", "PassphraseIfExist");
Попытка
// Вызываем метод отправки файла из общего модуля Открытого Пакет Интеграций.
// OPI самостоятельно инициализирует внешнюю компоненту, откроет сокет,
// авторизуется на сервере, передаст файл и закроет соединение.
Результат = OPI_SFTP.ОтправитьФайл(ПараметрыПодключения, ПутьКЛокальномуФайлу, "/upload/" + ИмяФайлаНаСервере);
Если Результат.Статус = Ложь Тогда
ВызватьИсключение Результат.СообщениеОбОшибке;
КонецЕсли;
ЗаписьЖурналаРегистрации("OPI SFTP", УровеньЖурналаРегистрации.Информация, , , "Файл успешно передан через OPI.");
Исключение
ТекстОшибки = "Ошибка передачи через OPI SFTP: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("OPI SFTP", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецПопытки;
КонецПроцедуры
Преимущества данного подхода: Полная кроссплатформенность из коробки, поддержка авторизации по SSH-ключам, высокая скорость работы Native API компоненты, отсутствие зависимостей от внешнего установленного ПО (такого как WinSCP или Java-серверы), чистота и лаконичность кода в 1С.
---
Если ваш сервер приложений 1С крутится на ОС Linux, и вам не хочется устанавливать дополнительные расширения или внешние компоненты, можно воспользоваться штатными утилитами, которые установлены практически в каждом дистрибутиве Linux по умолчанию — это консольные клиенты scp или sftp.
Для того чтобы 1С могла отправлять файлы в фоновом режиме без интерактивного ввода пароля, необходимо настроить авторизацию по SSH-ключам без пароля между сервером 1С и целевым SFTP-сервером. Выполним предварительные шаги настройки в консоли Linux-сервера 1С:
usr1cv8).ssh-keygen -t rsa -b 4096 (на все вопросы нажимайте Enter, чтобы создать ключ без кодовой фразы).ssh-copy-id user@sftp.example.com.ssh user@sftp.example.com. Если подключение произошло без запроса пароля — настройка выполнена успешно.Теперь мы можем написать простой и производительный код в 1С, который будет вызывать штатную утилиту scp для защищенного копирования файла:
&НаСервере
Процедура ОтправитьФайлПоSFTP_Linux_SCP(ПутьКЛокальномуФайлу, ИмяФайлаНаСервере)
// Формируем Linux-команду для копирования файла по протоколу SCP.
// Пример команды: scp /tmp/file.txt sftp_user@sftp.example.com:/upload/file.txt
ШаблонКоманды = "scp ""%1"" sftp_user@sftp.example.com:/upload/""%2""";
СтрокаКоманды = СтрШаблон(ШаблонКоманды, ПутьКЛокальномуФайлу, ИмяФайлаНаСервере);
Попытка
// Запускаем системную команду. Третий параметр "Истина" обеспечивает синхронное ожидание.
КодВозврата = ЗапуститьПриложение(СтрокаКоманды, , Истина);
Если КодВозврата <> 0 Тогда
ВызватьИсключение "Утилита scp вернула код ошибки: " + КодВозврата;
КонецЕсли;
ЗаписьЖурналаРегистрации("Linux SCP", УровеньЖурналаРегистрации.Информация, , , "Файл успешно отправлен по SCP.");
Исключение
ТекстОшибки = "Ошибка при вызове утилиты scp: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Linux SCP", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецПопытки;
КонецПроцедуры
Преимущества данного подхода: Максимальная скорость передачи, отсутствие накладных расходов на COM/NET-маршалинг, использование проверенных системных утилит ядра Linux, безопасность за счет использования асимметричных ключей шифрования.
---
В крупных корпоративных системах с повышенными требованиями к отказоустойчивости и информационной безопасности часто применяется паттерн с использованием микросервиса-посредника (HTTP-to-SFTP Proxy). 1С общается с прокси-сервером по простому протоколу HTTP/HTTPS, используя полностью штатный объект HTTPСоединение, а прокси-сервер принимает файл и пересылает его конечному клиенту по SFTP/SSH. Для организации сетевой передачи файлов и интеграции также подойдёт инструмент для обмена данными между базами 1С и приложениями.
Схема взаимодействия выглядит следующим образом:
Посмотрим на пример кода в 1С для работы по этой схеме:
&НаСервере
Процедура ОтправитьФайлЧерезПрокси(ПутьКЛокальномуФайлу, ИмяФайлаНаСервере)
// Настраиваем HTTP-соединение с нашим промежуточным микросервисом
НТТРСоединение = Новый HTTPСоединение("sftp-proxy.local", 8080, , , , 60);
// Формируем POST-запрос
HTTPЗапрос = Новый HTTPЗапрос("/upload-to-sftp");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/octet-stream");
HTTPЗапрос.Заголовки.Вставить("X-Target-Filename", ИмяФайлаНаСервере);
// Помещаем локальный файл в тело запроса
HTTPЗапрос.УстановитьИмяФайлаТела(ПутьКЛокальномуФайлу);
Попытка
HTTPОтвет = НТТРСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
ЗаписьЖурналаРегистрации("SFTP HTTP Proxy", УровеньЖурналаРегистрации.Информация, , , "Файл успешно отправлен через прокси-сервер.");
Иначе
ВызватьИсключение "Прокси вернул ошибку: " + HTTPОтвет.ПолучитьТелоКакСтроку();
КонецЕсли;
Исключение
ТекстОшибки = "Ошибка взаимодействия с SFTP прокси-сервером: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("SFTP HTTP Proxy", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецПопытки;
КонецПроцедуры
Преимущества данного подхода: Полное отсутствие сторонних библиотек на сервере 1С, кроссплатформенность, высокая отказоустойчивость, централизованное логирование всех интеграций на стороне микросервиса.
---
Выбор конкретного метода отправки файлов по протоколу SFTP зависит от архитектуры вашей ИТ-инфраструктуры: