Как реализовать отправку файлов из 1С по защищенному протоколу SSH (SFTP)?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе интеграции 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-серверов.

---

Способ 1. Использование WinSCP через COM-объект (для Windows-серверов)

Этот способ является одним из самых популярных и стабильных для серверов под управлением ОС Windows. Мы будем использовать бесплатную и многофункциональную утилиту WinSCP, которая предоставляет собственную сборку .NET библиотеки (WinSCPnet.dll). Эту библиотеку можно зарегистрировать в операционной системе в качестве COM-объекта, что позволит нам управлять передачей файлов напрямую из кода 1С с возможностью перехвата и обработки ошибок.

Рассмотрим пошагово процесс настройки и интеграции:

  1. Скачайте дистрибутив WinSCP (желательно портативную версию или версию с установочным пакетом .NET) с официального сайта.
  2. Найдите в каталоге программы файл WinSCPnet.dll.
  3. Зарегистрируйте библиотеку в операционной системе Windows на сервере 1С. Для этого запустите командную строку от имени администратора и выполните следующую команду (путь к утилите RegAsm может отличаться в зависимости от версии установленного .NET Framework):

%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С, возможность тонкой настройки параметров сессии, перехват исключений через стандартную конструкцию Попытка... Исключение, отсутствие необходимости в создании временных файлов-скриптов.

---

Способ 2. Запуск WinSCP в консольном режиме через файлы сценариев (CLI)

Если по каким-то причинам политика безопасности вашей компании запрещает регистрацию сторонних 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, легко переносится между серверами, прост в отладке (всегда можно открыть текстовый лог-файл и посмотреть детальный процесс взаимодействия с удаленным сервером).

---

Способ 3. Открытый Пакет Интеграций (OPI / OpenIntegrations) — Кроссплатформенное решение (Windows & Linux)

Если сервер 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С.

---

Способ 4. Использование штатных утилит операционной системы Linux (scp / sftp)

Если ваш сервер приложений 1С крутится на ОС Linux, и вам не хочется устанавливать дополнительные расширения или внешние компоненты, можно воспользоваться штатными утилитами, которые установлены практически в каждом дистрибутиве Linux по умолчанию — это консольные клиенты scp или sftp.

Для того чтобы 1С могла отправлять файлы в фоновом режиме без интерактивного ввода пароля, необходимо настроить авторизацию по SSH-ключам без пароля между сервером 1С и целевым SFTP-сервером. Выполним предварительные шаги настройки в консоли Linux-сервера 1С:

  1. Зайдите на сервер под пользователем, от имени которого запущен сервер приложений 1С (обычно это пользователь usr1cv8).
  2. Сгенерируйте пару SSH-ключей командой: ssh-keygen -t rsa -b 4096 (на все вопросы нажимайте Enter, чтобы создать ключ без кодовой фразы).
  3. Скопируйте публичный ключ на целевой SFTP-сервер: ssh-copy-id user@sftp.example.com.
  4. Проверьте ручное беспарольное подключение: 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, безопасность за счет использования асимметричных ключей шифрования.

---

Способ 5. Использование прокси-сервера (архитектурное решение для крупных систем)

В крупных корпоративных системах с повышенными требованиями к отказоустойчивости и информационной безопасности часто применяется паттерн с использованием микросервиса-посредника (HTTP-to-SFTP Proxy). 1С общается с прокси-сервером по простому протоколу HTTP/HTTPS, используя полностью штатный объект HTTPСоединение, а прокси-сервер принимает файл и пересылает его конечному клиенту по SFTP/SSH. Для организации сетевой передачи файлов и интеграции также подойдёт инструмент для обмена данными между базами 1С и приложениями.

Схема взаимодействия выглядит следующим образом:

  1. 1С отправляет POST-запрос с файлом во вложении на внутренний веб-сервис (написанный на Java, Go, Node.js или Python).
  2. Веб-сервис принимает запрос, валидирует его, временно сохраняет файл в оперативную память.
  3. Веб-сервис с помощью стандартных библиотек своего языка программирования (например, JSCH для Java) подключается к SFTP-серверу и загружает файл.
  4. Веб-сервис возвращает в 1С статус выполнения (HTTP-код 200 в случае успеха или 500 с текстом ошибки).

Посмотрим на пример кода в 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 зависит от архитектуры вашей ИТ-инфраструктуры:

← На главную