xcloud-python
xcloud-python copied to clipboard
ICE/STUN: Negotiation
Problem
ICE (Interactive Connectivity Establishment) / STUN is used to negotiate communication-channel between NAT'd hosts. Its currently only used for xhomestreaming. The initial ICE-message comes from the client (mobile device - iOS/Android) to the cloud.
Questions:
- Is Teredo involved for gathering that info?
- Is it related to host mxhome.ipv6.microsoft.com ?
- What are the 80 bytes long UDP packets, before STUN/ICE happens - is that maybe the communication with a STUN server to determine the Xbox's connectivity?
Current version of assembling the ICE request
https://github.com/tuxuser/xcloud/blob/8295d2c86bf8ece56dbbd02c1f749a4426955bcb/ice.py#L26-L37
You can test what the used library produces when gathering local candidates with following snippet:
import asyncio
from aiortc import RTCIceGatherer
async def main():
gatherer = RTCIceGatherer()
await gatherer.gather()
candidates = gatherer.getLocalCandidates()
params = gatherer.getLocalParameters()
print(':: Candidates')
for candidate in candidates:
print(candidate)
print(':: Params')
print(params)
asyncio.run(main())
Local IPs: 10.0.0.102
(Wireless), 10.0.0.246
(Wired)
Public IP: 126.242.118.111
Output:
:: Candidates
RTCIceCandidate(component=1, foundation='d175634b4f0f6f112c7c1cc9ad15ec68', ip='10.0.0.102', port=58503, priority=2130706431, protocol='udp', type='host', relatedAddress=None, relatedPort=None, sdpMid=None, sdpMLineIndex=None, tcpType=None)
RTCIceCandidate(component=1, foundation='c03547823954444e207cb7cb72c3c97c', ip='10.0.0.246', port=55610, priority=2130706431, protocol='udp', type='host', relatedAddress=None, relatedPort=None, sdpMid=None, sdpMLineIndex=None, tcpType=None)
RTCIceCandidate(component=1, foundation='b08d047b90595fc82469f8b2b3913eaf', ip='126.242.118.111', port=55610, priority=1694498815, protocol='udp', type='srflx', relatedAddress='10.0.0.246', relatedPort=55610, sdpMid=None, sdpMLineIndex=None, tcpType=None)
RTCIceCandidate(component=1, foundation='7eb039734c8997056a4537b2821f17f2', ip='126.242.118.111', port=58503, priority=1694498815, protocol='udp', type='srflx', relatedAddress='10.0.0.102', relatedPort=58503, sdpMid=None, sdpMLineIndex=None, tcpType=None)
:: Params
RTCIceParameters(usernameFragment='Goil', password='LCeehS7T9xJ0uYOBtvJbXz', iceLite=False)
Real / sample data
NOTE: The actual JSON post data is in a very fucked format, so I converted it for better visibility.
Original sample request, 1:1 as sent:
{
"candidates": "{\n \"Full\": \"1\",\n \"PacingMs\": \"50\",\n \"Version\": \"1\",\n \"Candidates\": {\n \"count\": \"2\",\n \"0\": {\n \"transportAddress\": \"10.0.0.187:46274\",\n \"baseAddress\": \"10.0.0.187:46274\",\n \"serverAddress\": \"\",\n \"ipv6\": \"0\",\n \"type\": \"0\",\n \"addressType\": \"3\",\n \"priority\": \"2130706175\",\n \"foundation\": \"1047782621\",\n \"transport\": \"udp\"\n },\n \"1\": {\n \"transportAddress\": \"[2001:0:338c:24f4:3405:17fd:a21d:47d7]:59394\",\n \"baseAddress\": \"teredo\",\n \"serverAddress\": \"\",\n \"ipv6\": \"1\",\n \"type\": \"4\",\n \"addressType\": \"0\",\n \"priority\": \"2130706431\",\n \"foundation\": \"1337598143\",\n \"transport\": \"udp\"\n }\n },\n \"Username\": \"F+R3n0qOTvc=\",\n \"Password\": \"ciypiKgGwlnWDQ8nqx3oFy3xs6eRHo4WpVDoFNjWyiM=\"\n}\n"
}
iOS
Request
POST https://uks.gssv-play-prodxhome.xboxlive.com/v4/sessions/home/<SESSION_GUID>/ice
{
"candidates": {
"Full": "1",
"PacingMs": "50",
"Version": "1",
"Candidates": {
"count": "7",
"0": {
"transportAddress": "[fe80::211:2daf:bbc4:7c6d]:59485",
"baseAddress": "[fe80::211:2daf:bbc4:7c6d%utun1]:59485",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130704895",
"foundation": "1966258098",
"transport": "udp"
},
"1": {
"transportAddress": "[fe80::f7d9:41:3b02:e963]:54748",
"baseAddress": "[fe80::f7d9:41:3b02:e963%utun0]:54748",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130705151",
"foundation": "1623794664",
"transport": "udp"
},
"2": {
"transportAddress": "[fe80::e8e2:a3ff:fe47:cf82]:57121",
"baseAddress": "[fe80::e8e2:a3ff:fe47:cf82%awdl0]:57121",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130705407",
"foundation": "4238851165",
"transport": "udp"
},
"3": {
"transportAddress": "[fe80::e8e2:a3ff:fe47:cf82]:50840",
"baseAddress": "[fe80::e8e2:a3ff:fe47:cf82%llw0]:50840",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130705663",
"foundation": "193038242",
"transport": "udp"
},
"4": {
"transportAddress": "10.0.0.210:64864",
"baseAddress": "10.0.0.210:64864",
"serverAddress": "",
"ipv6": "0",
"type": "0",
"addressType": "3",
"priority": "2130705919",
"foundation": "8449565",
"transport": "udp"
},
"5": {
"transportAddress": "[fe80::1]:60576",
"baseAddress": "[fe80::1%lo0]:60576",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130706175",
"foundation": "1535104454",
"transport": "udp"
},
"6": {
"transportAddress": "[2001:0:338c:24f4:429:211e:a21d:47d7]:57057",
"baseAddress": "teredo",
"serverAddress": "",
"ipv6": "1",
"type": "4",
"addressType": "0",
"priority": "2130706431",
"foundation": "2234788496",
"transport": "udp"
}
},
"Username": "u1hWGHuvhTs=",
"Password": "XFBjMQwX3CJxtHs1oj8WbzlT74I+P4gJWbh\\/OJrETgo="
}
}
Response
GET https://uks.gssv-play-prodxhome.xboxlive.com/v4/sessions/home/<SESSION_GUID>/ice
{
"candidates": {
"Full": "1",
"PacingMs": "50",
"Version": "1",
"Candidates": {
"count": "3",
"0": {
"transportAddress": "10.0.0.174:51068",
"baseAddress": "10.0.0.174:51068",
"serverAddress": "",
"ipv6": "0",
"type": "0",
"addressType": "3",
"priority": "2130705919",
"foundation": "3475377771",
"transport": "udp"
},
"1": {
"transportAddress": "[2001:0:338c:24f4:456:f3fd:a21d:47d7]:51069",
"baseAddress": "[2001:0:338c:24f4:456:f3fd:a21d:47d7]:51069",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "0",
"priority": "2130706175",
"foundation": "1346576940",
"transport": "udp"
},
"2": {
"transportAddress": "[fe80::456:f3fd:a21d:47d7]:51070",
"baseAddress": "[fe80::456:f3fd:a21d:47d7%6]:51070",
"serverAddress": "",
"ipv6": "1",
"type": "0",
"addressType": "4",
"priority": "2130706431",
"foundation": "2239954977",
"transport": "udp"
}
},
"Username": "K9rfTAAHfMI=",
"Password": "g3IuMXEcLVau\\/2QhQq6MvpsOqGBJHJ3T3+tg68p97fs="
}
}
Android
Request
POST https://uks.gssv-play-prodxhome.xboxlive.com/v4/sessions/home/<SESSION_GUID>/ice
{
"candidates": {
"Candidates": {
"0": {
"addressType": "3",
"baseAddress": "10.0.0.187:46274",
"foundation": "1047782621",
"ipv6": "0",
"priority": "2130706175",
"serverAddress": "",
"transport": "udp",
"transportAddress": "10.0.0.187:46274",
"type": "0"
},
"1": {
"addressType": "0",
"baseAddress": "teredo",
"foundation": "1337598143",
"ipv6": "1",
"priority": "2130706431",
"serverAddress": "",
"transport": "udp",
"transportAddress": "[2001:0:338c:24f4:3405:17fd:a21d:47d7]:59394",
"type": "4"
},
"count": "2"
},
"Full": "1",
"PacingMs": "50",
"Password": "ciypiKgGwlnWDQ8nqx3oFy3xs6eRHo4WpVDoFNjWyiM=",
"Username": "F+R3n0qOTvc=",
"Version": "1"
}
}
Response
GET https://uks.gssv-play-prodxhome.xboxlive.com/v4/sessions/home/<SESSION_GUID>/ice
{
"candidates": {
"Candidates": {
"0": {
"addressType": "3",
"baseAddress": "10.0.0.174:56974",
"foundation": "1251832755",
"ipv6": "0",
"priority": "2130705919",
"serverAddress": "",
"transport": "udp",
"transportAddress": "10.0.0.174:56974",
"type": "0"
},
"1": {
"addressType": "0",
"baseAddress": "[2001:0:338c:24f4:20c1:f3fd:a21d:47d7]:56975",
"foundation": "491644152",
"ipv6": "1",
"priority": "2130706175",
"serverAddress": "",
"transport": "udp",
"transportAddress": "[2001:0:338c:24f4:20c1:f3fd:a21d:47d7]:56975",
"type": "0"
},
"2": {
"addressType": "4",
"baseAddress": "[fe80::20c1:f3fd:a21d:47d7%6]:56976",
"foundation": "3489845490",
"ipv6": "1",
"priority": "2130706431",
"serverAddress": "",
"transport": "udp",
"transportAddress": "[fe80::20c1:f3fd:a21d:47d7]:56976",
"type": "0"
},
"count": "3"
},
"Full": "1",
"PacingMs": "50",
"Password": "lNj2y+Q3Jkec7SlUcsOwaAHOS5Fad4gKxmmHBumPnTo=",
"Username": "nxhPDLwFKc0=",
"Version": "1"
}
}
Libraries
aiortc aioice (used by aiortc)
Specs
RFC 4380 Teredo: Tunneling IPv6 over UDP through Network Address Translations (NATs) RFC 5245 Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols RFC 5839 Session Traversal Utilities for NAT (STUN) RFC 5991 Teredo Security Updates RFC 6081 Teredo Extensions RFC 8445 Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal