invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.71k stars 2.22k forks source link

Blocking app-measurement.com breaks realtime-database connection during push notification processing #1469

Closed kernel-sanders closed 5 years ago

kernel-sanders commented 6 years ago

Issue

When processing a push notification, I am updating an entry in my realtime-database. During testing, this would work ~1/2 the time. Digging into the console logs, it appears as if react-native-firebase is trying to re-use an old TCP connection to firebase, and after some time (~5 to 10 minutes) that connection is stale and does not work. Instead of opening a new connection and completing the update to the database, it simply fails. I believe this is because the device is on a network with a Pi-Hole which sinkholes app-measurement.com and e.crashlytics.com. The react-native-firebase library attempts to connect to app-measurement.com for the analytics, but if it can't it does not continue with any other connections? I believe this is a bug. If the analytics connection fails, the database update should occur anyway. Whitelisting e.crashlytics.com resolves the issue.

AppDelegate.m

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  NSLog(@"Got Local Notification");
  [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  NSLog(@"Got Remote Notification");
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  NSLog(@"Got User Notification");
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

Message handler code:

// Subscribe to push notifications for background notifications (priority 10 with alert)
firebase.notifications().onNotificationDisplayed((notification: Notification) => {
      console.log('onNotificationDisplayed');
      console.log(notification);
      firebase.database().ref(`/users/${currentUser.uid}`).update({ lastMessage: notification });
      firebase.database().ref(`/users/${currentUser.uid}/lastMessage`).update({ type: 'onNotificationDisplayed' });
      firebase.database().ref(`/users/${currentUser.uid}/lastMessage`).update({ timestamp: new Date() });
});

First push console logs (successful database update):

default 10:29:50.084513 -0400   appname Got Remote Notification
default 10:29:50.084560 -0400   appname Unknown aps key: content-available
default 10:29:50.338727 -0400   appname TCP Conn 0x1c417e900 event 1. err: 0
default 10:29:50.338821 -0400   appname TCP Conn 0x1c417e900 complete. fd: 8, err: 0
default 10:29:50.338861 -0400   appname TCP Conn 0x1c417e900 starting SSL negotiation
default 10:29:50.432625 -0400   appname TCP Conn 0x1c417e900 SSL Handshake DONE
default 10:29:50.699275 -0400   dasd    COMPLETED com.apple.pushLaunch.com.companyname.appname:97F734 <private>!

Second push console logs (no database update - URL redacted):

default 10:44:31.643363 -0400   appname Got Remote Notification
default 10:44:31.643430 -0400   appname Unknown aps key: content-available
default 10:44:31.643681 -0400   appname [com.companyname.appname] Did deliver 1 notifications
error   10:44:31.914655 -0400   appname nw_socket_get_input_frames recvmsg(fd 6, 1024 bytes) [57: Socket is not connected]
default 10:44:31.916060 -0400   appname TCP Conn 0x1c417cf80 canceled
default 10:44:31.916820 -0400   appname [12 s-usc1c-nss-211.firebaseio.com:443 stream, pid: 45453, traffic class: 200] cancelled
    [12.1 9C21CD12-026B-45CC-9091-D0A3A27FE0C3 10.42.5.54.49602<->35.201.97.85:443]
    Connected Path: satisfied (Path is satisfied), interface: en0, ipv4, dns
    Duration: 225.976s, DNS @0.000s took 0.275s, TCP @0.277s took 0.024s
    bytes in/out: 0/0, packets in/out: 0/0, rtt: 0.000s, retransmitted packets: 0, out-of-order packets: 0
default 10:44:31.921393 -0400   appname TIC Enabling TLS [11:0x1c4360540]
default 10:44:31.921525 -0400   appname TIC TCP Conn Start [11:0x1c4360540]
default 10:44:31.921972 -0400   appname Task <09C17321-38DB-417C-8E2B-5768DF7E15B0>.<1> setting up Connection 11
default 10:44:31.922181 -0400   appname [14 app-measurement.com:443 stream, pid: 45453, url: https://app-measurement.com/config/app/1:XXXXXXXX:ios:XXXXXXXXXX?platform=ios&app_instance_id=XXXXXXXXXXXXXXXXXX, tls] start
default 10:44:31.970071 -0400   appname TIC TCP Conn Event [11:0x1c4360540]: 3
error   10:44:31.970126 -0400   appname TIC TCP Conn Failed [11:0x1c4360540]: 1:61 Err(61)
default 10:44:31.970180 -0400   appname TIC TCP Conn Cancel [11:0x1c4360540]
error   10:44:31.970439 -0400   appname Task <09C17321-38DB-417C-8E2B-5768DF7E15B0>.<1> HTTP load failed (error code: -1004 [1:61])
default 10:44:31.970591 -0400   appname [14 app-measurement.com:443 stream, pid: 45453, url: https://app-measurement.com/config/app/1:XXXXXXXXX:ios:XXXXXXXXXXXX?platform=ios&app_instance_id=XXXXXXXXXXXXXXXXXX, tls] cancelled. Events:
default 10:44:31.970682 -0400   appname 0.000s [14 1218D1F1-C727-4CA6-AB5D-A9242D8939C0 app-measurement.com:443 resolver] path:start
default 10:44:31.970742 -0400   appname 0.000s [14 1218D1F1-C727-4CA6-AB5D-A9242D8939C0 app-measurement.com:443 resolver] path:satisfied
default 10:44:31.970820 -0400   appname 0.000s [14 1218D1F1-C727-4CA6-AB5D-A9242D8939C0 app-measurement.com:443 resolver] resolver:start_dns
default 10:44:31.970873 -0400   appname 0.036s [14 1218D1F1-C727-4CA6-AB5D-A9242D8939C0 app-measurement.com:443 resolver] resolver:receive_dns
error   10:44:31.970981 -0400   appname Task <09C17321-38DB-417C-8E2B-5768DF7E15B0>.<1> finished with error - code: -1004
default 10:44:31.971021 -0400   appname 0.037s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] path:start
default 10:44:31.971183 -0400   appname 0.038s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] path:satisfied
default 10:44:31.971359 -0400   appname 0.039s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] flow:start_nexus
default 10:44:31.971399 -0400   appname 0.039s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] flow:receive_nexus
default 10:44:31.971643 -0400   appname 0.043s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] flow:start_connect
default 10:44:31.971678 -0400   appname 0.047s [14.1 AC9AE0D8-8A86-46EE-B65C-1723D8BA10DE 10.42.5.54:56308->10.42.5.8:443 channel-flow] flow:failed_connect Error Domain=kNWErrorDomainPOSIX Code=61 "Connection refused" UserInfo={NSDescription=Connection refused}
default 10:44:31.971733 -0400   appname 0.047s [14 1218D1F1-C727-4CA6-AB5D-A9242D8939C0 app-measurement.com:443 resolver] resolver:children_failed
default 10:44:31.971767 -0400   appname 0.048s [14] path:cancel
default 10:44:32.052176 -0400   dasd    COMPLETED com.apple.pushLaunch.com.companyname.appname:4C6488 <private>!

