Як викликати внутрішній API із застосунку iPhone через VPN
Класифікуйте невдалий запит за його кодом NSURLError, перш ніж торкатися тунелю, а потім виправте саме той шар, який справді зламався.
API відповідає в Safari на тому самому телефоні, а запит застосунку завершується тайм-аутом. Ця різниця зазвичай не в тунелі: застосунок, що звертається до внутрішньої служби, робить звичайний запит HTTPS, а наявний VPN на пристрої вирішує лише, чи має цей запит шлях. Вбудувати в застосунок другий тунель — це продуктове рішення, а не лагодження тайм-ауту. Далі невдача класифікується за місцем виникнення з використанням тієї поверхні помилок, яка в застосунку вже є.
Починайте з помилки, а не з тунелю
URLSession повідомляє про транспортні збої як про NSError значення в NSURLErrorDomain, і код — найдешевший доступний доказ. Перш ніж змінювати будь-яку конфігурацію, залогуйте цей код разом з іменем хоста, що збоїть, і минулим часом задачі. Тайм-аут, збій імені та збій довіри виглядають на екрані однаково і потребують трьох різних виправлень. Спершу класифікуйте, потім читайте розділ для цього класу.
Метрики задачі відповідають на наступне питання, чи було взагалі встановлено з'єднання, що відокремлює запит, який ніколи не мав маршруту, від того, на який сервер відповідав надто довго. Ніщо з цього не вимагає змінювати тунель; потрібно надрукувати діагностику самого запиту там, де ви зможете її прочитати.
Розв'язання імен збоїть раніше за все інше
Коротке офісне ім'я на кшталт api.corp.example зазвичай залежить від домену пошуку, якого немає на телефоні, тому застосунок розв'язує ім'я, що існує лише всередині будівлі. NSURLErrorCannotFindHost — це підпис. Повне ім'я хоста має розв'язуватися через будь-який резолвер, який встановить VPN, і застосунок повинен запитувати повністю кваліфіковану форму щоразу, коли домен пошуку не гарантований. Заміна імені на адресу та вимкнення перевірок сертифікатів переносить збій, а не виправляє його.
Приватний запис DNS і сертифікат, виданий саме на це ім'я, — це підтримувана пара. Усе інше — обхідний шлях, що доходить до користувачів.
Тайм-аут — це питання шляху, а не імені
NSURLErrorTimedOut означає, що ім'я розв'язалося і ніщо не відповіло, що вказує на маршрут, політику пакетів або службу. Коли тунель призначається для кожного застосунку, інший застосунок, що досягає того самого сервера, нічого не каже про вашу збірку, бо це зіставлення не є спільним. Перевірте, що запущений пакет перебуває всередині цього призначення, потім перевірте, що шлях служби для нього дозволений. Збірка для розробки, встановлена поза призначенням, може бути повністю поза тунелем і виглядати як зламана API.
Порівняння в браузері показує, що якийсь застосунок на пристрої має шлях. Воно ніколи не доводить, що ваша збірка має його, тому обидва тести треба проводити окремо.
Збої довіри стосуються імені в сертифікаті
NSURLErrorServerCertificateUntrusted разом з помилкою TLS під ним означає, що ланцюжок або перевірка тотожності не пройшли. Внутрішній CA має бути довіреним на пристрої, а сертифікат, виданий на інше ім'я хоста, залишається неправильним після будь-якого переналаштування мережі. Настанови App Transport Security від Apple далі застосовуються до цих з'єднань, що завантажують URL, і тунель навколо звичайної служби HTTP не робить цю службу безпечною від краю до краю.
Виправте тотожність або якір довіри й тримайте список винятків порожнім. Загальний виняток для довільного завантаження приховує збій під час розробки й залишає його на місці для кожного користувача після.
Відмова HTTP належить застосунку, а не мережі
401 або 403 після завершеного рукостискання означає, що запит дійшов і служба його відхилила, тому залишається питання про обліковий запис, аудиторію токена, область або ключ. Записуйте код стану та ім'я хоста, але ніколи не носійний токен і не тіло відповіді. У цей момент тунель робить свою роботу, а подальші зміни мережі лише відкладають справжнє виправлення.
Таблиця — це класифікація, яку варто тримати біля термінала: один рядок на кожен збій, про який застосунок справді може повідомити. Надрукуйте код перш ніж читати його, бо обраний рядок визначає, який розділ ви опрацюєте.
| Where it fails | What the app sees | First check |
|---|---|---|
| name resolution | NSURLErrorCannotFindHost (-1003) | resolve the fully qualified name from the device itself |
| no path, or no answer | NSURLErrorTimedOut (-1001) | is this bundle inside the per-app mapping, and is the service path allowed |
| TLS trust | NSURLErrorServerCertificateUntrusted (-1202) | does the certificate name match the host, and is the internal CA trusted |
| service refusal | HTTP 401 or 403 after a completed handshake | account, token audience, scope or key |
Кожен рядок дешевше перевірити, ніж той, що під ним, і кожен виключає інший шар того самого запиту. Просувайтеся таблицею вниз, доки рядок не збіжиться, а потім припиніть змінювати мережу.