Справочник настроек прокси инструкции по программам

1С прокси: настройка обмена с внешними сервисами через ИнтернетПрокси и HTTPСоединение

1С:Предприятие обращается наружу за курсами валют, за сведениями о контрагентах из открытых реестров и за подтверждением выгрузок на торговые площадки, и весь исходящий трафик уходит через объекты платформы HTTPСоединение и WSСсылка. Страница показывает, как направить эти вызовы через посредника: собрать объект ИнтернетПрокси, развести глобальную настройку конфигурации и настройку на одно соединение, спрятать пароль от лишних глаз и заставить обмен отрабатывать из регламентного задания на сервере.

У меня в поддержке три базы, где обмен с внешними сервисами идёт круглосуточно. Первая тянет курсы каждое утро, вторая раз в час забирает статусы заказов с маркетплейса, третья по кнопке проверяет реквизиты контрагента перед проведением документа. Все три ходят наружу через посредника. Толковой сводки по этому вопросу я нигде не нашёл: половина форумных советов относится к клиентской части и на сервере не работает, вторая половина обрывается на строчке с конструктором. Ниже собран порядок, который я довёл до рабочего состояния на всех трёх базах.

1. Что понадобится

Платформа 8.3.14 либо новее: объект ИнтернетПрокси и его метод Установить в этих сборках ведут себя одинаково, различия начинаются только в поведении OpenSSL на серверах под Linux. Нужен доступ в конфигуратор, право администрирования в самой базе и учётная запись администратора кластера, если база работает в клиент-серверном варианте. Отдельно приготовьте доступ к машине, где крутится служба агента сервера: половина разбора в конце страницы упирается именно в неё.

Строка подключения понадобится в одном из двух видов. Форма IP:PORT подходит, когда внешний адрес сервера 1С внесён в кабинете привязкой и порт пускает вас по адресу источника. Форма IP:PORT:LOGIN:PASS подходит для доступа по паре логина и пароля. Список у меня выдаётся ссылкой сразу в обоих форматах, поэтому я беру нужную форму и подставляю значения в код без ручной разборки текста. Примеры на странице написаны на адресе 203.0.113.44 и порте 8000, меняйте цифры, структуру строк оставляйте как есть.

Для серверной части я держу приватные серверные адреса под обмен из учётной системы: в пакет входят две привязки, менять их в кабинете можно свободно, и это закрывает случай, когда рядом с продуктивным сервером стоит копия базы для отладки. Пул примерно на 12 000 активных адресов, ротация внутри него идёт автоматически, поэтому строка подключения в коде остаётся одна и та же от прогона к прогону. Трафик безлимитный, что для ночных выгрузок каталога заметно упрощает арифметику. Включение пакета занимает около 5 минут, а бесплатный тест до 2 часов покрывает и первую проверку из конфигуратора, и один цикл регламентного задания.

2. Объект ИнтернетПрокси и его конструктор

Всё, что платформа знает о посреднике, живёт в объекте ИнтернетПрокси. Конструктор принимает один логический параметр. Значение Истина велит платформе взять настройки операционной системы, значение Ложь создаёт пустой объект, который вы заполняете руками. Я всегда собираю объект руками: поведение кода тогда одинаково на сервере под Windows, на сервере под Linux и в файловой базе на ноутбуке разработчика.

// посредник задаётся явно, системные параметры Windows платформа при этом игнорирует
Посредник = Новый ИнтернетПрокси(Ложь);
Посредник.Установить("http",  "203.0.113.44", 8000, "u4821", "Rw7fQ2mE", Ложь);
Посредник.Установить("https", "203.0.113.44", 8000, "u4821", "Rw7fQ2mE", Ложь);
Посредник.НеИспользоватьПроксиДляАдресовЛокальнойСети = Истина;
Посредник.НеИспользоватьПроксиДляАдресов.Добавить("srv-1c.corp.local");
Посредник.НеИспользоватьПроксиДляАдресов.Добавить("10.20.0.0/16");

