-
Notifications
You must be signed in to change notification settings - Fork 78
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
Bluetooth IP Address Advertisement #325
base: master
Are you sure you want to change the base?
Conversation
I'm not very good at C, so I had no idea how to constrict most of the code here to be only run on a Linux system as I know that will be a big problem as if this is merged it means that no other platform will be able to build. |
I guess this is "BTLE" (BLE) described here: https://support.apple.com/guide/deployment/use-airplay-dep9151c4ace/web https://www.bluetooth.com/bluetooth-resources/the-bluetooth-low-energy-primer/ https://github.com/microsoft/windows-universal-samples/tree/main/Samples/BluetoothAdvertisement it's present in windows and macOS too.
|
That's it, Apple describes it as the "Bluetooth IP Address Advertisement". BLE avertisements can be sent out on Windows and macOS too - I might have a go at implementing it on Windows later, I'll just need to take a look at existing code and figure out how one implements different libraries for each platform etc. as I've never worked in C before.
Currently, the code is set so that it attempts to set up a BLE interface, if it doesn't find one/an error occurs (usually that it doesn't have the privileges as the program needs to be run as sudo) then it sends a message in the console saying it is disabled for the session as there was an error and gives up using BLE. It doesn't exactly send a DNS-SD advertisement over bluetooth, the payload size of a BLE advertisement is very small due to power limitations and so instead all that gets sent in the payload is the following 8 bytes:
All that still needs to be implemented is using the Windows BLE library if on Windows and I assume using the linux library on mac (unless there is an alternative - Will need to look into this). Also I've just realised that it only gets the ethernet iface IP address atm, so people using Wi-Fi won't have their ip broadcast - I will fix this soon. |
can you take a look at SimpleBLE (a GPL v3 cross-platfom BLE implementation) ? https://github.com/OpenBluetoothToolbox/SimpleBLE Unfortunately the large number of "issues" suggests its not quite mature yet.... |
C++ with "extern C" wrappers for interface with C works. uxplay.cpp does this. |
I remember seeing this library when I began trying to put it all together, since I didn't really know anything about C I stayed away from it because of the no. of issues (fixing my own problems was going to be enough, let alone having problems because the library was causing them). Will take a look at it tonight and try to use this library instead as that will make it a lot easier than implementing it differently for each platform. |
BLE does look like a good feaure to add, thanks for your work on this |
Thank you - Off topic but I've been fighting for a while to try to figure out how H265 works, struggling with wrapping my head around the HomeKit pairing process as it's not easy. Will keep trying though as I'm keen on figuring it out. Whilst I've got you - How do you reverse engineer all of this? I'm sure at the start you could use existing docs and research, but the things you're doing currently like HLS aren't really that well documented, and so I'm interested to know how you figure the stuff like that out when it's behind an encrypted channel of communication? Do you have a custom proxy solution that you use? |
HLS was a total mystery. incomplete pieces of a code with no ancestry in our own code base had appeared on github from time to time, with no license or provenance., until late last year, when someone interested noticed the full C++ code was recently published with a GPL license as "apsdk-public", but not in a usable state, as a demo and the fairplay substitute (playfair) were stripped out. It seems that a single author had been working on it since 2017. Luckily, looking back in the code history we were able to restore an earlier working demo, and see how to put back fairplay, which was indeed what was being used. (It's the only partial "crack" of fairplay that has been achieved, so I believe all open source and non-apple closed source implementations use it). Finally, by filling up the working demo with printf statements at every function call, the HLS workings became traceable and understandable. A working example that one can add printf's to is the key, when there is not much documentation. apsdk-public has a C++ interface to a 2017 C hlsparser found on github. we borrowed this interface as apsdk is GPL, and gave C wrappers to it, and connected it to adapted UxPlay. . The remaining issues are GStreamer integration, so at some point uxplay will get HLS support (at least for youtube videos, since netflix has removed non-apple airplay support.) Homekit pairing (from the client viewpoint) is semi documented at https://github.com/ejurgensen/pair_ap with server and client implementation. This also includes a client-only implementation of legacy-pairing it calls "fruit pairing" with SRP that was very useful for using on a true AppleTV to see what its SRP server responses were (this is the one-time pairing protocol, also used in homekit) , and fill in undocumented details by guess-and-check. https://github.com/philippe44/libraop was also very useful, but does not do homekit. |
Unfortunately not. In legacy pairing (even with SRP authentication, which sets up what COULD be used for total communication encryption ) I was surprised to find that after all the work to implement SRP authentication, it doesnt enforce total encryption. But homekit does, as can been seen in https://github.com/ejurgensen/pair_ap, and seems to use (apple-modified) SRP with the "big random integer" upped from 2048 to 3072 bits. |
one design possibility is that the running uxplay writes its BLE message to a file that only exists while uxplay is running, and some helper function, running as root if that is needed, broadcasts it on bluetooth at appropriate intervals if it exists? something like that is implement in the -dacp option for interfacing with a remote controller for the iOS client. I am assuming that the client responds on the network, not with reverse BLE? |
|
I think apple generally uses the non-connectable BLE, for things like
e.g https://github.com/MarketStreetCyber/Blabber/blob/main/impersonate/setup_appletv.py uses "ADV_NONCONN_IND" which I assume is non connectable |
SimpleBLE won't be enough unfortunately - It doesn't seem to support broadcasting advertisements (and it took me 4 hours to include in the project). I'll have to have a go at writing an implementation for each platform. We're talking about non-connectable here, as @thiccaxe said the ADV_NONCONN_IND. Meaning that the listening device (iOS devices) cannot connect to the device - As such, like you said, the client responds by sending an HTTP request to the IP address in the BLE advertisement. |
This reverts commit efed512.
@connorh315 Confirming your observation that simpleBLE doesnt do advertising, I found this discussion on the simpleBLE discord server: It also seems that simpleBLE development was previously supported by developer's previous employer, and has now stalled (he comments: For a project like this to prosper, raw manpower is not enough if it’s not coordinated, as it leads to a steady degradation of the code quality. Either by managing people or coding myself, this is work that needs to put food on the table in one way or another.)
|
I think that BLE on Windows is going to be a bit of a pain to implement, I can't find any reliable docs/examples on using the Bluetooth libraries to broadcast an advertisement. Perhaps for now, I could just make the functions empty when building for Windows? It's a bit of a cheap cop out but I don't have long before I go back to work and don't want to leave this open - All this means is that the feature will only work on Linux. What do we all think? |
That's fine. If its activated by an option (e.g. -ble ) one can test for windows and reject the option with an error message at startup. I am more worried about your earlier mention of running as root, etc. can you explain a bit more ? |
is this a useful ref? https://punchthrough.com/creating-a-ble-peripheral-with-bluez/ ideally Uxplay would just write the advertisement that should be sent to a file that only exists while uxplay is running,and some bluez service (running as root) would detect that file, read it and transmit the contents with BLE. Is such a thing possible? |
I've had a look at the link that you've sent, I am probably able to rewrite it all to use the D-Bus, however I'm not entirely sure that this circumvents using sudo. I could give it a go though. As an alternative, I have discovered that a user can run Let me know whether this is suitable, as I do understand your concern with running UxPlay as sudo (especially since it seems to break GStreamer). |
once a working prototype is available, one can see how to improve it. Ideally uxplay would write a file with the BLE message to be sent, just like the -dacp option, and a separate helper script would periodically check for the existence of that file and if it is found send the BLE message. UxPlay works fine as root, with the firewall switched off, I checked. This is fine for testing. The main thing is to have a working prototype to start with. |
What's the problem with the current prototype so I know what needs to be done to improve that atm? And just so I understand as well what's the reason you want a separate helper script rather than the solution being a part of the UxPlay binary? |
BLE is tangential to UxPlay and not really core. I think it would make sense to use something like python for ble as it already has a (probably) better package (bleak). Also, I am going to say with some confidence that ble will eventually run into issues like needing to be rebroadcasted, restarted, what is Bluetooth is turned of, etc. let a user script take care of that. It also allows faster iteration and the feature can be published quicker. Dont want to use python? Any language can read / watch a file |
@connorh315 I haven't yet tested your prototype, if its working, that's great as a start. but writing the platform-independent BLE message text to a file that something else reads and sends the message is a truly cross-platform solution. |
@connorh315 I am trying to test your prototype.
This means uxplay -btip will run with no avahi-daemon service present. This should test your BLE advertisement.
|
Sure. Current setup: In order to suppress dnssd, I added a return 1 on line One issue that is definitely something that I need to fix is that the IP that it grabs is from the I'd suggest adding a logger on line 90 of Should the code fail to initialize/send commands to the bluetooth interface it will spit out two messages, the first message being either line 49 or line 55. The second message is in uxplay.cpp where it will output that it will disable all attempts at BLE for the rest of the lifetime of the program (to prevent the console from being spammed). Should all be well, you won't see any messages in the console regarding bluetooth (perhaps I should change this and make it clear the service is running?) |
describe what I should see on the client: I assume uxplay should show up as a choice for mirroring (but for me it doesn't, with dnssd disabled)? what tests should show ble is working? (something with bluetoothctl, I guess). |
So if its working, with dnssd suppressed, I should see uxplay on the client in the normal way? should I also use bluetoothctl to verify BLE in some way?
This would be a very useful contribution. |
Exactly. I think I need to have a go at fixing some of the issues I've already described and then I'll set up a few other systems to test, would you mind telling me what system you're testing this on - Or at the very least the distro and the bluetooth card (especially what type it is: USB, internal etc.).
Assuming no errors are displayed it should have correctly initialized and set up the HCI for advertising. Unfortunately there is no way of viewing the advertisements that are sent out (Unless you're willing to buy a BLE development board like I did) in Wireshark.
Transient pairing does not require pair-verify at all, once the initial M1-M4 steps are completed the devices can derive their public/private keys off of the session_key and at that point begin encrypting their comms. I initially added libsodium I was planning on including the entire pair_ap repo as a submodule, but there was a lot of build errors that I couldn't wrap my head around so I ended up moving the individual functions myself. Despite it being in the Cmake file, I didn't use libsodium at all in the end. |
I have two usb bluetooth v5 plugins testing on linux x86_64 desktop, varius distros, or Rpi 4 or 5. all with with systemd and bluetoothctl. Yes, no libsodium please. The main thing is to have a working prototype. Then a cleaned-up integration into uxplay can easily be done. can you point out in your code the server response that starts the client encryption? |
Perfect, will try to fix up the code a little bit better. I assume you're connected to the network via wifi?
In |
@connorh315 Here is ancient 10 years old code to apparently implement an BLE beacon (which I think is what you are doing?)) https://github.com/dburr/linux-ibeacon
|
Question for you though, how can I get the IPV4 address of the adapter that the http server hosts a socket on? Is there a struct containing this as I couldn't easily find one by search. That's probably the main reason why the code wasn't working for you as no matter what it's currently broadcasting the address of the ethernet interface, and not the actual interface used for the http server. |
The address being used in the test is in fact eth0: so your code is using the correct address , so that doesnt explain why it didnt work. I will test with a bluetooth 4.0 adapter which I also ordered , (I'm using 5.x) |
I'm working on having the uxplay startup extract ipv6, ipv6 (global) and ipv6 (link-local) non-temporary addresses for Uxplay.c (github, master) will soon have std::strings ip4, ip6_global, ip6_local available soon after uxplay starts. I'll post here when it's available. |
Has to be an ipv4 address btw, thats the standard set for the ble advert |
That's a relief! I figured out with a lot of google help how to distinguish "permanent" from "temporary"(privacy) ipv6 addresses in Windows, but in Linux it was still not clear. In Linux "old style" permanent ipv6 addresses based on MAC address are still in use, "new style" ones are not so common, but I did not yet find how to detect these from C. |
Gotcha. I think there is a variation in the BLE advertisement that I'd read somewhere (something along the lines of 09 06 06 instead of 09 06 03 for the message). I wasn't entirely sure what the purpose of it might be but interestingly that might be ipv6? Doesn't really matter though ipv4 should be suitable. Would you still like me to clean this up or would you like to test yourself first and then we clean this all up afterwards? Unrelated but I figured out how to trigger a proper h265 stream that contains the necessary information to decode it. I posted about my findings in a discussion in this repo. Not sure if you'd seen it or not. |
The nRF52840 arrived, but the setup instructions seem daunting. Does one need the whole SDK installed to just use the sniffer feature, or can one dispense with that.? |
Err, don't think you need the SDK. I followed these instructions and it worked just fine. Something that's worth noting is I had to flash my dongle with new firmware for it to be set up in sniffing mode. |
I think a custom library is going to need to be built for advertising over BLE on all the different operating systems. Additionally, I think that DBus can be used to circumvent needing root, as according to this root should only be required because I'm directly interfacing with hci, rather than using a higher level impl. such as DBus. Not too sure on that though. |
https://stackoverflow.com/questions/37287026/bluez-library-access-as-non-root-user |
systemd guide:https://www.linux.com/topic/desktop/systemd-services-monitoring-files-and-directories objective:"uxplay -btip" when started writes a file ~/.uxplay.btip containing the BLE announcement. On exit, uxplay deletes this file. This can be modeled on the similar action of the -dacp option. systemd monitors the existence of this file. while it exists, it runs a systemd service every x secs that uses bluez to send the uxplay BLE service advertisement. |
After Bluetooth discovery, is Wi-Fi Direct networking still needed? |
If you mean needed in the sense of discovering the device: no. The Bluetooth discovery tells the sender what IP to find the receiver under. The sender will then attempt a connection under the local network it is attached to, and will discover the receiver if it is on the same network. I do still think that Wi-Fi direct would be a nice feature though, so if you were asking on whether it is worth implementing Wi-Fi Direct: I still think so. |
I misunderstood; I thought this Bluetooth was Bluetooth broadcasting in P2P. https://support.apple.com/en-hk/guide/deployment/dep9151c4ace/web |
0f7948d
to
1a77a9f
Compare
Sometimes the service discovery is a bit slow (or non-existent on poorly managed networks). This is an alternative method for Airplay senders to detect receivers. It involves frequently sending out the IP address of the receiver over Bluetooth. If a sender is in range and has Bluetooth enabled it will pick up the BLE advert, and then send a special "GET /info" request to the IP address in question to receive data similar to that which is broadcast by the DNS-SD. The IP address advertisement leads to more reliable discovery from testing.
Only works on Linux currently, requires sudo (as well as a BLE interface too). Enable this with the -btip argument