Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MCS: fallback to port 443 if 5228 is blocked #1662

Merged
merged 1 commit into from
Aug 1, 2022

Conversation

matttbe
Copy link
Contributor

@matttbe matttbe commented Feb 4, 2022

According to Google Firebase's doc, other ports than 5228 can be used:

If your organization has a firewall to restrict traffic to or from
the Internet, you need to configure it to allow mobile devices to
connect with FCM in order for devices on your network to receive
messages. FCM typically uses port 5228, but it sometimes uses 443,
5229, and 5230.

Src: https://firebase.google.com/docs/cloud-messaging/concept-options#messaging-ports-and-your-firewall

As suggested by @mar-v-in, it is enough to first try 5228 and then only
try with 443 as fall back port. Indeed, it would be surprising to find
any firewall blocking port 5228 but not 5229.

Closes: #408

Note: this PR was marked as "Draft" for the moment for 2 reasons:

  • I didn't code in Java for years :-D (but the modification was not complex)
  • I didn't know how to easily install the .apk I built on my side to test it on my personal phone (and not just a VM) because my package has a different signature than the one coming with the ROM (Lineage + MicroG).

The PR has now been tested and ready to be reviewed.

@matttbe matttbe marked this pull request as draft February 5, 2022 11:22
@matttbe
Copy link
Contributor Author

matttbe commented Mar 2, 2022

I was not able to validate it but probably good for review.

@matttbe matttbe marked this pull request as ready for review March 2, 2022 11:43
@chirayudesai
Copy link
Contributor

I don't know how I can easy install the .apk I built on my side to test it on my phone: it has a different signature than the one coming with the ROM (Lineage + MicroG).

It will, but you could replace the APK installed on the system with your own.

You can also try the emulator, https://github.com/microg/GmsCore/wiki/Development-Tools#using-the-emulator

Or with signature spoofing, any signature would be OK to upgrade it and all I need to do is to sign the APK? Or can I easily force the upgrade?

No, since that only spoofs the reported signature, and doesn't touch the actual app upgrade signature checking code.

@matttbe
Copy link
Contributor Author

matttbe commented Mar 4, 2022

Hi @chirayudesai

Thank you for your reply!

It will, but you could replace the APK installed on the system with your own.

Good idea. I tried this on Android 11 with Magisk: I had to create a Magisk module to replace /system/priv-app/GmsCore/GmsCore.apk but it doesn't seem to work.

Is it the wrong APK?

You can also try the emulator, https://github.com/microg/GmsCore/wiki/Development-Tools#using-the-emulator

Yes I guess I could, I don't know well that.

No, since that only spoofs the reported signature, and doesn't touch the actual app upgrade signature checking code.

ACK!

According to Google Firebase's doc, other ports than 5228 can be used:

    If your organization has a firewall to restrict traffic to or from
    the Internet, you need to configure it to allow mobile devices to
    connect with FCM in order for devices on your network to receive
    messages. FCM typically uses port 5228, but it sometimes uses 443,
    5229, and 5230.

Src: https://firebase.google.com/docs/cloud-messaging/concept-options#messaging-ports-and-your-firewall

As suggested by @mar-v-in, it is enough to first try 5228 and then only
try with 443 as fall back port. Indeed, it would be surprising to find
any firewall blocking port 5228 but not 5229.

If none of these ports, a new attempt will be done later as before.

Closes: microg#408
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
@matttbe matttbe force-pushed the gcm-mcs-port-fallback branch from 0bd1bc2 to 423db81 Compare March 5, 2022 10:41
@matttbe
Copy link
Contributor Author

matttbe commented Mar 5, 2022

I finally managed to validate this: I had to remove the data in /data/app/ to be able to use the app I built and installed in /system/priv-app/GmsCore/GmsCore.apk.

I found that in the previous version, I forgot to send the TEARDOWN message only if all ports had an issue. It is fixed now.

Here is what we can see when I block the port 5228 with iptables:

