Post

Replies

Boosts

Views

Activity

Automatic Reverse Proxy with NETransparentProxyManager (or similar?)
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 0.0.1 app1.dev.local 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 				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 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 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?
3
0
1.1k
Dec ’20
WeatherKit with watchOS resulting with 401
My guess the issue is that the iOS app is com.example.MyApp and the bundle id for the watchOS app is com.example.MyApp.watchkitapp, so WeatherKit works perfectly on the iOS app after registering bundleID and request WeatherKit service. But it does not work on watchOS, giving me 401 errors. I assume it is because of the bundleID, but maybe something else. 2022-06-25 08:58:58.999485-0500 JumpLog Watch App[72341:1201484] [WK_Geocode] failed to reverse geocode. location=CLLocationCoordinate2D(latitude: 37.62471885, longitude: -122.42857813), error=reverseGeocodeFailed(Error Domain=NMDeviceConnectionErrorDomain Code=2 "Timed out." UserInfo={NSDescription=Timed out.}) 2022-06-25 08:58:59.019561-0500 JumpLog Watch App[72341:1201484] [Database] Attempting to invalidate an assertion that is no longer valid 2022-06-25 08:58:59.724802-0500 JumpLog Watch App[72341:1198856] [WeatherService] Encountered an error when fetching weather data subset; location=<+37.62471885,-122.42857813> +/- 5.00m (speed 34.21 mps / course 332.23) @ 6/25/22, 8:56:58 AM Central Daylight Time, error=invalidJWTResponse(Optional(<NSHTTPURLResponse: 0x60000394bf20> { URL: https://weather-data.apple.com/v2/token } { Status Code: 401, Headers { Connection = ( close ); "Content-Length" = ( 0 ); Date = ( "Sat, 25 Jun 2022 13:58:59 GMT" ); Server = ( Apple ); "Strict-Transport-Security" = ( "max-age=31536000; includeSubdomains" ); "X-Apple-Origin" = ( "8961098f-b238-3714-ba44-5b569c861456" ); "X-Cache" = ( "TCP_MISS from a23-33-47-144.deploy.akamaitechnologies.com (AkamaiGHost/10.8.2-41841244) (-)" ); "X-Content-Type-Options" = ( nosniff ); "X-Frame-Options" = ( SAMEORIGIN ); "X-REQUEST-ID" = ( "2076edab-2346-4a50-83c1-e62f46aab9eb" ); "X-XSS-Protection" = ( "1; mode=block" ); } }))
0
0
780
Jun ’22
watchOS 9.0 Developer Beta 3: allowsBackgroundLocationUpdates = true crashes the application
This code worked before for me on Beta 2. Now I get the exception Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: !stayUp || CLClientIsBackgroundable(internal->fClient) || _CFMZEnabled()' I do call requestAlwaysAuthorization() if the authorizationStatus != authorizedAlways (and I have tried with authorizedWhenInUse). I start the collection like that locationManager.activityType = .airborne locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation locationManager.allowsBackgroundLocationUpdates = true locationManager.startUpdatingLocation() And I have a delegate attached to the location manager to collect the data. I have enabled Background Modes for location updates, and have in info information about the Privacy - Location ... for various options
1
0
1.3k
Jul ’22
Using SettingsLink from MenuBarExtra does not activate the app
I have a Utility app that does not have a Dock icon and runs in the menu bar. On macOS Sonoma (14 DB 1) you cannot use anymore the workaround that we used on previous versions of the macOS, as you get a warning that you should use SettingsLink. NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil) But the issue is, that before I usually were calling as well NSApp.activate(ignoringOtherApps: true) to activate the app. As clicking on the MenuBar app icon does not do that. The SettingsLink only opens the Settings Scene, but does not actually activates the app. I could not find a workaround how to do so. As I cannot inject my code in SettingsLink call. Any ideas how I can activate my app when SettingsLink is called?
1
2
1.4k
Jun ’23
How to read back from Spatial Image encoded with HEIC information about which image at which index is left or right?
In the example https://developer.apple.com/documentation/imageio/writing-spatial-photos, we see that for each image encoded with the photo we include the following information: kCGImagePropertyGroups: [ kCGImagePropertyGroupIndex: 0, kCGImagePropertyGroupType: kCGImagePropertyGroupTypeStereoPair, (isLeft ? kCGImagePropertyGroupImageIsLeftImage : kCGImagePropertyGroupImageIsRightImage): true, kCGImagePropertyGroupImageDisparityAdjustment: encodedDisparityAdjustment ], Which will identify which image is left, and which is right, also information about group type = stereo pair. Now, how do you read those back? I tried to implement a reading simply with CGImageSourceCopyPropertiesAtIndex, and that did not work, getting back "No property groups found." func tryToReadThose() { guard let imageData = try? Data(contentsOf: outputImageURL), let source = CGImageSourceCreateWithData(imageData as NSData, nil) else { print("cannot read") return } for i in 0..<CGImageSourceGetCount(source) { guard let imageProperties = CGImageSourceCopyPropertiesAtIndex(source, i, nil) as? [String: Any] else { print("cannot read options") continue } if let propertyGroups = imageProperties[String(kCGImagePropertyGroups)] as? [Any] { // Process the property groups as needed print(propertyGroups) } else { print("No property groups found.") } //print(imageProperties) } } I assume maybe CGImageSourceCopyPropertiesAtIndex expects something as a 3rd parameter. But in the https://developer.apple.com/documentation/imageio/cgimagesource "Specifying the Read Options" I don't see anything related to that.
1
0
631
Jun ’24
How to disable exporting a content from the Quicklook preview in vision OS 2.0?
It is pretty cool that you can preview Spatial Photos and Videos with just PreviewApplication.push(...), but the issue is, you can disable the editing, but buttons to export content to Files still going to be there. So if my application uses this to showcase some proprietary or licensed content in my application, I cannot really disable an option of exporting it from my app. And another, more major issue, a lot of developers would not even know that user can save Previewed item, as this Save to Files button is not that easy to find.
0
0
417
Jun ’24