Метод Установить вызывается отдельно для каждого протокола. Про это спотыкаются чаще всего: обмен настроили на http, а сервис отвечает по HTTPS, и запрос спокойно уходит мимо посредника напрямую. Обе строки нужны всегда, даже когда вы уверены, что наружу пойдёт только защищённый канал.

Параметр метода УстановитьЧто задаётПример значенияЗамечание
Протоколсхема соединения с целевым узлом"https"строчными буквами, поддерживаются http, https, ftp, ftps
Серверадрес самого посредника"203.0.113.44"без схемы и без порта в строке
Портпорт посредника8000тип Число, строка тут отвергается
Пользовательлогин доступа к порту"u4821"пустая строка при доступе по привязке адреса
Парольпароль доступа к порту"Rw7fQ2mE"пустая строка при доступе по привязке адреса
ИспользоватьАутентификациюОСпередача учётной записи WindowsЛожьИстина рассчитана на корпоративный шлюз с NTLM

Заполненный объект умеет отвечать на вопросы о самом себе, и это выручает при отладке. Метод НастроенДляПротокола показывает, дошла ли настройка до нужной схемы, а Сервер и Порт печатают то, что реально записано внутри:

Если Посредник.НастроенДляПротокола("https") Тогда
    ЗаписьЖурналаРегистрации("Обмен.Посредник", УровеньЖурналаРегистрации.Информация, , ,
        "Посредник для https: " + Посредник.Сервер("https")
        + ":" + Формат(Посредник.Порт("https"), "ЧГ=0"));
Иначе
    ВызватьИсключение "Посредник для https не настроен";
КонецЕсли;

Список исключений собирается свойством НеИспользоватьПроксиДляАдресов. Туда кладутся имена узлов и подсети, к которым платформа пойдёт напрямую: внутренний веб-сервер публикации, шлюз ЭДО внутри периметра, тестовый стенд в соседней стойке. Свойство НеИспользоватьПроксиДляАдресовЛокальнойСети выключает посредника для коротких имён без точки. Я включаю его почти всегда, потому что внутренние вызовы между базами одного контура через внешний порт гонять смысла нет.

3. Глобальная настройка конфигурации и настройка на одно соединение

У платформы есть два способа определить, куда пойдёт исходящий запрос. Первый способ глобальный: конфигурация хранит параметры посредника у себя и подставляет их во все обмены. Второй способ точечный: код собирает объект ИнтернетПрокси прямо перед вызовом и передаёт его в конструктор соединения. Разница между ними видна в момент, когда часть сервисов должна идти через посредника, а внутренние адреса остаются на прямом канале.

Уровень настройкиГде хранитсяНа что действуетКто может изменить
Системные параметры Windowsветка реестра учётной записи, раздел Internet Settingsтолько вызов Новый ИнтернетПрокси(Истина)администратор машины
Настройки конфигурации на клиентехранилище общих настроек, профиль пользователяобмены, запущенные из сеанса этого пользователясам пользователь в форме настроек
Настройки конфигурации на сервереконстанта либо безопасное хранилище базыфоновые и регламентные задания, серверные вызовыадминистратор базы
Объект в коде перед вызовомпеременная в модуле, живёт до конца процедурыровно то соединение, куда объект переданразработчик конфигурации

В типовых конфигурациях на библиотеке стандартных подсистем форма настроек лежит в разделе администрирования, подраздел интернет-поддержки и сервисов. Там две группы полей, отдельно для клиента и отдельно для сервера, и вторая группа спасает ровно тот случай, когда обмен работает по кнопке и молчит по расписанию. Прочитать сохранённое из кода даёт функция ПолучитьПрокси общего модуля ПолучениеФайловИзИнтернета: она возвращает готовый объект ИнтернетПрокси для указанного протокола.

Своим конфигурациям я делаю одну общую функцию и зову её отовсюду. Тогда адрес посредника лежит в единственном месте, а правка при переезде на другой порт занимает одну строку:

