NEVPNManager で保存に失敗する?順序は読み込み、有効化、保存、接続
コード 4 とコード 5 は通常、プロファイルが読み込み前に編集されたか、無効のまま保存されたことを意味します。呼び出しの順序を直し、その後エンタイトルメントを確認してください。
iOS の Network Extension VPN で最初の試行のほとんどを説明するのは二つのエラーコード、NEVPNErrorDomain Code=4 と Code=5 です。どちらもサーバーからの苦情ではありません。一方は、ディスクから一度も読み込まれていないオブジェクトにアプリが設定を書き込むときに現れ、もう一方は書き込み自体が失敗したとき、多くの場合プロファイルがまだ無効のまま保存されているために現れます。どちらも四つの呼び出しの順序を変えれば直り、IKEv2 のパラメータに触る必要はありません。
まず読み込み、さもなければ保存には比較対象がない
マネージャは保存済みプロファイルのコピーを保持しており、編集するオブジェクトはそれを読むまでそのコピーではありません。まず loadFromPreferences を呼び、その完了ハンドラの中で編集し、それから保存します。読み込みを飛ばすと、フレームワークは自分が持っているものと書き込もうとしているものの不一致を見ます。Swift ではどの手順も形は同じで、各手順はそれぞれのクロージャに入ります:
let mgr = NEVPNManager.shared()
mgr.loadFromPreferences { loadErr in
guard loadErr == nil else { return }
let proto = NEVPNProtocolIKEv2()
proto.serverAddress = "vpn.example.net"
proto.username = "alice"
proto.useExtendedAuthentication = true
mgr.protocolConfiguration = proto
mgr.isEnabled = true
mgr.saveToPreferences { saveErr in
// do not start here; reload, then connect
}
}
保存クロージャの内側からトンネルを開始するのは、別の場所での同じ誤りです。プロファイルが読み直される前に実行されるため、開始呼び出しは保存された状態ではなく、自分が構築した状態を見ます。保存クロージャは 二回目の loadFromPreferences で終わり、その完了ハンドラだけが startVPNTunnel を呼びます。
有効化フラグは保存の一部です
保存済みプロファイルは有効にされるまで機能しません。同じ書き込みで isEnabled = true を設定しないと、プロファイルは無効のままディスクに残り、設定に完全に見える構成が表示されていても startVPNTunnel は拒否します。
外部での編集がもう半分です。ユーザーが設定で何かを変えた場合や、デバイスがネットワーク間を移動した場合は、メモリにまだ保持している値を信頼する前に読み直してください。オブジェクトはそうした変更を代わりに監視しません。古いコピーは、アプリがユーザーの編集を黙って巻き戻すプロファイルを書く経路です。隣り合う二つのフィールドは同じ瞬間に静かな問題を起こし、on-demand ルールは空のプレースホルダではなくルールオブジェクトの配列でなければならず、disconnectOnSleep はコピーした既定値ではなく選んだ動作を反映すべきです。
サードパーティ製アプリに使えるプロトコルは二つだけです
Network Extension がアプリに与えるのは IPsec と IKEv2 です。L2TP と PPTP はシステムの内部にとどまるため、それらを必要とするアプリは使えず、現実的な答えは IKEv2 対応ゲートウェイか管理対象の構成プロファイルです。
資格情報も同じパターンです。パスワードを Keychain に入れ、文字列ではなく永続参照を渡します。保存時の nil 参照は通常、項目が書き込まれる前に検索が走ったという意味で、マネージャが壊れているわけではありません。
どちらも回避策ではなく設計上の判断です。パスワードを自前の設定に保持するアプリは、フレームワークが勧めない道を選んでおり、それが生む失敗は保存エラーのように読めます。
コードを書き直す前にエンタイトルメントを除外する
loadFromPreferences がまったくコールバックしない場合、考えられる原因は Network Extension 機能の欠落か、それを含まないプロビジョニングプロファイルです。この失敗はエラーを返さずに止まるため、動いているコードが何時間も書き直されます。出荷するつもりの署名済みビルドでエンタイトルメントを確認してください。シミュレータ実行とデバイス実行は異なることがあり、重要な対象はデバイスなので、ターゲットの署名設定を開き、その正確なビルドに Network Extension 機能があることを確認します。
エンタイトルメントのないプロビジョニングプロファイルはハードウェアでも同じように失敗しますが、同じビルドがシミュレータでは普通に読み込めることがあります。呼び出しの順序を書き直す前に、署名済みアーカイブを実機で試してください。
想定ではなく状態の変化を見る
NEVPNStatusDidChangeNotification を監視し、各手順の後に manager.connection.status を記録します。invalid から一度も出ない状態は、プロファイルが保存されていないかエンタイトルメントがないことを意味します。connecting に達して一度も接続しない場合は提案か資格情報を示しており、別の証拠を伴う別の調査です。
プロファイルが設定、一般、VPN の下に現れることを確認し、各クロージャのエラーを記録します。この二つの事実が、推測なしに順序の不具合と権限の不具合を分けます。