Что под капотом миграции писем с Exchange Server на Яндекс Почту

Привет, Хабр! Я продолжаю цикл статей, посвящённый разным аспектам администрирования Организаций Яндекс 360 для бизнеса. В этот раз я отойду от принципа туториала и расскажу о том, как появился новый функционал миграции из Exchange Server без сбора паролей и как этот принцип применили для делегированного доступа к почтовым ящикам по протоколу IMAP.

d39e8d154956fc54b6b2dfc7a764c743.jpg

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

В этой статье будет:

  • Краткий обзор принципов миграции

  • Нюансы подключения по IMAP к Microsoft Exchange Server от имени делегированной учетной записи

  • Чтение логов IMAP сервер

  • Обзор делегирования почты по IMAP

Принципы миграции почты в облачные сервисы, такие как Яндекс Почта

Разные спецы вкладывают разный смысл в понятие «миграция почты». Если говорить максимально широко, то миграция почты — это:

  • Создание учётных записей пользователей в целевой системе — таких же, как в системе-источнике

  • Наполнение глобальной адресной книги такими же сущностями: пользователями, внутренними и внешними контактами, списками рассылок с составом

  • Копирование транспортных правил и других конфигурационных параметров почтовой инфраструктуры

  • Копирование писем из системы-источника в целевую систему

  • Копирование контактов, календарных событий, задач и др.

  • Настройка почтовых клиентов пользователей на разных платформах на новую почтовую систему

Глобально существует три подхода к осуществлению миграции почты:

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

Пример: миграция из Exchange Server в Exchange Online. В этом случае используется внутренняя служба Mailbox Replication Service — по названию понятно, чем она умеет заниматься. Exchange Online, или ExO (сокращение напоминает мне об XO;)), знает, как подключиться к Endpoint на наземном Exchange Server. Именно поэтому один из пунктов инструкции по миграции гласит «Включить MRS Proxy», чтобы всякие внешние сервисы типа ExO могли подключиться к Endpoint в локальном сервере.

  1. Между решениями разных производителей, используя API отдающего решения.

Например, Exchange Online имеет на своём борту API. Яндекс 360 использует именно этот API для того, чтобы забрать почту из ExO в Яндекс 360 для бизнеса, не собирая пароли пользователей. В этом случае нужно зарегистрировать приложение через Azure App Registration, выдать права этому приложению на содержимое почтовых ящиков пользователей и запустить миграцию. Аналогичный подход в Google Workspace

  1. Между решениями разных производителей, используя отраслевой стандарт IMAP.

Любое почтовое решение в том или ином виде поддерживает протокол IMAP. Он предназначен для того, чтобы синхронизировать письма в почтовых ящиках по клиент-серверной логике. Если взять Яндекс 360 как целевую систему и Microsoft Exchange Server как сервер-источник, то, зная пароли всех пользователей на Exchange, можно настроить в Яндекс 360 список пользователей, которым нужно мигрировать, со списком паролей. Далее в Яндекс 360 создаётся несколько сборщиков, которые, выступая в роли IMAP-клиента, копируют себе письма из Exchange Server.

У третьего способа есть пара минусов: надо собирать пароли пользователей. «А может, мне вам ещё ключи от квартиры отдать, где деньги лежат?» — спросит пользователь, а ИТ-безопасник покрутит пальцем у виска. Миграция отложится, пока все не пройдут известные пять стадий принятия. В худшем случае она не состоится вообще.И второй минус: по IMAP перенесешь только письма, и придется забыть про другие сущности типа календарей, контактов, задач.

Описанный выше сценарий миграции по IMAP уже давно работает в Яндекс 360. Однако, учитывая популярность Exchange Server, было принято решение улучшить этот сценарий, чтобы не пришлось собирать пароли пользователей. Как настраивать весь процесс миграции таким способом, читайте в моей предыдущей статье.

Реализация делегирования в протоколе IMAP у Microsoft Exchange

Компания Microsoft реализовала прелюбопытный способ делегированного подключения от имени одной учётной записи к почтовому ящику другого пользователя. Мне не удалось найти его описание ни в RFC, ни в публичной официальной документации. Если говорить про делегирование по IMAP, то в RFC подробно описан функционал через команду NAMESPACE, но Microsoft Exchange Server её не поддерживает.