// Общий модуль ОбменСВнешнимиСервисами, вызывается только на сервере
Функция ПосредникОбмена() Экспорт

    Настройки = Константы.ПараметрыПосредникаОбмена.Получить().Получить();
    Если Настройки = Неопределено Или ПустаяСтрока(Настройки.Сервер) Тогда
        Возврат Новый ИнтернетПрокси(Ложь); // прямой канал
    КонецЕсли;

    Прокси = Новый ИнтернетПрокси(Ложь);
    Для Каждого Схема Из СтрРазделить("http,https", ",") Цикл
        Прокси.Установить(Схема, Настройки.Сервер, Настройки.Порт,
            Настройки.Логин, Настройки.Пароль, Ложь);
    КонецЦикла;
    Прокси.НеИспользоватьПроксиДляАдресовЛокальнойСети = Истина;

    Для Каждого Адрес Из СтрРазделить(Настройки.Исключения, ";", Ложь) Цикл
        Прокси.НеИспользоватьПроксиДляАдресов.Добавить(СокрЛП(Адрес));
    КонецЦикла;

    Возврат Прокси;

КонецФункции

Константа с типом ХранилищеЗначения принимает структуру целиком, и добавление нового поля потом обходится без переделки метаданных. Ветка с пустым сервером возвращает объект без настроек: соединение уйдёт напрямую, и обмен продолжит работать на стенде, где посредник не нужен. Такая ветка избавила меня от отдельной сборки конфигурации для тестового контура.

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

4. Передача посредника в объект HTTPСоединение

Конструктор HTTPСоединение принимает посредника пятым параметром. Первым идёт имя узла без схемы: строка вида https://api.example.net тут вызовет отказ, потому что платформа ждёт только хост. Протокол задаётся сочетанием порта и последнего параметра с защищённым соединением.

Соединение = Новый HTTPСоединение(
    "api.example.net",                        // только имя узла, без схемы и без пути
    443,
    ,                                         // логин целевого сервиса
    ,                                         // пароль целевого сервиса
    ОбменСВнешнимиСервисами.ПосредникОбмена(),
    60,                                       // таймаут в секундах
    Новый ЗащищенноеСоединениеOpenSSL());

Запрос = Новый HTTPЗапрос("/v3/rates?base=EUR&symbols=USD,CNY");
Запрос.Заголовки.Вставить("Accept", "application/json");
Запрос.Заголовки.Вставить("User-Agent", "1c-exchange/2.1");

Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
    ВызватьИсключение "Курсы: код состояния " + Ответ.КодСостояния;
КонецЕсли;

Тело = Ответ.ПолучитьТелоКакСтроку("UTF-8");
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Тело);
Курсы = ПрочитатьJSON(Чтение, Истина);

Седьмой параметр про защищённое соединение забывают чаще прочего. Без него платформа пытается говорить по открытому каналу на порт 443, и в журнале появляется отказ на согласовании шифрования. Обратный случай тоже встречается: объект ЗащищенноеСоединениеOpenSSL передан, а порт указан 80, и целевой сервер закрывает соединение молча.

Отправка данных наружу выглядит так же, меняется только метод и наполнение тела:

Запрос = Новый HTTPЗапрос("/v1/offers/batch");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенСервиса);
Запрос.УстановитьТелоИзСтроки(ТелоJSON, КодировкаТекста.UTF8,
    ИспользованиеByteOrderMark.НеИспользовать);

Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Метка порядка байтов в начале тела ломает разбор JSON на стороне половины сервисов, поэтому третий параметр я задаю явно каждый раз. Ошибка из-за неё выглядит обидно: код 400 с сообщением про неожиданный символ в первой позиции, и посредник тут ни при чём.

Таймаут в шестом параметре считается в секундах и покрывает всю операцию целиком. Ноль снимает ограничение сверху, что для обмена по расписанию заканчивается зависшим фоновым заданием на сутки. Я ставлю 60 для запросов за справочниками и 180 для выгрузки крупных пакетов. Один и тот же объект соединения переиспользуется для серии запросов к одному узлу, и это экономит рукопожатие на каждом вызове.