Environment

  1. Application Target Platform:

    iOS
  2. Development Operating System:

    macOS High Sierra, 10.13.6
  3. Build Tools:

    Xcode 9.4.1 (9F2000)
  4. React Native version:

    0.54.2
  5. React Native Firebase Version:

    4.3.8
  6. Firebase Module:

    database/messaging
  7. Are you using typescript?

    no
Salakar commented 6 years ago

My initial looking through the iOS SDK code indicates that app-mesaurement.com is also used for network reachability testing:

https://github.com/firebase/firebase-ios-sdk/blob/master/GoogleUtilities/Network/GULNetwork.m#L248 and https://github.com/firebase/firebase-ios-sdk/blob/master/GoogleUtilities/Network/GULNetworkConstants.m#L24

, which is why other services like database are failing most likely - I think. 🙈

cc @wilhuff & @paulb777 from the firebase/firebase-ios-sdk GitHub repo - any thoughts on this issue?

wilhuff commented 6 years ago

Preliminarily I'd consider this a bug in your filter configuration in Pi-hole. There's a major difference between third-party non-consensual ad-serving/tracking, and first-party app analytics/crash reporting that happens to be implemented with Firebase.

Our disposition is not to fight against ad blockers or otherwise hostile networks. We don't use them, we don't test them, etc. We're not opposed to making our software work better in their presence, but this is not a priority for us--there's only so many hours in the day.

If you're interested in making this better, pull requests are welcome.

bobobo1618 commented 5 years ago

@wilhuff as someone who actively blocks traffic like this on-device, I'd be interested in making this work. Would you accept a PR that simply changes the host to connectivitycheck.gstatic.com or captive.apple.com? That seems like a simple way to solve both issues.

Salakar commented 5 years ago

I'm gonna close this issue as it's not related to this library, we only consume the official Firebase SDKs, any changes would need making there.

Feel free to continue discussing though.

wilhuff commented 5 years ago

@bobobo1618 that's not really my call. @paulb777 what's your take?

If this is going to get anything past spitballing I'd suggest moving this discussion to an issue/PR in the firebase-ios-sdk repo.

paulb777 commented 5 years ago

@bobobo1618 At first glance, I suspect we would accept such a PR. However, we'd need to do a bit more investigation and get a few more reviewers/approvers.

Please create an issue or PR at https://github.com/firebase/firebase-ios-sdk with details about the issue and why the proposed hosts would address it along with any trade-offs between the two.

bobobo1618 commented 5 years ago

Thanks @paulb777, I created https://github.com/firebase/firebase-ios-sdk/issues/2254.