Итак, у вас Exchange Server и на нём настроено делегирование. Учётная запись Delegate имеет полные права на ящик Resource. В таком случае, чтобы настроить Outlook по IMAP и подключиться к делегированному ящику, укажите в поле «Учётная запись» конструкцию example.com/delegate/resource, где:

  • example.com — домен в Active Directory, под которым аутентифицируется пользователь исходного почтового ящика;

  • delegate — имя учётной записи делегата, у которого есть права на ящик ресурса;

  • resource — атрибут alias или mailnickname почтового ящика сотрудника, на который у делегата есть доступ.

Вуаля, вы подключились по IMAP к другому ящику!

Почему так? Для начала обозначу требование: нужно, чтобы почтовый клиент при попытке подключения поддерживал команду LOGIN протокола IMAP. Обратимся к первоисточнику — RFC.

Есть две команды и обе являются стандартными для протокола IMAP:

  • AUTHENTICATE посовременнее. Команда поддерживает всякие «секурные ништяки», а уж если и пересылает пароль в открытом виде, то хотя бы в BASE64.

  • LOGIN постарее. Эту команду не рекомендуют к использованию, особенно когда нет TLS. Всё потому, что она передаёт пароль в явно открытом виде — даже без кодировки BASE64.

Я полностью разделяю такую позицию, касательно рекомендаций не использовать без TLS. Но нам важно знать, что IMAP-реализация в Microsoft Exchange Server не только поддерживает команду LOGIN, но и по-своему интерпретирует её. Пример выше показывает особый принцип интерпретации и бизнес-логики при работе с делегированными ящиками. 

Когда IMAP-клиент передаёт конструкцию example.com/delegate/resource, Exchange Server понимает это так, будто пользователь с учётной записью delegate из домена example.com пытается подключиться к делегированному ящику с алиасом resource. Одно от другого явно отделяет слеш — /. Кстати, один из заказчиков, который переносил несколько тысяч ящиков, столкнулся с тем, что у него всё заработало на слегка иной конструкции: delegate@example.com/resource.

Отмечу, что другие почтовые серверы тоже используют аналогичный приём. Только вместо слеша у них могут быть # или *. Синтаксис тоже может отличаться: например, Dovecot проглатывает конструкцию resource*delegate, а Mirapoint — #resource@example.test#delegate#.

В итоге почтовый клиент подключается к корневой папке почтового ящика с алиасом resource и работает с ним как с родным. Для клиента Exchange Server всё выглядит так, что не придерёшься.

Логи IMAP на стороне Exchange Server

После успешной настройки клиента самое любопытное — взглянуть, как со всем этим работал сервер. Давайте посмотрим логи IMAP-служб. В Exchange таких служб две, и файла с логами тоже два.

Первая служба — Microsoft Exchange IMAP4. Как ясно из описания: Provides Internet Message Access Protocol service to clients. If this service is stopped, clients won’t be able to connect to this computer using the IMAP4 protocol. Служба фактически проксирует клиентские подключения к бэку. Имя файла с логами вида IMAP42024022417–1

Вторая служба — Microsoft Exchange IMAP4 Backend. Не буду нудно копировать описание — думаю, из названия всё ясно. Эта служба творит магию, а именно: предоставляет клиентам информацию из почтовых ящиков, обрабатывает всякие полезные команды IMAP, такие как list, subscribe и т.д. Имя файла с логами вида IMAP4BE2024022417–1

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

Это лог службы Microsoft Exchange IMAP4 из файла IMAP42024022417–1:

Заголовки:
dateTime, sessionId, seqNumber, sIp, cIp, user, duration, rqsize, rpsize, command, parameters, context, puid

01:
2024–02–24T17:41:52.734Z,0000000000007ADF,0,10.129.0.11:143, 176.59.37.143:55098,,1,0,53, OpenSession,,,

02
2024–02–24T17:41:53.047Z,0000000000007ADF,1,10.129.0.11:143, 176.59.37.143:55098,,1,15,169, capability,, R=OK,

03
2024–02–24T17:41:54.059Z,0000000000007ADF,2,10.129.0.11:143,
176.59.37.143:55098,,1,44,286, authenticate, NTLM, «R=lvrv NO AUTHENTICATE failed.; Msg=AuthFailed: LogonDenied, User: not found; ErrMsg=AuthFailed: LogonDenied»,