Когда сервис требует именно защищённого канала до самого посредника и отдаёт крупные тела, я перевожу обмен на HTTPS-прокси для выгрузок из учётной системы. Порт при этом один и тот же для обеих схем, разбираться со вторым набором значений в константе не приходится.

5. WSСсылка, WSПрокси и обмен по SOAP

Веб-сервисы государственных реестров и часть корпоративных шлюзов работают по SOAP, и платформа общается с ними через WSСсылку. Статическая ссылка лежит в метаданных конфигурации, её описание загружается в конфигураторе с машины разработчика. Отсюда первая тонкость: загрузка WSDL в конфигураторе идёт через настройки клиентского компьютера, а рабочий вызов идёт с сервера. Обе точки нужно настроить, иначе описание загрузится, а обмен встанет.

Посредник передаётся в метод СоздатьWSПрокси пятым параметром:

WSПрокси = WSСсылки.ПроверкаКонтрагентов.СоздатьWSПрокси(
    "http://example.net/party",                // URI пространства имён
    "PartyCheckService",                       // имя сервиса
    "PartyCheckSoap",                          // имя порта
    60,                                        // таймаут
    ОбменСВнешнимиСервисами.ПосредникОбмена(), // посредник
    Новый ЗащищенноеСоединениеOpenSSL());

WSПрокси.Пользователь = ДоступКСервису.Логин;
WSПрокси.Пароль       = ДоступКСервису.Пароль;

Результат = WSПрокси.CheckParty("7736207543");

Свойства Пользователь и Пароль у объекта WSПрокси относятся к учётной записи самого сервиса. Логин посредника туда класть бесполезно, он живёт внутри объекта ИнтернетПрокси и передаётся отдельно. Путаница между двумя парами логина и пароля даёт ровный поток отказов 401 при исправной сети.

Динамическое описание собирается парой объектов, и посредник нужен уже на этапе загрузки схемы:

Определения = Новый WSОпределения(
    "https://example.net/ws/party?wsdl",
    ДоступКСервису.Логин,
    ДоступКСервису.Пароль,
    ОбменСВнешнимиСервисами.ПосредникОбмена(),
    60,
    Новый ЗащищенноеСоединениеOpenSSL());

WSПрокси = Новый WSПрокси(Определения,
    "http://example.net/party", "PartyCheckService", "PartyCheckSoap");
WSПрокси.Пользователь = ДоступКСервису.Логин;
WSПрокси.Пароль       = ДоступКСервису.Пароль;

Пропущенный четвёртый параметр в конструкторе WSОпределения даёт самую невнятную ошибку из всех, что встречались мне в обменах: платформа пишет про невозможность загрузить WSDL, и по тексту совершенно неясно, что запрос за описанием ушёл напрямую и упёрся в фильтр исходящих соединений. Правило простое: посредник кладётся в каждый конструктор, где он предусмотрен сигнатурой.

Отдельно держите в голове объект FTPСоединение и глобальные процедуры получения файлов. FTPСоединение принимает посредника шестым параметром, а процедура ПолучитьФайл смотрит на свои умолчания. Если обмен таскает архивы прайсов по FTP, посредник туда тоже передаётся явно.

6. Где хранить логин и пароль

Пароль доступа к порту попадает в базу, и дальше начинается разговор о том, кто его сможет прочитать. Я перебрал три пути и пользуюсь двумя из них.

СпособКто видит значениеПопадает в выгрузку базыКогда я выбираю
Реквизит константы с типом Строкалюбой пользователь с правом чтения константыда, открытым текстомникогда на продуктиве
Безопасное хранилище библиотекикод в привилегированном режимеда, в закрытом видеобмен идёт с нескольких машин с меняющимися адресами
Привязка внешнего адреса серверапароля в базе нет вовсенечего выгружатьсервер со стабильным внешним адресом

