|
The iPhone Wiki is no longer updated. Visit this article on The Apple Wiki for current information. |
Difference between revisions of "Apple Push Service Protocol"
(Add documentation about the fields in "connect" and "connected" commands) |
(Rename messages->commands and fields->items, since that's what apsd calls them. Also reduce heading levels.) |
||
| Line 1: | Line 1: | ||
iOS devices connect to Apple's push servers via port 5223. The protocol is proprietary and has nothing to do with XMPP (which uses the same port to establish SSL-encrypted client connections). The Push service protocol also uses SSL encryption. |
iOS devices connect to Apple's push servers via port 5223. The protocol is proprietary and has nothing to do with XMPP (which uses the same port to establish SSL-encrypted client connections). The Push service protocol also uses SSL encryption. |
||
| − | As of iOS5, Apple uses a new push protocol. The same protocol is used on the Mac too. With iOS4, the protocol used |
+ | As of iOS5, Apple uses a new push protocol. The same protocol is used on the Mac too. With iOS4, the protocol used command IDs <code>00</code> to <code>06</code>, while the new protocol uses command IDs <code>07</code> to <code>0f</code> and all fields in a message (called "items") have a consistent type-length-value encoding. |
| − | While every iOS version after that continued adding new |
+ | While every iOS version after that continued adding new commands and items, since iOS 10 there is ''another'' new push protocol known as "apnspack", which uses the same command and item IDs but encodes them in a completely different binary format. The client negotiates use of this new protocol with the protocol name "apns-pack-v1" in [[wikipedia:ALPN|ALPN]]. The apnspack format is not yet documented in this page. |
==Message Structure== |
==Message Structure== |
||
| Line 9: | Line 9: | ||
The format of the non-packed APNS protocol is as follows: |
The format of the non-packed APNS protocol is as follows: |
||
| − | *1 byte message type |
+ | *1 byte message type ("command ID") |
*4 byte payload length |
*4 byte payload length |
||
| − | * |
+ | *items, all with |
**1 byte type |
**1 byte type |
||
**2 byte length |
**2 byte length |
||
| Line 17: | Line 17: | ||
Example: |
Example: |
||
| − | *<code>07</code> |
+ | *<code>07</code> command ID (Connect) |
*<code>00 00 00 27</code> 39 byte payload length |
*<code>00 00 00 27</code> 39 byte payload length |
||
| − | *<code>01</code> |
+ | *<code>01</code> item 1 |
**<code>00 20</code> 32 byte length |
**<code>00 20</code> 32 byte length |
||
**<code>8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 ce 8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 ce</code>value 1 (32-byte push token) |
**<code>8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 ce 8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 ce</code>value 1 (32-byte push token) |
||
| − | *<code>02</code> |
+ | *<code>02</code> item 2 |
**<code>00 01</code> 1 byte length |
**<code>00 01</code> 1 byte length |
||
**<code>01</code> value |
**<code>01</code> value |
||
| − | == |
+ | ==Commands== |
| − | Note that some |
+ | Note that some items are optional, either because they're only sent depending on certain conditions, |
or because they were introduced in a later iOS version and earlier ones don't send it. |
or because they were introduced in a later iOS version and earlier ones don't send it. |
||
That will be documented in more detail later. |
That will be documented in more detail later. |
||
| − | + | ===07 Connect=== |
|
First command sent after SSL handshake is completed. |
First command sent after SSL handshake is completed. |
||
| Line 42: | Line 42: | ||
*Direction: device to server |
*Direction: device to server |
||
| − | * |
+ | *command ID: <code>07</code> |
| − | * |
+ | *items: |
**<code>01</code> 32-byte push token |
**<code>01</code> 32-byte push token |
||
**<code>02</code> 1 byte "state" (value <code>01</code>) |
**<code>02</code> 1 byte "state" (value <code>01</code>) |
||
| Line 60: | Line 60: | ||
**<code>14</code> 2-byte int, "TLS handshake time" in milliseconds |
**<code>14</code> 2-byte int, "TLS handshake time" in milliseconds |
||
| − | + | ===08 Connect Response=== |
|
*Direction: server to device |
*Direction: server to device |
||
| − | * |
+ | *command ID: <code>08</code> |
| − | * |
+ | *items: |
**<code>01</code> status (<code>00</code> ok, <code>02</code> some error) |
**<code>01</code> status (<code>00</code> ok, <code>02</code> some error) |
||
**<code>03</code> 32-byte push token (unless the device sent one in Connect) |
**<code>03</code> 32-byte push token (unless the device sent one in Connect) |
||
| Line 75: | Line 75: | ||
The lowest significant bit in 'capabilities' seems to mean "dual channel support" (possibly related to the iPhone proxying Apple Watch notifications). |
The lowest significant bit in 'capabilities' seems to mean "dual channel support" (possibly related to the iPhone proxying Apple Watch notifications). |
||
| − | + | ===09 Push Topics=== |
|
*Direction: device to server |
*Direction: device to server |
||
| − | * |
+ | *command ID: <code>09</code> |
| − | * |
+ | *items: |
**<code>02</code> 20-byte ID for enabled topic (like topic for push-enabled app or a specific iCloud service like Find My iPhone) |
**<code>02</code> 20-byte ID for enabled topic (like topic for push-enabled app or a specific iCloud service like Find My iPhone) |
||
**<code>03</code> 20-byte ID for disabled topic |
**<code>03</code> 20-byte ID for disabled topic |
||
| − | + | ===0A Push Notification=== |
|
*Direction: server to device (for iMessage and possibly others too, also the other way round) |
*Direction: server to device (for iMessage and possibly others too, also the other way round) |
||
| − | * |
+ | *command ID: <code>0a</code> |
| − | * |
+ | *items: |
**<code>01</code> recipient push token |
**<code>01</code> recipient push token |
||
**<code>02</code> topic |
**<code>02</code> topic |
||
| Line 94: | Line 94: | ||
**<code>07</code> unknown (<code>00</code>) |
**<code>07</code> unknown (<code>00</code>) |
||
| − | + | ===0B Push Notification Response=== |
|
*Direction: server to device (for iMessage and possibly others too, also the other way round) |
*Direction: server to device (for iMessage and possibly others too, also the other way round) |
||
| − | * |
+ | *command ID: <code>0b</code> |
| − | * |
+ | *items: |
**<code>04</code> response token |
**<code>04</code> response token |
||
**<code>08</code> status (<code>00</code> ok, <code>02</code> error) |
**<code>08</code> status (<code>00</code> ok, <code>02</code> error) |
||
| − | + | ===0C Keep-Alive=== |
|
*Direction: device to server |
*Direction: device to server |
||
| − | * |
+ | *command ID: <code>0c</code> |
| − | * |
+ | *items: |
**<code>01</code> connection method ("WiFi" or GSM MNC like "31038" for AT&T) |
**<code>01</code> connection method ("WiFi" or GSM MNC like "31038" for AT&T) |
||
**<code>02</code> iOS version, e.g. "5.0" |
**<code>02</code> iOS version, e.g. "5.0" |
||
| Line 111: | Line 111: | ||
**<code>05</code> unknown (values like <code>10</code>, <code>15</code> or <code>20</code>) |
**<code>05</code> unknown (values like <code>10</code>, <code>15</code> or <code>20</code>) |
||
| − | + | ===0D Keep-Alive Confirmation=== |
|
*Direction: server to device |
*Direction: server to device |
||
| − | * |
+ | *command ID: <code>0d</code> |
| − | *no |
+ | *no items |
| − | + | ===0E No Storage=== |
|
*Direction: server to device |
*Direction: server to device |
||
| − | * |
+ | *command ID: <code>0e</code> |
| − | * |
+ | *items: |
**<code>03</code> 32-byte push token |
**<code>03</code> 32-byte push token |
||
| − | + | ===0F Flush=== |
|
*Direction: both |
*Direction: both |
||
| − | * |
+ | *command ID: <code>0f</code> |
| − | * |
+ | *items: |
**2-byte integer indicating length of padding |
**2-byte integer indicating length of padding |
||
**padding: NULL-bytes, typical lengths are 64, 128, 256, 512 |
**padding: NULL-bytes, typical lengths are 64, 128, 256, 512 |
||
Revision as of 02:45, 3 August 2021
iOS devices connect to Apple's push servers via port 5223. The protocol is proprietary and has nothing to do with XMPP (which uses the same port to establish SSL-encrypted client connections). The Push service protocol also uses SSL encryption.
As of iOS5, Apple uses a new push protocol. The same protocol is used on the Mac too. With iOS4, the protocol used command IDs 00 to 06, while the new protocol uses command IDs 07 to 0f and all fields in a message (called "items") have a consistent type-length-value encoding.
While every iOS version after that continued adding new commands and items, since iOS 10 there is another new push protocol known as "apnspack", which uses the same command and item IDs but encodes them in a completely different binary format. The client negotiates use of this new protocol with the protocol name "apns-pack-v1" in ALPN. The apnspack format is not yet documented in this page.
Contents
Message Structure
The format of the non-packed APNS protocol is as follows:
- 1 byte message type ("command ID")
- 4 byte payload length
- items, all with
- 1 byte type
- 2 byte length
- value
Example:
07command ID (Connect)00 00 00 2739 byte payload length01item 100 2032 byte length8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 ce 8a 73 82 00 82 ac 91 32 88 b6 aa ef 90 91 65 cevalue 1 (32-byte push token)
02item 200 011 byte length01value
Commands
Note that some items are optional, either because they're only sent depending on certain conditions, or because they were introduced in a later iOS version and earlier ones don't send it. That will be documented in more detail later.
07 Connect
First command sent after SSL handshake is completed.
When a device is first activated, it doesn't have a push token yet. This command 07 is sent without a token, and the server returns a new token in its command 08 reply. In all future connections, the device sends the token in command 07, and the server doesn't return a token in command 08.
- Direction: device to server
- command ID:
07 - items:
0132-byte push token021 byte "state" (value01)054-byte flags, bitfield (example from iOS 12:00 00 02 6a)061 byte interface (0: cellular, 1: Wi-Fi)08cellular carrier name (or the string "WiFi")09OS version (example: 12.4.8)0aOS build (example: 16G201)0bhardware version (example: iPhone6,1)0ccertificate, contains the X.509 "device certificate" obtained during device activation0d17-byte nonce, first 8 bytes are milliseconds since epoch, rest is generated randomly0e"signature", consisting of bytes 01 01, followed by RSASSA-PKCS1-SHA1 signature of the nonce (0d) using the public key in the certificate (0c)102-byte int, possibly protocol version112-byte int, "redirect count"132-byte int, "DNS resolve time" in milliseconds142-byte int, "TLS handshake time" in milliseconds
08 Connect Response
- Direction: server to device
- command ID:
08 - items:
01status (00ok,02some error)0332-byte push token (unless the device sent one in Connect)042-byte int, max message size (value10 00)05unknown (value00 02)06capabilities (bitfield)082-byte int, large message size0a8-byte int, server time, milliseconds since unix epoch0b2 bytes, geo region (country code)
The lowest significant bit in 'capabilities' seems to mean "dual channel support" (possibly related to the iPhone proxying Apple Watch notifications).
09 Push Topics
- Direction: device to server
- command ID:
09 - items:
0220-byte ID for enabled topic (like topic for push-enabled app or a specific iCloud service like Find My iPhone)0320-byte ID for disabled topic
0A Push Notification
- Direction: server to device (for iMessage and possibly others too, also the other way round)
- command ID:
0a - items:
01recipient push token02topic03notification payload04response token05expiry (32-bit UNIX timestamp)06timestamp (64-bit UNIX timestamp in nanoseconds)07unknown (00)
0B Push Notification Response
- Direction: server to device (for iMessage and possibly others too, also the other way round)
- command ID:
0b - items:
04response token08status (00ok,02error)
0C Keep-Alive
- Direction: device to server
- command ID:
0c - items:
01connection method ("WiFi" or GSM MNC like "31038" for AT&T)02iOS version, e.g. "5.0"03iOS build number04device model, e.g. "iPhone2,1"05unknown (values like10,15or20)
0D Keep-Alive Confirmation
- Direction: server to device
- command ID:
0d - no items
0E No Storage
- Direction: server to device
- command ID:
0e - items:
0332-byte push token
0F Flush
- Direction: both
- command ID:
0f - items:
- 2-byte integer indicating length of padding
- padding: NULL-bytes, typical lengths are 64, 128, 256, 512