06
2024–02–24T17:41:54.707Z,0000000000007ADF,3,10.129.0.11:143, 176.59.37.143:55098, delegate,117,34,26, login, example.com/delegate/resource *****, «R=OK; Msg=Proxy: ex2019.example.com:1993: SSL; ProxySuccess; ActivityContextData=938210d8-e299–42f0-bfcd-3e404f5a18d7»,

Это лог службы Microsoft Exchange IMAP4 Backend из файла IMAP4BE2024022417–1:

Заголовки
dateTime, sessionId, seqNumber, sIp, cIp, user, duration, rqsize, rpsize, command, parameters, context, puid

04
2024–02–24T17:41:54.654Z,0000000000007490,0,[fe80::13c1:9b58:8991:10af12]:1993,[fe80::13c1:9b58:8991:10af%12]:7982,,4,0,53, OpenSession,,,

05
2024–02–24T17:41:54.655Z,0000000000007490,1,[fe80::13c1:9b58:8991:10af%12]:1993, [fe80::13c1:9b58:8991:10af%12]:7982,,1,12,195, capability,, R=OK,

06
2024–02–24T17:41:54.707Z,0000000000007490,2, [fe80::13c1:9b58:8991:10af%12]:1993,[fe80::13c1:9b58:8991:10af%12]:7982, delegate,51,31,33, authenticate, PLAIN, «R=OK; Msg=Auth: User: example.com/delegate, Mbx: resource; User: LegacyDn: /o=Не Скажу/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=user19b73161, RecipientType: UserMailbox, RecipientTypeDetails: UserMailbox, Selected Mailbox: Display Name: Никита Никитин, Mailbox Guid: 78c2e947-cc53–40b4-ad67–68091ee42101, Database: 85d5bd59–7c18–4773-a9e5-be0d0beba46e, Location: ServerFqdn: ex2019.example.com, ServerVersion: 1942127450, DatabaseName: EX, HomePublicFolderDatabaseGuid: 00000000–0000–0000–0000–000000000000; LiveIdAR=OK; ActivityContextData=I32: ADR.C[vm2019]=2, F: ADR.AL[vm2019]=0.8032, Dbl: ST.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=16, I32: MB.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=8, F: MB.AL[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=2.5, I32: ADS.C[vm2019]=4, F: ADS.AL[vm2019]=1.22655, I32: ATE.C[vm2019.example.com]=6, F: ATE.AL[vm2019.example.com]=0.1666667, Dbl: VCGS.T[EX2019]=0, I32: VCGS.C[EX2019]=2, Dbl: MAPI.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=20, Dbl: RPC.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=20, I32: RPC.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=8, I32: MAPI.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=19, I32: ROP.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=19146008, Dbl: EXR.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=17; Budget=Owner: SidS-1–5–21–1933324732–2533695465–2567999076–1171 Imap~false, Conn:1, MaxConn: Unlimited, MaxBurst:3600000, Balance:3600000, Cutoff: Unlimited, RechargeRate:600000, Policy: GlobalThrottlingPolicy_a0170094-be11–4537-bd30-f20453745af5, IsServiceAccount: False, LiveTime:00:00:00.0250000»,

07
2024–02–24T17:41:55.054Z,0000000000007490,3,[fe80::13c1:9b58:8991:10af%12]:1993,[fe80::13c1:9b58:8991:10af%12]:7982, delegate,3,53,93, id,»(name Microsoft Outlook version 16.0)», «R=OK; ActivityContextData=Dbl: BudgUse.T[]=4.00190019607544; Budget=Owner: SidS-1–5–21–1933324732–2533695465–2567999076–1171Imap~false, Conn:1, MaxConn: Unlimited, MaxBurst:3600000, Balance:3599997, Cutoff: Unlimited, RechargeRate:600000, Policy: GlobalThrottlingPolicy_a0170094-be11–4537-bd30-f20453745af5, IsServiceAccount: False, LiveTime:00:00:00.3719990»,

08
2024–02–24T17:41:55.619Z,0000000000007490,4,[fe80::13c1:9b58:8991:10af%12]:1993,[fe80::13c1:9b58:8991:10af%12]:7982, delegate,4,15,65, list,» », «R=OK; FolderCount=1; ActivityContextData=I32: ROP.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=7179789, Dbl: BudgUse.T[]=4.00540018081665, I32: MB.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=3, F: MB.AL[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=1, Dbl: STCPU.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=15, Dbl: MAPI.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=4, Dbl: EXR.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=1, Dbl: RPC.T[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=3, I32: RPC.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=3, I32: MAPI.C[ex2019.85d5bd59–7c18–4773-a9e5-be0d0beba46e]=12; Budget=Owner: SidS-1–5–21–1933324732–2533695465–2567999076–1171Imap~false, Conn:1, MaxConn: Unlimited, MaxBurst:3600000, Balance:3599997, Cutoff: Unlimited, RechargeRate:600000, Policy: GlobalThrottlingPolicy_a0170094-be11–4537-bd30-f20453745af5, IsServiceAccount: False, LiveTime:00:00:00.9369983»,

01 (front) — сервер успешно открыл сессию для клиента по протоколу IMAP.
02 (front) — сервер получил от клиента команду capability.
03 (front) — сервер получил команду authenticate, где в качестве username была конструкция domain/delegate/resource, не переварил, сказал denied. Послал, короче, но культурно. Сессию не закрыл.
04 (back) — сессия была открыта. Внезапно. Но обратите внимание, это постучался Front к Back и проксировал подключение через себя.
05 (back) — аналогично проксирована команда capability до бэка.

Специально поставил одинаковый номер, так как в одно время произошло проксирование и реакция на бэке.
06 (front) — получена команда login. На самом деле клиент отправил дословно команду Login: example.com/delegate/resource Это подтверждает строчка DerParole в логах и результат фронта — ProxySuccess.
06 (back) — здесь подробнее:

  • Бэк выцепил пользователя из того, что User = delegate.

  • В контексте указано, что Auth: User: example.com/delegate.

  • Ящик, который реально будет показываться, спрятан в поле Mbx: resource.

Вот ты и попался: вот так Exchange Server отдаёт по протоколу IMAP ящик одного пользователя при подключении другим пользователем. Далее мы видим LegacyDN — оказывается, для IMAP этот атрибут из AD важен. А ещё важен Mailbox Guid — в какой базе, на каком сервере лежит весь ресурс.

07 (back) — идёт типичная коммуникация протокола IMAP, клиент отправил команду id.
08 (back) — команда list, клиент отправил команду на листинг содержимого почтового ящика. В Outlook начнут появляться папки ящика resource, а не основного ящика пользователя delegate.

Всё тайное стало явным: мы увидели, как Exchange Server, получив определённую команду, разобрал её и отдал клиенту нужный ящик. Миграция почты из Exchange Server в Яндекс Почту полностью повторяет эту бизнес-логику. После этих исследований, мы повторили в существующем миграторе механизм команды LOGIN с передачей заданного значения, который формирует сам администратор в CSV.

Делегирование по IMAP в Яндекс 360

В начале этого года в Яндекc Почте был реализован механизм делегированного доступа к почтовым ящикам по протоколам IMAP и SMTP. Он заключается в том, что администратор может выдать разные права:

  • полного доступа на содержимое почтового ящика;

  • отправки как (Send-as);

  • отправки от имени (Send on behalf).

Как это сделать, описано в документации: https://yandex.ru/support/business/mail/sharing/index.html 

По сути, мы применили ту же логику и придумали, как реализовать делегирование по IMAP от Яндекс Почты в Outlook. Почему мы это сделали? Во-первых, мы уже получили опыт, развивая наш инструмент миграции с Exchange Server. Во-вторых, как известно, часто клиент по IMAP в B2B-сегменте — это Outlook. 

Пользователю Outlook при настройке по IMAP делегированного ему ящика нужно указать учётную запись в виде example.test/user/resource и свой пароль приложения, а не пароль делегированного ящика. После этого IMAP сервер это распознает и предоставит доступ к делегированному ящику.

А вот в Mozilla Thunderbird в IMAP-клиенте реализована поддержка команд Namespace как и в Яндекс Почте — другие ящики прорастают непосредственно внутри основного .

Делегирование почты — это большая тема, достойная отдельной статьи. В этом же материале мы с вами увидели, как работает делегирование по IMAP у Microsoft Exchange Server. При миграции писем из Exchange Server мигратор Яндекс Почты использует именно этот механизм. 

Если у вас во время запуска миграции что-то не работает, теперь вы знаете, куда нужно залезть и какие логи почитать, чтобы попытаться решить возникшие проблемы. Ну и также вы теперь знаете, почему именно такую конструкцию надо указывать в учётной записи при настройке делегирования по IMAP в Outlook.

© Habrahabr.ru