Строковая константа проигрывает по всем статьям. Значение видно в форме настроек, видно в консоли запросов, уезжает в выгрузку и в резервную копию, а после передачи базы подрядчику на доработку живёт уже у него. Держать там пароль от внешнего порта я перестал после первого же разбора инцидента.

Безопасное хранилище библиотеки стандартных подсистем закрывает вопрос аккуратно. Запись и чтение идут в привилегированном режиме, обычному пользователю содержимое недоступно даже через отчёт по регистру:

УстановитьПривилегированныйРежим(Истина);

ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(
    Справочники.НастройкиОбменов.ВнешниеСервисы,
    Новый Структура("Логин, Пароль", "u4821", "Rw7fQ2mE"),
    "ДоступКПосреднику");

Доступ = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(
    Справочники.НастройкиОбменов.ВнешниеСервисы, "ДоступКПосреднику");

УстановитьПривилегированныйРежим(Ложь);

Владельцем выступает ссылка на элемент справочника настроек, ключ задаёт строку внутри хранилища. Один владелец спокойно хранит несколько ключей, поэтому доступ к посреднику и токен целевого сервиса лежат рядом, без лишних объектов метаданных. Не забудьте снять привилегированный режим сразу после чтения: оставленный включённым режим тянется до конца вызова и снимает проверку прав со всего кода ниже.

Третий путь избавляет от пароля целиком. Внешний адрес сервера 1С вносится привязкой в кабинете, порт пускает вас по адресу источника, и в базе не остаётся ни одной строки с секретом. Для продуктивного сервера со стабильным внешним адресом я выбираю именно так и подключаю приватный пул с привязкой адреса сервера. Пятый и шестой параметры метода Установить при этом остаются пустыми строками, а обмен стартует молча в любое время суток. Вторая привязка из пакета уходит на резервный узел кластера, и переключение при отказе основного сервера обходится без правки константы. Помните про арифметику потоков: обычный пакет даёт 1000, корпоративный до 3000, пакеты по потокам не складываются, при двух активных привязках лимит делится пополам. Для параллельной выгрузки в несколько потоков считайте по фактической половине.

7. Сервер 1С под служебной учётной записью и системные параметры Windows

Вот место, где ломается больше половины настроек. Обмен по кнопке работает, обмен по расписанию молчит, а код между ними один и тот же. Причина в том, что серверный код исполняется процессом rphost, а тот запущен службой агента сервера от служебной учётной записи. Ваши личные настройки сети в этот процесс не попадают.

Где исполняется кодЧью учётную запись видит платформаКакие системные параметры читает Новый ИнтернетПрокси(Истина)
Модуль формы, директива НаКлиентепользователь, вошедший в систему Windowsветку Internet Settings профиля этого пользователя
Серверный вызов из формы, файловая базапользователь, вошедший в систему Windowsту же ветку профиля пользователя
Серверный вызов, клиент-серверная базаучётная запись службы агента сервераветку профиля служебной учётной записи
Фоновое или регламентное заданиеучётная запись службы агента серверату же ветку служебной учётной записи
Сервер под Linuxпользователь usr1cv8переменные окружения процесса, ветки реестра нет вовсе

Служба по умолчанию стартует от локальной учётной записи USR1CV8, и её ветка реестра пустая. Профиль такой учётки не загружается при обычной работе службы, поэтому конструктор с параметром Истина возвращает объект без настроек, и запрос уходит прямым каналом в закрытый фильтр. Отсюда моё правило: параметр Истина в серверном коде не появляется никогда.

Вторая ловушка касается команды netsh winhttp set proxy. Она пишет в машинное хранилище WinHTTP, которым пользуются службы Windows. Платформа 1С к этому хранилищу не обращается, и прописанный там посредник на обмен из базы не влияет совершенно. Проверить содержимое обоих хранилищ можно с той же машины:

netsh winhttp show proxy
reg query "HKU\S-1-5-21-...-1013\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer

