NEProxySettings.matchDomains = [""] — supported catch-all when no IP routes are claimed?

We are building a VPN using NEPacketTunnelProvider where the intent is to route HTTP/S traffic through a local proxy server, while non-HTTP/S traffic flows directly to the network without being tunnelled at the IP layer.

The configuration claims no included IP routes — it relies entirely on NEProxySettings to intercept HTTP/S traffic via the URL loading layer.

private func configureIPSettings(_ settings: NEPacketTunnelNetworkSettings) {
    settings.ipv4Settings = NEIPv4Settings(
        addresses: ["192.168.1.1"],
        subnetMasks: ["255.255.255.255"]
    )
    // No includedRoutes set — no IP traffic enters the tunnel
}

private func configureProxySettings(_ settings: NEPacketTunnelNetworkSettings) {
    let proxySettings = NEProxySettings()
    proxySettings.httpEnabled = true
    proxySettings.httpServer = NEProxyServer(address: "127.0.0.1", port: 9000)
    proxySettings.httpsEnabled = true
    proxySettings.httpsServer = NEProxyServer(address: "127.0.0.1", port: 9000)
    proxySettings.matchDomains = [""]
    settings.proxySettings = proxySettings
}

When matchDomains is nil or not set, HTTP/S traffic does not reach the local proxy in this configuration. Setting matchDomains = [""] makes it work correctly.

The matchDomains documentation states:

"If the destination host name of a HTTP connection shares a suffix with one of these strings then the proxy settings will be used."

An empty string is a suffix of every string, so [""] matching all hostnames follows from that definition. But this isn't explicitly documented.

Questions:

  • Is matchDomains = [""] a supported and stable way to apply proxy settings to all HTTP/S traffic when no IP routes are claimed, or is this an unintended side-effect?

  • Why does matchDomains = nil not apply the proxy globally in this configuration? The documentation doesn't describe its behaviour relative to IP routing.

  • NEDNSSettings.matchDomains explicitly documents an empty string as matching all domains — is the same semantics intended for NEProxySettings.matchDomains?

Answered by DTS Engineer in 884513022
We are building a VPN using NEPacketTunnelProvider where the intent is to route HTTP/S traffic through a local proxy server

To what end?

My experience is that most folks on this path are trying to implement a content filter on iOS. We don’t support the use of packet tunnel provider for that. See TN3120 Expected use cases for Network Extension packet tunnel providers.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

We are building a VPN using NEPacketTunnelProvider where the intent is to route HTTP/S traffic through a local proxy server

To what end?

My experience is that most folks on this path are trying to implement a content filter on iOS. We don’t support the use of packet tunnel provider for that. See TN3120 Expected use cases for Network Extension packet tunnel providers.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NEProxySettings.matchDomains = [""] — supported catch-all when no IP routes are claimed?
 
 
Q