Hello,
I am trying to build an automatic reverse proxy for the development experience. Basically all developers are limited to running several web applications on various port on localhost, like localhost:8000 and localhost:9000. My idea is simple, trying to map http://app1.dev.local to localhost:8000 and http://app2.dev.local to localhost:9000. It could be easily achieved with a few records in /etc/hosts
And installed haproxy/nginx on port 80 that will redirect the traffic based on the Host header.
But my idea is to use the Network Extensions to do the same. To use more native experience.
I have tried to use NETransparentProxyManager with NETunnelProviderProtocol and NEAppProxyProvider in system network extension.
In the app I have
And in the system network extension
That actually does what I want, but only for Safari. If I try to use curl or Chrome, those two ignore the VPN and fail to resolve the DNS.
If I use curl directly on IP address, that works. So host based NENetworkRule do not work on curl or Chrome.
I have tried also to switch to NEAppProxyProviderManager instead, which has NEAppRule, and it also includes matchDomains, but when I specify those: (a) for Chome as an example matchDomains does not work, I am getting all traffic (b) for Safari and curl I cannot catch the traffic with
So I am curious, is it possible with the network extensions to achieve what I want? If yes, what kind of Manager should I use and Provider?
I am trying to build an automatic reverse proxy for the development experience. Basically all developers are limited to running several web applications on various port on localhost, like localhost:8000 and localhost:9000. My idea is simple, trying to map http://app1.dev.local to localhost:8000 and http://app2.dev.local to localhost:9000. It could be easily achieved with a few records in /etc/hosts
Code Block 127.0.0.1 app1.dev.local 127.0.0.1 app2.dev.local
And installed haproxy/nginx on port 80 that will redirect the traffic based on the Host header.
But my idea is to use the Network Extensions to do the same. To use more native experience.
I have tried to use NETransparentProxyManager with NETunnelProviderProtocol and NEAppProxyProvider in system network extension.
In the app I have
Code Block NETransparentProxyManager.loadAllFromPreferences { (managers, loadError) in ... if self.manager == nil { self.logger.log("creating NETransparentProxyManager") let config = NETunnelProviderProtocol() config.providerBundleIdentifier = "app.loshadki.DevVPN.systemextension" config.serverAddress = "DevVPN" config.disconnectOnSleep = false self.manager = NETransparentProxyManager() self.manager!.localizedDescription = "DevVPN" self.manager!.isEnabled = true self.manager!.protocolConfiguration = config } else { self.logger.log("NETransparentProxyManager DevVPN already exists") } self.manager!.saveToPreferences(completionHandler: { (saveError) in ... do { try self.manager?.connection.startVPNTunnel(options: ["mode": "localOnly" as NSObject]) } catch { ... } }) } }
And in the system network extension
Code Block class AppProxyProvider: NEAppProxyProvider { override func startProxy(options: [String : Any]?, completionHandler: @escaping (Error?) -> Void) { ... let proxySettings = NETransparentProxyNetworkSettings(tunnelRemoteAddress: "127.0.0.1") proxySettings.includedNetworkRules = [ NENetworkRule(destinationNetwork: NWHostEndpoint(hostname: hostnameIP, port: "80"), prefix: 32, protocol: .any), NENetworkRule(destinationHost: NWHostEndpoint(hostname: "app1.dev.local", port: "80"), protocol: .any), NENetworkRule(destinationHost: NWHostEndpoint(hostname: "app2.dev.local", port: "80"), protocol: .any) ] setTunnelNetworkSettings(proxySettings) { error in ... } } ... }
That actually does what I want, but only for Safari. If I try to use curl or Chrome, those two ignore the VPN and fail to resolve the DNS.
If I use curl directly on IP address, that works. So host based NENetworkRule do not work on curl or Chrome.
I have tried also to switch to NEAppProxyProviderManager instead, which has NEAppRule, and it also includes matchDomains, but when I specify those: (a) for Chome as an example matchDomains does not work, I am getting all traffic (b) for Safari and curl I cannot catch the traffic with
Code Block NEAppRule(signingIdentifier: "com.apple.Safari", designatedRequirement: "identifier \"com.apple.Safari\" and anchor apple")
So I am curious, is it possible with the network extensions to achieve what I want? If yes, what kind of Manager should I use and Provider?