Третья тонкость про внешний адрес. Порт посредника видит адрес, с которого пришло соединение, и смена учётной записи службы на него никак не влияет. Привязывать в кабинете нужно внешний адрес сервера приложений, каким его видит внешняя сторона. У сервера за NAT локальный адрес интерфейса и внешний адрес различаются, и путаница между ними даёт постоянный отказ 403 при рабочей сети. Для парка серверов, где обмены живут годами без правок, я держу HTTP-прокси под серверные обмены 1С: строка подключения короткая, привязка правится в кабинете, конфигурацию при этом трогать не нужно.

Ещё одна деталь про кластер. Рабочие процессы могут быть подняты на нескольких машинах, и обмен уйдёт с той, куда попал сеанс. Внешние адреса всех машин кластера должны быть внесены привязками, либо доступ идёт по логину с паролем. Я потратил вечер на разбор обмена, который отрабатывал через раз, пока не сообразил посмотреть, сколько рабочих серверов в кластере.

8. Регламентные задания и обмен по расписанию

Регламентное задание запускает свой метод в фоновом сеансе на сервере. Клиентского контекста там нет, форм нет, сообщения пользователю уходят в пустоту. Всё, что настроено в клиентской части конфигурации, для этого сеанса недоступно. Настройка посредника поэтому берётся серверная, из константы либо безопасного хранилища.

