O que o NEVPNManager consegue criar no iOS (e o que não)
A API de VPN do iOS constrói uma configuração própria da app a partir de três classes de protocolo. L2TP, PPTP e perfis assinados não fazem parte dessa superfície.
Quando constróis um ecrã VPN dentro de uma app iOS, a primeira surpresa é que a lista de protocolos da app Definições não é a lista da API. A framework Network Extension permite à tua app criar uma configuração VPN pessoal, propriedade dessa app, e aceita apenas alguns objetos de protocolo. Tudo o resto que as pessoas esperam, do L2TP a um perfil descarregado, fica fora dessa superfície ou é privado da Apple. As falhas que se seguem normalmente não são erros, é a API a recusar um trabalho que nunca lhe foi dado.
O mito: a API é um editor das Definições
Acredita-se que, como o iOS consegue configurar perfis IKEv1, IKEv2, L2TP e IPsec, uma app pode criar qualquer um deles programaticamente. Não pode. A framework expõe exatamente um espaço de configuração à app que a chama, e esse espaço só aceita um pequeno conjunto de classes de protocolo públicas. Tudo o resto que as pessoas esperam, do L2TP a um perfil descarregado, fica fora dessa superfície ou é privado da Apple.
As falhas que se seguem normalmente não são erros. É a API a recusar um trabalho que nunca lhe foi dado, e a correção é desenhar o ecrã em torno do que a API possui.
Três objetos de protocolo e os que não existem
As tuas opções são IKEv1 através de NEVPNProtocolIPSec, IKEv2 através de NEVPNProtocolIKEv2, e NETunnelProviderProtocol se forneceres a tua própria extensão de túnel de pacotes. A referência do NEVPNManager lista os objetos de protocolo aceites. L2TP e PPTP nunca aparecem nessa lista porque a Apple não publicou classes para eles. Tentar qualquer um deles termina ao guardar com um erro, ou pior, com uma configuração que o sistema recusa silenciosamente usar.
O código de ambiente de trabalho segue outras regras. No macOS, SCNetworkInterfaceCreateWithInterface empilha um tipo de interface como L2TP sobre IPv4 e liga-o a um serviço de rede, e networksetup -connectpppoeservice inicia o resultado. São necessários direitos de administrador e uma ferramenta auxiliar, porque o segredo partilhado e a palavra-passe vão para o porta-chaves do sistema. Copia esse desenho para o iOS e nada compila.
Passa uma referência do porta-chaves, não a palavra-passe
Nenhuma das duas classes IKE aceita uma palavra-passe como texto. As duas propriedades passwordReference e sharedSecretReference querem uma referência persistente do porta-chaves, que obténs de SecItemCopyMatching pedindo kSecReturnPersistentRef. Passar os dados do item, ou inserir uma cadeia no campo, produz uma falha ao guardar ou uma ligação com credenciais vazias. A referência só é duradoura quanto o item do porta-chaves por trás dela, por isso o item tem de existir antes de a configuração ser montada. Cria-o na mesma transação do guardar e eliminas toda uma classe de erros de ordenação.
A autenticação por certificado segue outro caminho: identityData mais identityDataPassword para um blob PKCS#12. Distribuir esse blob dentro do pacote da app é um hábito herdado do código de exemplo, não uma decisão de lançamento, porque a palavra-passe viaja com ele e cada cópia da app transporta a mesma identidade.
O direito e a disponibilidade condicionam tudo
O gestor pode nem existir, e a razão é o provisionamento. O identificador da tua app precisa da capacidade Network Extension juntamente com o direito de VPN pessoal, e o perfil que assina a compilação tem de transportar ambos.
Ignora isso e a instância partilhada devolve nil, ou o guardar falha com um erro que nunca menciona o direito. A disponibilidade é a outra porta. Aponta para algo mais antigo do que o iOS 8 e o símbolo falta em tempo de execução, por isso a falha é um crash ou um gestor nil, não um gestor sem configuração. Verifica o tempo de execução e o direito antes de depurares o teu grafo de objetos.
Carrega, modifica, guarda e depois observa a ordem a pedido
Trata o ciclo de vida como carregar, modificar, guardar, e nunca saltes o carregamento. Até loadFromPreferences terminar, o gestor não detém nada e o objeto de protocolo não pode ser lido nem trocado.
Um segundo guardar substitui a configuração em vez de acrescentar outra, por isso um guardar a meio pode danificar um perfil que estava a funcionar. As regras a pedido formam um array ordenado, e essa ordem é a política. Coloca uma regra de ligar-em-qualquer-lugar antes da regra de desligar e a uma desconexão manual segue-se uma reconexão imediata, o que parece um defeito mas segue a avaliação documentada.
Move a regra de desligar para a frente quando a ação do utilizador tem de vencer. O que fica fora do controlo da app importa igualmente. As rotas vêm do túnel ou da política do servidor em vez de uma preferência que defines, com um fornecedor de túnel de pacotes a reportá-las quando arranca. A app não pode listar nem editar perfis instalados por outras apps ou perfis de configuração, por isso não prometas um ecrã que mostre todas as VPN do dispositivo.