Post not yet marked as solved
I have come across a problem when using a NetworkExtension in Swift to utilise OpenVPN or Wireguard with the NETunnelProviderManager.
I have the following code in the ViewDidLoad() of my mainViewController. I don't load it twice, and it works fine when using the Apple integrated IKEv2.
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(vpnStatusDidChange(_:)), name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
But when I use OpenVPN or Wireguard via the Networkextension, these network-status-change-events keep firing n+1 upon each connection. First time it fires once. Second time I connect and disconnect, I see the network-statuses has fired twice, then three times etc.
I have been researching a lot and couldn't find a solution. But I found a possible workaround:
func loadTunnelProviderManager(completion:@escaping () -> Void) {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if error == nil {
self.tunnelProviderManager = managers?.first ?? NETunnelProviderManager()
completion()
}
}
}
If I don't retrieve managers?.first and instantiate it each time instead:
self.tunnelProviderManager = NETunnelProviderManager()
Then the issue is resolved. However every time I connect to the VPN, inevitably a new VPN config is also created in the settings, which is not ideal.
TL;DR
Long story short, how do I delete all existing managers before instantiating a new NETunnelProviderManager? I know this might go against the convention, but it will solve the issue.
Post not yet marked as solved
According to Apple:
"Early next year, you’ll be able to use custom product pages to create ad variations with Apple Search Ads. Custom product pages will be available to select right from your Apple Search Ads account, letting you create more relevant ads for different audiences." Source: https://developer.apple.com/app-store/custom-product-pages/
The time has finally come. We can now create custom product pages. I have created two of them and got them approved by Apple as well.
However in Adsearch, under creative set, I only can see the original screenshots that I had submitted to Apple as part of the release. I can't create ads for the product custom pages, that I got approved later on.
Any ideas or advice, please?
Thanks
Post not yet marked as solved
Hello,
In the code I have utilised the NEVPNManager to establish an IKEv2 connection to my StrongSwan server. I have disabled IPv4 on the server to focus only on the IPv6 issues.
When I run the app under MacOS, it works perfectly fine.
When I run the app under iPad (iOS) it also works perfectly fine. Both obtain an IPv6 from the server.
But when I run the app under my iPhone X, the IPv6 connection can't be established. I have updated the OS to iOS 15.1, but it didn't help. I have restarted the phone several times and made sure the DNS settings in Wifi connection is set to automatic.
When I do a sudo tcpdump icmp6 on the server I get this for iPad:
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:46:45.036393 IP6 fe80::9400:ff:fef1:6bcb > fe80::1: ICMP6, neighbor solicitation, who has fe80::1, length 32
08:46:45.037036 IP6 fe80::1 > fe80::9400:ff:fef1:6bcb: ICMP6, neighbor advertisement, tgt is fe80::1, length 24
But when I run it under my iPhone X I get errors on tcpdump:
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:49:36.594341 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 61921, length 121
08:49:36.594693 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 49461, length 155
08:49:36.605300 IP6 2a01:4f8:c17:1f2d::1 > one.one.one.one: ICMP6, destination unreachable, unreachable port, 2a01:4f8:c17:1f2d::1 udp port 63572, length 152
...
Does the iPhone has some sort of firewall enabled?
Below is my code. Why is the iPhone X affected, but not the iPad?
func connectIKEv2VPN() {
self.vpnManager.loadFromPreferences(completionHandler: vpnLoadHandler)
}
func vpnLoadHandler(error: (Error?)) -> Void {
let tkcs = MyKeychainService()
let deviceService = DeviceService.shared
var protcol: NEVPNProtocol
let ikev2 = NEVPNProtocolIKEv2()
ikev2.useExtendedAuthentication = true
ikev2.localIdentifier = "My VPN"
ikev2.remoteIdentifier = EnvFabric.shared.getUrlForCode(DeviceService.shared.getRetrievedServerCode())
ikev2.authenticationMethod = NEVPNIKEAuthenticationMethod.none
ikev2.deadPeerDetectionRate = NEVPNIKEv2DeadPeerDetectionRate.medium
ikev2.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
ikev2.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA256
ikev2.ikeSecurityAssociationParameters.diffieHellmanGroup = .group19
ikev2.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
ikev2.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
ikev2.childSecurityAssociationParameters.integrityAlgorithm = .SHA256
ikev2.childSecurityAssociationParameters.diffieHellmanGroup = .group19
ikev2.childSecurityAssociationParameters.lifetimeMinutes = 1440
ikev2.disableMOBIKE = false
protcol = ikev2
protcol.disconnectOnSleep = false
protcol.serverAddress = EnvFabric.shared.getUrlForCode(DeviceService.shared.getRetrievedServerCode())
self.vpnManager.localizedDescription = DeviceService.shared.getRetrievedServerName()
protcol.username = deviceService.getDeviceId()
tkcs.save(key: "DEVICE_TOKEN", value: deviceService.getDeviceToken())
protcol.passwordReference = tkcs.load(key: "DEVICE_TOKEN")
self.vpnManager.protocolConfiguration = protcol
self.vpnManager.onDemandRules = nil
self.vpnManager.isOnDemandEnabled = false
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: vpnSaveHandler)
}
func vpnSaveHandler(error: (Error?)) -> Void {
if let error = error {
if ((error as NSError).code == 4) {
return
}
} else {
do {
try self.vpnManager.connection.startVPNTunnel()
}
} catch let error {
SwiftyBeaver.warning("Error starting VPN Connection", error.localizedDescription)
}
}
}
Post not yet marked as solved
Hello,
So far we have been validating the receipts via a nightly script. But the proper way would be to handle App Store server notification to automate the process.
But our App is already live for sometime, if we'd set that URL we would get all production notifications sent straight to our test server.
But first we need to test it with a sandbox environment. How can we do this? There should have been two URLs in the application info, one for production and one for sandbox.
Any advice please?
Post not yet marked as solved
Hello,Based on what I read here promoted IAP's have be named differently than default IAPs to help with ASO.But it's not clear to me if I have to place the promoted IAPs in a separate group or not?e.g. under my non-promoted IAP subscription group I have the following:Arrange your subscriptions in descending order, starting with the option that offers the highest level of service. You can add more than one subscription to each level. This order will determine your subscription’s upgrade and downgrade options.1. Standard - One Week1. Standard - One Month1. Standard - One Year2. Lite - One Week2. Lite - One Month2. Lite - One YearSo do I now add a promoted IAP with optimised title and description inside the same group? Or in a different group?1. Standard - One Week1. Standard - One Month1. Standard - One Year2. Lite - One Week2. Lite - One Week - Promoted2. Lite - One Month2. Lite - One YearThank you,Houman
Post not yet marked as solved
I have signed out of Mac AppStore.When I try to attempt a IAP purchase on my MacOS app I get this error message shown:Account Not In This Store Your account is not valid for use in the U.S. store.You must switch to the U.K. store before purchasing.[Environment: Sandbox]I have created fresh Sandbox users, but the app is not asking me to enter them. And based on the documentation of Apple I shouldn't enter them into the AppStore login or I get them wasted.I have deleted the ~/Library/Containers/app-bundle-id, rebooted the dev machine and cleared once again the build folder. But I can't get it working.How do I get a prompt for entering the sandbox user?Any advice would be appreciated.
Post not yet marked as solved
I have been researching for a few days and haven't found a conclusive answer to my scenario.I would like to provide two subscription types on iOS: Lite and Standard.I would like to provide one subscription type on Mac: Standard.Standard is the bigger service that covers both iOS and Mac. Lite is the lesser one that only supports iOS.Based on what I see on AppStoreConnect, Mac has a complete separate IAP than iOS. Hence I can't share the same standard subscription type among the two platforms. Even though the standardservice is supposed to be cross-platform.I can certainly store each receipt type from iOS and Mac into my DB separately and do the validations directly with AppStore and MacStore respectively. But I can't stop the user from purchasing the standard subscription twice, once from iOS and then again from Mac. This is really bad since I wouldn't be able to refund it either if someone makes this mistake since Apple regards them as two different apps.Surely I can't be the only person with this problem, how is that supposed to be done, please?
Post not yet marked as solved
I have been investigating ifit's possible to achieve the following. I have both an IKEv2 VPN server and have a Swift iOS client. On the client side I have enabled the isOnDemandEnabled on the NEVPNManager and have set the rules to match anything.var vpnManager : NEVPNManager
var protcol: NEVPNProtocol
let ikev2 = NEVPNProtocolIKEv2()
ikev2.useExtendedAuthentication = true
...
protcol = ikev2
protcol.disconnectOnSleep = false
let connectRule = NEOnDemandRuleConnect()
connectRule.interfaceTypeMatch = .any
vpnManager.onDemandRules = [connectRule]
vpnManager.isOnDemandEnabled = trueThis should mean that any attempt to access the internet should match this rule and should only go over the VPN. (This is my understanding of it, I hope that's right).The Killswitch in VPN terminology is a feature that stops all internet traffic to go to and from the device, as soon as the VPN becomes unavailable. This is so to prevent any leakage in case the VPN tunnel becomes inaccessible. This could be as simple as monitoring if the current IP address fluctuates as a trigger to do this.What I couldn't find out is if iOS 10.3+ already does this in the background as long as the OnDemandfeature is enabled?Or is it just a way to reconnect to the VPN as soon as the VPN drops, but the traffic could still leak to the existing 4G without the VPN server present? I couldn't find any information yet this regarding. Any advice please? Hopefully Eskimo can see this, please. :-)Thanks,
Is IKEv2 MOBIKE mobility protocol supported by iOS NEVPNManager?ikev2.authenticationMethod = NEVPNIKEAuthenticationMethod.none
ikev2.deadPeerDetectionRate = NEVPNIKEv2DeadPeerDetectionRate.medium
ikev2.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
ikev2.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA256
ikev2.ikeSecurityAssociationParameters.diffieHellmanGroup = .group14
ikev2.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
ikev2.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
ikev2.childSecurityAssociationParameters.integrityAlgorithm = .SHA256
ikev2.childSecurityAssociationParameters.diffieHellmanGroup = .group14
ikev2.childSecurityAssociationParameters.lifetimeMinutes = 1440Is it something I have to configure separately or is it enabled out of the box?I would like to improve the connection or loss of when moving from cellular 4G to WiFi / WiFi to 4G. The server runs StrongSwan IKEv2, which supports IKEv2 MOBIKE mobility protocol out of the box. So my question is if the iOS NEVPNManager enables that automatically, or does it need to be configured?Many Thanks,Houman
Post not yet marked as solved
Hello,I have upgraded to Xcode 10 and now the rewarded Ad example from AdMob doesn't run anymore. It seems com.apple.commcenter.coretelephony.xpc is somehow corrupted.Can somebody confirm this, please?Many Thanks,2018-09-22 09:21:45.455938+0100 RewardedVideoExample[6416:294056] Failed to create remote object proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.456063+0100 RewardedVideoExample[6416:294077] Failed to ping server after delegate was set2018-09-22 09:21:45.456121+0100 RewardedVideoExample[6416:294075] Failed to create synchronous remote object proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.456234+0100 RewardedVideoExample[6416:294075] [NetworkInfo] Descriptors query returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.456537+0100 RewardedVideoExample[6416:294075] Failed to create synchronous remote object proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.456609+0100 RewardedVideoExample[6416:294075] [NetworkInfo] Descriptors query returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.470376+0100 RewardedVideoExample[6416:294075] Failed to create synchronous remote object proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.470519+0100 RewardedVideoExample[6416:294075] [NetworkInfo] Descriptors query returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}2018-09-22 09:21:45.649944+0100 RewardedVideoExample[6416:294080] WF: === Starting WebFilter logging for process RewardedVideoExample2018-09-22 09:21:45.650052+0100 RewardedVideoExample[6416:294080] WF: _userSettingsForUser : (null)2018-09-22 09:21:45.650131+0100 RewardedVideoExample[6416:294080] WF: _WebFilterIsActive returning: NO2018-09-22 09:21:46.000475+0100 RewardedVideoExample[6416:294076] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /Users/houmie/Library/Developer/CoreSimulator/Devices/3DF3454D-E65D-4E0A-A48F-B8FAB0717330/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles2018-09-22 09:21:46.001483+0100 RewardedVideoExample[6416:294076] [MC] Reading from private effective user settings.2018-09-22 09:21:46.035596+0100 RewardedVideoExample[6416:294056] <Google> Invalid Request. Cannot determine request type. Is your ad unit id correct?Reward based video ad failed to load: Request object configured wrong.2018-09-22 09:21:59.963218+0100 RewardedVideoExample[6416:294077] <Google> Invalid Request. Cannot determine request type. Is your ad unit id correct?Reward based video ad failed to load: Request object configured wrong.
Post not yet marked as solved
This would be very helpful to set the pricing right for a new app. Currently, I haven't found a way to see how much my competitors are charging in each region. Any advice, please?Many Thanks,
Post not yet marked as solved
There is one thing I don't quite understand when it comes to In-App Subscription purchase.I obtain the receipt on iOS client like this:private func loadReceipt() -> Data? {
guard let url = Bundle.main.appStoreReceiptURL else {
return nil
}
do {
let receipt = try Data(contentsOf: url)
return receipt
} catch {
print("Error loading receipt data: \(error.localizedDescription)")
return nil
}
}And send it for verification to my server (written in Python).def verify_receipt(self, receipt):
r = requests.post(config.APPLE_STORE_URL, json=receipt)
request_date_ms = DateUtils.generate_ms_from_current_time()
for item in r.json()['latest_receipt_info']:
expires_date_ms = int(item['expires_date_ms'])
if expires_date_ms > request_date_ms:
return True
return FalseI get the expires_date_ms from latest_receipt_info, and if it's greater than the current time in milliseconds, then the subscription counts as still valid.1) Would you say this is a solid way of verifying if the subscription is valid?2) What is the exact purpose of latest_receipthere? Is it a copy of the receipt that I just passed in? Could it be newer due to the latest attempt at subscribing? Should I save this one to the database for the current user, and test this receipt from now on going forward to see if the user is still subscribed?Thank you very much for your advice,
Post not yet marked as solved
I have implemented a subscription IAP for my VPN app. But since the VPN profile is stored on the iOS device itself, theoretically the user could just turn on the VPN from the settings, without having to open the app.This is a problem for users that have stopped paying the subscription. How can I prevent them from using the VPN from the back door?Many Thanks,