// Общий модуль ОбменСВнешнимиСервисамиРегламент, вызывается заданием
Процедура ЗагрузитьСправочникиИКурсы() Экспорт

    ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(
        Метаданные.РегламентныеЗадания.ЗагрузкаВнешнихДанных);

    Посредник = ОбменСВнешнимиСервисами.ПосредникОбмена();
    Ошибок = 0;

    Для Каждого Источник Из ОбменСВнешнимиСервисами.СписокИсточников() Цикл
        Попытка
            ОбменСВнешнимиСервисами.ЗабратьПорцию(Источник, Посредник);
        Исключение
            Ошибок = Ошибок + 1;
            ЗаписьЖурналаРегистрации("Обмен.ВнешниеСервисы",
                УровеньЖурналаРегистрации.Ошибка,
                Метаданные.Справочники.НастройкиОбменов,
                Источник.Ссылка,
                ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
    КонецЦикла;

    Если Ошибок > 0 Тогда
        ВызватьИсключение "Обмен завершён с отказами: " + Ошибок;
    КонецЕсли;

КонецПроцедуры

Попытка вокруг каждого источника нужна для того, чтобы один недоступный сервис не сносил весь цикл. Общий счётчик отказов в конце поднимает исключение, и задание помечается аварийным: платформа тогда включает свой механизм повторов. Настраивается он двумя реквизитами в списке регламентных заданий, число повторов при аварийном завершении и интервал между ними. Я ставлю 3 повтора с интервалом 300 секунд, чего хватает на короткую недоступность целевого сервиса.

Расписание правится из конфигуратора либо кодом. Второй путь удобнее для типовых, где список заданий закрыт от изменения:

Задание = РегламентныеЗадания.НайтиПредопределенные(
    Метаданные.РегламентныеЗадания.ЗагрузкаВнешнихДанных)[0];

Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодПовтораДней = 1;
Расписание.ВремяНачала = Дата(1, 1, 1, 6, 30, 0);
Расписание.ПериодПовтораВТечениеДня = 3600;
Расписание.ВремяКонца = Дата(1, 1, 1, 22, 0, 0);

Задание.Расписание = Расписание;
Задание.Использование = Истина;
Задание.Записать();

В файловой базе регламентные задания сами по себе не запускаются. Их выполняет отдельный сеанс, который держат открытым, либо внешний вызов через ВыполнитьОбработкуЗаданий из скрипта. Для файловой базы под обменом это лишний повод перенести настройку посредника в код: сеанс исполнителя стартует от учётной записи планировщика, и его сетевые параметры отличаются от ваших.

Долгие обмены удобно наблюдать по одному месту. Я завожу отдельный регистр сведений со строкой на каждый прогон: время старта, длительность, число обработанных строк и внешний адрес, который вернул сервис эха. Утренний взгляд на него занимает секунд десять и показывает картину за всю ночь. Стенды, которые живут дольше пары суток, я держу на месячном сроке доступа к пулу, чтобы срок перекрывал полный цикл наблюдений без переподключений посреди отладки.

9. Проверка после настройки

Первая проверка сравнивает два адреса подряд, прямой и через посредника. Обработку я делаю внешней, чтобы гонять её на любой базе без правки конфигурации:

&НаСервере
Функция ВнешнийАдрес(Прокси)
    Соединение = Новый HTTPСоединение("api.ipify.org", 443, , , Прокси, 30,
        Новый ЗащищенноеСоединениеOpenSSL());
    Ответ = Соединение.Получить(Новый HTTPЗапрос("/"));
    Возврат СокрЛП(Ответ.ПолучитьТелоКакСтроку("UTF-8"));
КонецФункции

&НаСервере
Процедура СверитьНаСервере()
    Прямо  = ВнешнийАдрес(Новый ИнтернетПрокси(Ложь));
    Черезп = ВнешнийАдрес(ОбменСВнешнимиСервисами.ПосредникОбмена());
    ЗаписьЖурналаРегистрации("Обмен.Проверка", УровеньЖурналаРегистрации.Информация, , ,
        "прямо: " + Прямо + " ; через посредника: " + Черезп);
КонецПроцедуры

Значения обязаны различаться. Совпадение говорит, что запрос ушёл мимо посредника, и причину ищите в списке исключений либо в незаполненном протоколе. Повторите вызов пять раз подряд: второе значение будет меняться от прогона к прогону, ротация внутри пула работает без вашего участия и на код никак не влияет.

Вторая проверка смотрит на заголовки ответа. Сервис эха с расширенным выводом печатает то, что реально дошло до целевого узла:

Соединение = Новый HTTPСоединение("httpbin.org", 443, , , ПосредникОбмена(), 30,
    Новый ЗащищенноеСоединениеOpenSSL());
Ответ = Соединение.Получить(Новый HTTPЗапрос("/anything"));
Сообщить(Ответ.КодСостояния);
Сообщить(Ответ.ПолучитьТелоКакСтроку("UTF-8"));

Третья проверка обязательна, и делать её нужно от лица сервера. Клиентский вызов ничего не докажет: он идёт с вашей машины и с вашими настройками. Заведите разовое фоновое задание, которое пишет результат в журнал регистрации, запустите его руками и прочитайте запись:

Параметры = Новый Массив;
ФоновыеЗадания.Выполнить("ОбменСВнешнимиСервисами.ПроверкаПосредника",
    Параметры, "проверка-посредника", "Разовая проверка посредника");

Читается журнал выгрузкой в таблицу значений, отбор ставится по имени события и дате:

Отбор = Новый Структура;
Отбор.Вставить("ДатаНачала", НачалоДня(ТекущаяДатаСеанса()));
Отбор.Вставить("Событие", "Обмен.Проверка");

Таблица = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(Таблица, Отбор, , , 200);

Для Каждого Строка Из Таблица Цикл
    Сообщить(Формат(Строка.Дата, "ДЛФ=DT") + " | " + Строка.Пользователь
        + " | " + Строка.Комментарий);
КонецЦикла;

Колонка с пользователем показывает главное. Запись от служебной учётной записи агента сервера означает, что проверка прошла именно в том контексте, в котором будет работать обмен по расписанию. Запись от вашего имени означает, что код выполнился в вашем сеансе, и вывод про сеть в этом случае ни о чём не говорит. Я прогоняю эту пробу после каждой правки константы, привычка стоит пятнадцати секунд и снимает почти весь класс расхождений между кнопкой и расписанием.

Когда картина по сети остаётся мутной, включите технологический журнал на время прогона. В файле logcfg.xml каталога конфигурации сервера достаточно события EXCP и события CALL с длительностью: тексты сетевых отказов там подробнее того, что попадает в журнал регистрации, и в них видно, до какого узла платформа реально пыталась достучаться.

10. Разбор ошибок

Сообщение платформыПричинаЧто делать
Ошибка работы с Интернет: HTTP статус: 407 (Proxy Authentication Required)логин с паролем не дошли до объекта посредниказаполнить пятый и шестой параметры метода Установить либо перейти на привязку адреса
Ошибка работы с Интернет: HTTP статус: 403 (Forbidden)внешний адрес сервера приложений в кабинете отсутствуетвнести внешний адрес машины привязкой и повторить прогон
Ошибка при вызове конструктора (HTTPСоединение): Недопустимое значение параметра (параметр номер '1')в имя узла попала схема https:// либо путьоставить в первом параметре только хост
Ошибка работы с Интернет: Соединение с сервером не установленопорт посредника закрыт исходящим фильтром на самом серверепроверить доступность порта с машины сервера приложений
Ошибка работы с Интернет: Удаленный узел не прошел проверкуседьмой параметр конструктора пуст либо цепочка сертификатов неполнаяпередать Новый ЗащищенноеСоединениеOpenSSL(), доложить корневой сертификат
Ошибка работы с Интернет: Превышено время ожиданиятаймаут короче времени ответа сервисаподнять шестой параметр конструктора до 120 секунд
Ошибка при вызове метода контекста (СоздатьWSПрокси): Ошибка загрузки WSDLпосредник не передан пятым параметром, запрос за схемой ушёл напрямуюдобавить объект посредника в вызов и в конструктор WSОпределения
Ошибка работы с Интернет: Couldn't resolve proxy nameна сервере под Linux имя посредника не разрешаетсяписать в поле сервера адрес цифрами
Значение не является значением объектного типа (Установить)переменная посредника получила Неопределено из константыдобавить ветку с пустой настройкой в общую функцию
Ошибка при вызове метода контекста (ПрочитатьДанныеИзБезопасногоХранилища): Недостаточно правчтение идёт без привилегированного режимаобернуть вызов установкой привилегированного режима
Ошибка работы с Интернет: HTTP статус: 401 (Unauthorized)в свойства WSПрокси попал логин посредникаразвести учётную запись сервиса и учётную запись порта
Ошибка работы с Интернет: HTTP статус: 429 (Too Many Requests)темп выгрузки выше того, что принимает целевой сервисдобавить паузу между порциями, снизить параллелизм заданий
Ошибка работы с Интернет: SSL: certificate verify failedна сервере под Linux пустое хранилище доверенных корнейустановить пакет с корневыми сертификатами в систему
Регламентное задание завершилось аварийно, ниже в журнале сетевой отказобмен по кнопке работает, задание идёт от служебной учётной записиперенести параметры посредника в серверную настройку конфигурации
Код состояния 200, тело пустое, отказов в журнале нетответ прочитан методом для двоичных данныхчитать тело методом ПолучитьТелоКакСтроку с указанием кодировки

Две строки заслуживают отдельного комментария. Отказ 407 при заполненных полях логина я разбирал трижды, и каждый раз причина сидела в протоколе: метод Установить был вызван только для схемы http, а сервис отвечал по HTTPS. Платформа в такой ситуации молча идёт мимо посредника, доходит до фильтра и возвращает текст, по которому догадаться о пропущенной строке трудно.

Вторая строка про рабочую кнопку при мёртвом расписании. Отладка тут короткая: запустите тот же метод фоновым заданием и посмотрите в журнал регистрации на колонку пользователя. Расхождение станет видно сразу, и дальше остаётся перенести параметры посредника из клиентской части в серверную либо задать их прямо в общей функции конфигурации.

Смежные серверные сценарии разобраны на соседних страницах справочника: запуск скриптов и заданий по расписанию описан в материале про PowerShell и планировщик заданий, запуск обменов в контейнерах в статье про настройку посредника в Docker, а выгрузка готовых таблиц наружу в инструкции про Google Таблицы и Apps Script. Если тот же сервер должен отдавать посредника всем программам разом, начните с раздела про системные сетевые параметры Windows 11.