iptables -A OUTPUT -p tcp --dport 5228 -j REJECT --reject-with tcp-rst
03-05 11:24:50.607 D/GmsGcmMcsSvc(25411): Connection is not enabled or dead.
03-05 11:24:50.637 D/GmsGcmMcsSvc(25411): Connect initiated, reason: Intent { act=android.intent.action.MY_PACKAGE_REPLACED flg=0x4000010 pkg=com.google.android.gms cmp=com.google.android.gms/org.microg.gms.gcm.TriggerReceiver (has extras) }
03-05 11:24:50.637 D/GmsGcmMcsSvc(25411): Connection is not enabled or dead.
03-05 11:24:50.637 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:24:50.659 D/GmsGcmMcsSvc(25411): Starting MCS connection to port 5228...
03-05 11:24:50.719 D/GmsGcmMcsSvc(25411): Connection is not enabled or dead.
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): Exception while connecting to mtalk.google.com:5228
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): java.net.ConnectException: failed to connect to mtalk.google.com/172.253.120.188 (port 5228) from /:: (port 46212): connect failed: ECONNREFUSED (Connection refused)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:142)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:621)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:570)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:450)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:218)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:452)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:483)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.handleMessage(McsService.java:687)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at android.os.Handler.dispatchMessage(Handler.java:102)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at android.os.Looper.loop(Looper.java:223)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService$HandlerThread.run(McsService.java:185)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.Linux.connect(Native Method)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:138)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connectErrno(IoBridge.java:156)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:134)
03-05 11:24:50.730 W/GmsGcmMcsSvc(25411): 	... 15 more
03-05 11:24:50.730 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:24:50.742 D/GmsGcmMcsSvc(25411): Starting MCS connection to port 443...
03-05 11:24:50.790 D/GmsGcmMcsSvc(25411): Connected to mtalk.google.com:443
03-05 11:24:50.799 D/GmsGcmMcsSvc(25411): Activated SSL with mtalk.google.com:443
03-05 11:24:50.990 D/GmsGcmMcsSvc(25411): Sending login request...
03-05 11:24:50.993 D/GmsGcmMcsSvc(25411): Scheduling heartbeat in 300 seconds...
03-05 11:24:51.005 D/GmsGcmMcsSvc(25411): Connect initiated, reason: Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4200010 (has extras) }
03-05 11:24:51.095 D/GmsGcmMcsOutput(25411): Outgoing message: LoginRequest{id=android-30, domain=mcs.android.com, user=4562711192924308082, resource=4562711192924308082, auth_token=8623190068506771374, device_id=android-3f5201a7daf3c272, setting=[Setting{name=new_vc, value=1}], adaptive_heartbeat=false, use_rmq2=true, auth_service=ANDROID_ID, network_type=1}
03-05 11:24:51.095 D/GmsGcmMcsOutput(25411): Write MCS version code: 41
03-05 11:24:51.229 D/GmsGcmMcsInput(25411): Reading from MCS version: 41
03-05 11:24:51.243 D/GmsGcmMcsInput(25411): Incoming message: LoginResponse{id=android-30, jid=user@firebase.com/notifications, last_stream_id_received=1, server_timestamp=1646475890905}
03-05 11:24:51.284 D/GmsGcmMcsSvc(25411): Logged in
03-05 11:24:51.296 D/GmsGcmMcsInput(25411): Incoming message: IqStanza{type=SET, id=, extension=Extension{id=12, data=[size=0]}}
03-05 11:24:51.296 W/GmsGcmMcsSvc(25411): Unknown message: IqStanza{type=SET, id=, extension=Extension{id=12, data=[size=0]}}
03-05 11:25:05.615 I/ActivityManager(1434): Waited long enough for: ServiceRecord{bb82118 u0 com.google.android.gms/org.microg.gms.gcm.McsService}

And when I block the port 443 as well:

