Hi there! I recently used SwiftNIO example - Connect Proxy with NEPacketTunnelProvider to set up a local proxy server which support HTTPS proxy
. I also referenced this link to simultaneously support HTTP proxy
. It works great when opening web pages in browsers like Safari or Chrome!
However, when I use some instant messenger app to make VOIP calls
, I can't make successful calls. What could be the possible reason for this? I want my proxy server to intercept only HTTP/HTTPS
requests but not interfere with or block VOIP calls
. Is there any configuration parameter that can achieve this?
I'm sorry, but I don't have a strong background in proxy servers and VOIP. I would greatly appreciate any guidance or insights.
Here is how I start Packet Tunnel
and Proxy Server
:
let tunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: localhostIP)
let proxySettings = NEProxySettings()
proxySettings.httpServer = NEProxyServer(address: localhostIP, port: localhostHttpPort)
proxySettings.httpsServer = NEProxyServer(address: localhostIP, port: localhostHttpsPort)
proxySettings.autoProxyConfigurationEnabled = false
proxySettings.httpEnabled = true
proxySettings.httpsEnabled = true
proxySettings.excludeSimpleHostnames = true
proxySettings.exceptionList = ["192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", "127.0.0.1", "localhost", "*.local"]
tunnelNetworkSettings.proxySettings = proxySettings
tunnelNetworkSettings.ipv4Settings = NEIPv4Settings(addresses: ["10.8.0.2"], subnetMasks: ["255.255.255.0"])
tunnelNetworkSettings.mtu = 1500
let dns = NEDNSSettings(servers: ["8.8.8.8"])
dns.matchDomains = [""]
tunnelNetworkSettings.dnsSettings = dns
tunnelNetworkSettings.ipv4Settings?.includedRoutes = [NEIPv4Route.default()]
tunnelNetworkSettings.ipv4Settings?.excludedRoutes = [
NEIPv4Route(destinationAddress: "192.168.0.0", subnetMask: "255.255.0.0"),
NEIPv4Route(destinationAddress: "10.0.0.0", subnetMask: "255.0.0.0"),
NEIPv4Route(destinationAddress: "172.16.0.0", subnetMask: "255.240.0.0")
]
setTunnelNetworkSettings(tunnelNetworkSettings) { error in
self.pendingCompletion?(error)
self.pendingCompletion = nil
}
And how I've used SwiftNIO
:
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
let bootstrap = ServerBootstrap(group: group)
.serverChannelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
.childChannelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
.childChannelInitializer { channel in
channel.pipeline.addHandler(ByteToMessageHandler(HTTPRequestDecoder(leftOverBytesStrategy: .forwardBytes)))
.flatMap {
channel.pipeline
.addHandler(HTTPResponseEncoder())
}
.flatMap {
if channel.localAddress?.port == self.localhostHttpPort {
channel.pipeline
.addHandler(ConnectHttpHandler())
} else {
channel.pipeline
.addHandler(ConnectHttpsHandler())
}
}
}
Most folks who hit issues like this are trying to twist the NE packet tunnel architecture into doing something that it was not intended to do. DTS sees a lot of this, so much so that my colleague (at the time) wrote TN3120 Expected use cases for Network Extension packet tunnel providers. Packet tunnel providers are intended to… well… tunnel packets. Folks who use it for that purpose rarely run into problems like this.
What could be the possible reason for this?
This is failing because you claim the default route:
tunnelNetworkSettings.ipv4Settings?.includedRoutes = [NEIPv4Route.default()]
When you do that, the system expects you to be able to forward packets to any destination on the Internet. Presumably you don’t do that, and so various networking apps start to fail.
The only reason Safari works is that your VPN also sets up a proxy server. Safari uses URLSession
which has built-in proxy support. So, its HTTP[S] requests get routed to your local proxy, which allows them to work.
If the user runs an app that’s not compatible with an HTTP[S] proxy, the app’s traffic will be sent as packets to your packet tunnel provider. You have no way to forward those, and so things fail.
You’ve noticed this with VoIP apps but there are numerous other apps that’ll have the same problem.
How do you fix that? Well, that’s tricky, and it very much depends on your goals. You wrote:
I want my proxy server to intercept only HTTP/HTTPS requests but not interfere with or block VOIP calls.
It sounds like you’re trying to build a debugging HTTP[S] proxy. It’s possible to do that — there are some popular products out there — but I can’t help you with it. It’s not an expected use case for packet tunnel providers and, as per TN3120, that means it’s something that DTS doesn’t support.
IMPORTANT I work for Developer Technical Support (DTS) and so “support” in the above paragraph refers to what DTS supports. I can’t make definitive statements about the policy of other groups at Apple, most notably App Review.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"