03-05 11:26:54.372 D/GmsGcmMcsSvc(25411): I/O error: java.net.SocketException: Connection reset
03-05 11:26:54.404 D/GmsGcmMcsSvc(25411): Teardown initiated, reason: java.net.SocketException: Connection reset
03-05 11:26:54.404 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:26:54.413 D/GmsGcmMcsSvc(25411): Scheduling reconnect in 5 seconds...
03-05 11:26:59.438 D/GmsGcmMcsSvc(25411): Connection is not enabled or dead.
03-05 11:26:59.438 D/GmsGcmTrigger(25411): Not connected to GCM but should be, asking the service to start up. Triggered by: Intent { act=org.microg.gms.gcm.mcs.RECONNECT flg=0x14 cmp=com.google.android.gms/org.microg.gms.gcm.TriggerReceiver (has extras) }
03-05 11:26:59.450 D/GmsGcmMcsSvc(25411): Connect initiated, reason: Intent { act=org.microg.gms.gcm.mcs.RECONNECT flg=0x14 cmp=com.google.android.gms/org.microg.gms.gcm.TriggerReceiver (has extras) }
03-05 11:26:59.450 D/GmsGcmMcsSvc(25411): Connection is not enabled or dead.
03-05 11:26:59.450 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:26:59.468 D/GmsGcmMcsSvc(25411): Starting MCS connection to port 5228...
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): Exception while connecting to mtalk.google.com:5228
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): java.net.ConnectException: failed to connect to mtalk.google.com/74.125.206.188 (port 5228) from /:: (port 38306): connect failed: ECONNREFUSED (Connection refused)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:142)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:621)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:570)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:450)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:218)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:452)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:483)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.handleMessage(McsService.java:687)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at android.os.Handler.dispatchMessage(Handler.java:102)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at android.os.Looper.loop(Looper.java:223)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService$HandlerThread.run(McsService.java:185)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.Linux.connect(Native Method)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:138)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connectErrno(IoBridge.java:156)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:134)
03-05 11:26:59.529 W/GmsGcmMcsSvc(25411): 	... 15 more
03-05 11:26:59.529 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:26:59.535 D/GmsGcmMcsSvc(25411): Starting MCS connection to port 443...
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): Exception while connecting to mtalk.google.com:443
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): java.net.ConnectException: failed to connect to mtalk.google.com/74.125.206.188 (port 443) from /:: (port 41366): connect failed: ECONNREFUSED (Connection refused)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:142)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:621)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.connect(Socket.java:570)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:450)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at java.net.Socket.<init>(Socket.java:218)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:452)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.connect(McsService.java:483)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService.handleMessage(McsService.java:687)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at android.os.Handler.dispatchMessage(Handler.java:102)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at android.os.Looper.loop(Looper.java:223)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at org.microg.gms.gcm.McsService$HandlerThread.run(McsService.java:185)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.Linux.connect(Native Method)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:138)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.ForwardingOs.connect(ForwardingOs.java:94)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connectErrno(IoBridge.java:156)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	at libcore.io.IoBridge.connect(IoBridge.java:134)
03-05 11:26:59.539 W/GmsGcmMcsSvc(25411): 	... 15 more
03-05 11:26:59.539 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:26:59.546 D/GmsGcmMcsSvc(25411): Unable to connect to all different ports, retrying later
03-05 11:26:59.552 D/GmsGcmMcsSvc(25411): Teardown initiated, reason: java.net.ConnectException: failed to connect to mtalk.google.com/74.125.206.188 (port 443) from /:: (port 41366): connect failed: ECONNREFUSED (Connection refused)
03-05 11:26:59.552 D/GmsGcmMcsSvc(25411): Closing all sockets...
03-05 11:26:59.560 D/GmsGcmMcsSvc(25411): Scheduling reconnect in 10 seconds...

(as you can see, I left the whole stacktrace in case of error to connect to the server)

So it seems to do the job and this is ready for review.

@mar-v-in mar-v-in merged commit 758fb76 into microg:master Aug 1, 2022
@mar-v-in
Copy link
Member

mar-v-in commented Aug 1, 2022

Thanks. LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Which Port is required? ( Firewall )
3 participants