Push notifications when suspicious activity is detected
When suspicious activity is detected there should be an option to send user push notification through Ntfy service.
Sending Ntfy messages can be done via HTTP PUT/POST or via the CLI (with curl).
this needs the device to have internet access. Maybe this could be one option besides offering an API on the device to check for notifications. So people can create rayhunter companion apps :)
So I did some tests and here is what you need to do (assuming that Rayhunter device has internet access):
- On your mobile phone install Ntfy app and then add "self-hosted ntfy server" (go to Settings - Server URL and enter
https://ntfy.envs.net/. You can use official Ntfy server, but is not very reliable,envsis working fine. In the ntfy app then tap the "+" button and enter the topic name you want to subscribe to. You can made up anything for topic name, however it should be unique enough name that others are unlikely to guess. Why? Because topics are basically public (unless you use authentication)! In this example I am assuming your topic name isMyTopic. Also, I recommend to set that Ntfy has unlimited battery use and that android does not remove permissions if app is not used for some time. - Then you can test sending the notifications from command line. Here are example commands.
If you are using curl:
curl -d "TEST message!" https://ntfy.envs.net/MyTopic. If you are usingwget:wget --post-data="TEST message!" https://ntfy.envs.net/MyTopic -O - &> /dev/null
That is it. @m0veax reported that TP-LINK M7350 device has wget (and not curl), and wget supports HTTP only. So in that case you can use http://ntfy.envs.net/MyTopic, which is not very safe, but it works.
However, there is an option to create a Go binary (for Arm64 architecture), to send message through HTTPS.
Here is a quick and dirty example (send_ntfy.go) with topic name and server hardcoded:
package main
import (
"bytes"
"fmt"
"net/http"
)
func sendNtfyMessage(topic, message string) error {
// Construct the URL for the ntfy topic
url := fmt.Sprintf("https://ntfy.envs.net/%s", topic)
// Create the request body
body := bytes.NewBufferString(message)
// Send the HTTP POST request
resp, err := http.Post(url, "text/plain", body)
if err != nil {
return fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
// Check the response status
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
fmt.Println("Message sent successfully!")
return nil
}
func main() {
// Define the topic and message
topic := "MyTopic"
message := "Test message from Rayhunter!"
// Send the message
err := sendNtfyMessage(topic, message)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}
Then you can cross compile:
set GOOS=linux
set GOARCH=arm64
go build -o send_ntfy_arm64 send_ntfy.go
Copy the binary (send_ntfy_arm64) to a Rayhunter device, make it executable (chmod +x) and run it (./send_ntfy_arm64).
What do you think?
You can use this code: https://github.com/MatejKovacic/ntfy-go/
I would support push notifications though I think it should be behind a config flag since it will require an active service plan to work as @m0veax mentions. I think we should build it directly into rust instead of relying on wget or curl. I would be happy to accept a PR for this feature.
I just made a successful test on M7350, however I needed to disable certificate checking.
So it is working!
Updated Go code is here (see at the end of page): https://github.com/MatejKovacic/ntfy-go/blob/main/README.md
Unfortunately, I don't know Rust, but this is a proof of concept, that this could be done.
I would support push notifications though I think it should be behind a config flag since it will require an active service plan to work as @m0veax mentions. I think we should build it directly into rust instead of relying on wget or curl. I would be happy to accept a PR for this feature.
I'd agree. I don't love having something have to go out to the internet when it should really be local. If the threat model is that you're living your life or having a conversation and want to know if there's an IMSI catcher then you really can't just keep watching the LCD. But, you can't really expect the internet to be reliable enough for a bunch of services to work well enough that a push works. Polling an API on the rayhunter or maybe giving the rayhunter a rest callback to hit where it's all local seems to be more reliable.
Truthfully, it's too bad that the orbic device doesn't have a buzzer :)
yea I really wish it had a buzzer or a speaker or something!
OK, I did this: https://github.com/MatejKovacic/ntfy-send
It is an app to send Ntfy push notifications from TP link devices. If there is no internet connection, sending does not fail, but message is stored into queue and sent later, when internet connection is available. I think this is important, because if IMSI catcher does MITM it will block internet connection, so notifications would not be sent.
P. S. This is written in Rust. I do not know Rust at all, but managed to do this with the help of Deepseek (I described what I want, when there were compile errors, I pasted errors to LLM, got new version... and so on, until app was working). So this is merely a proof of concept, someone who actually knows Rust, should check this. Anyhow, I tested the app well, and sending messages and clearing the queue works really nice.
i think that if the notification does not go out in real-time, it doesn't have a lot of value. if it arrives "whenever" then I can also just look at the device sometime later.
rayhunter has a HTTP API -- i propose to write a tool that polls this API, and run this tool on a device that is in the modem's wifi. this would be useful if you carry the modem around with you, at least.
maybe browser notification API can be used from the webinterface as well.
Yes. I agree with @untitaker.
Does the RayHunter advertise itself on the lan side in any way (mDNS?) such that an app would be able to discover it and start polling the HTTP API for updates? If so, I presume that it would be pretty straight-forward to write a iOS/Android mobile app that polls it and notifies the user.
Well, one interesting option would be to use small computer connected through WiFi or USB. One interesting option would be LicheeRV-Nano-W (with USB and wifi/BT) or even more basic version with USB only (LicheeRV-Nano-B) which costs around 17 EUR.
It is running modern Debian (someone ported it) with systemd. You can solder speaker and connect a small touch screen! Unfortunately a board has built-in microphone, which is a security risk, but you can unsolder it.
This would give us options for sound alert, more heavy processing and storage of the data, even GPS... but yes, it would require some hardware development...
Alternatively, NordicSemi has released a System-on-Package (nRF91 series) that has a built-in cellular modem and processor. There are development boards available with it. They're not FCC certified in that form, but it would be trivial for a device to be made with a speaker and light. The trick would be maintaining the rule set that identifies the IMSI catcher
Oooo. I'm going let this hang out in my brain a bit. I was also thinking about how to get Rayhunter to send me alerts without having to be looking at the Orbics screen.
I meeean comissioning our own hardware for this would be a dream, we could get all the things we want and turn this into a whole sigint platform with detection of bluetooth and wifi fuckery as well, it would be cool to have lora on board too!
oh my goddddd that would be the dreammm
FWIW, I attempted a prototype of integrating notifications into the rayhunter code with a config option. While the code itself is pretty straightforward, getting a TLS library cross compiling so we can hit ntfy over https ended up more complicated than I was anticipating. From what I can tell, the setup instructions in @MatejKovacic's ntfy-send tool are approximately what we'd need to add to the setup instructions for rayhunter (at least for Linux and Mac, I'm less clear on Windows).
I believe reqwest with rustls should cross compile easily. unsure whether the resulting binary is small enough though
That's what I attempting to use. The error is ToolNotFound: failed to find tool "armv7l-linux-musleabihf-gcc": No such file or directory (os error 2). The error comes from trying to build ring, which reqwest configures rustls to use as a cryptography provider. It works after downloading, extracting, and adding armv7l-linux-musleabihf-cross.tgz from https://musl.cc/ to the path.
I can check the change in the binary size too. I'm happy to try to get the notification code into a PR-able state if you're OK adding a couple steps to the build setup process.
Edit: binary size goes from 4.6M to 5.5M
i'm not sure but it's also not my call. i'd make a PR anyway and see if people like it. after all, see comment from cooper:
I would support push notifications though I think it should be behind a config flag since it will require an active service plan to work as @m0veax mentions. I think we should build it directly into rust instead of relying on wget or curl. I would be happy to accept a PR for this feature.
my concern that a solution that requires a working internet connection will not be very reliable, and I would not use it because the SIM card I use is not activated. personally i'd need something that pulls data directly onto my phone over the router's wifi, so i'm thinking, android app that keeps the phone awake.
but a solution that exists today is better than one that is "perfect" and is never built.
Yes, but we can have a queue (so mesaages are sent when internet connection is restored, and sending notifications could be setting in configuration.
I think we should have a subsystem that detects whether there is an internet connection or not and enables / disables certain features based on that (like push notifications, future auto updates, etc.)
I found what feels like a simple solution to the build issue, which is to add a clang/llvm dependency. I pushed a draft PR that adds a config option for an ntfy channel and enables notifications if it's set. Right now it's just notifying for new detections but I was thinking a low battery notification would be useful as well.
I'll wait for directional feedback from @cooperq before adding documentation to the PR, but thoughts from others is also appreciated. And if someone has a mac or non-orbic devices and doesn't mind giving it a try that would be great.
hey @simonft, thanks for working on that! while Ntfy is probably the closest i've seen to the kind of service we're looking for, i still have a couple concerns about it:
- their privacy policy (https://docs.ntfy.sh/privacy/) is delightfully short and readable, but it doesn't clarify how long message or topic data is retained, which is a real concern if our notifications contain any sensitive information
- since Ntfy topics are effectively passwords (if you guess someone's topic, that's all you need to read the notifications), i worry we're setting up a major footgun for users who aren't making very secure topic names
- Ntfy can be self-hosted, which is great, but i worry about hitching our horse to a paid service that i don't know that well
because of 1 & 2, i tend to think any Ntfy notifications we send should contain 0 sensitive info, which IMO means they should be as opaque as possible -- maybe even just a generic "Rayhunter has emitted a warning!" message. and because of 3, we should let the user configure the Ntfy service URL.
also, while it doesn't necessarily have to make it into the first implementation, it'd be good if the UI clearly indicated whether there's network connectivity so the user knows whether or not notifications will reliably make it through.
taking a different tack, @untitaker mentioned the possibility of using Meshtastic for user notifications. i'm not super knowledgable about Meshtastic's inner workings, but from what i've skimmed it seems like this would require connecting the rayhunter device to a Meshtastic node (either over WiFi or possibly the USB/serial connection) and broadcasting notifications to a user's private channel. this would let notifications remain encrypted from the rayhunter device to the destination node, and then a user could read the decrypted notification in the myriad ways Meshtastic allows (app, browser, device screen, etc).
at a surface level, this feels like a better environment for notifications that may contain sensitive info, but if someone knows otherwise please correct me!
at a surface level, this feels like a better environment for notifications that may contain sensitive info, but if someone knows otherwise please correct me!
yeah i played with it for a few days now, i think it's worth continuing pursuing but i don't think it will be reliable or all that user friendly. ntfy definitely seems easier to reason about, i'd be in favor of merging it because i really don't see a better solution or architecture cropping up in the near- to mid-term.
after talking it over w/ the team some more, i think we're good to go on accepting this ntfy-based approach! @simonft are you still free to work on the PR you submitted?
Yep, I think I can continue work on it this week. The notification text is currently "New warning triggered!" which is maybe too generic. I can change that to "Rayhunter has emitted a warning!", allow changing the ntfy server, and update the docs.
Maybe user should have the option to set the text? Also, what about some variables, for instance to describe a warning. I. e to tell which indicator got activated?
Maybe user should have the option to set the text? Also, what about some variables, for instance to describe a warning. I. e to tell which indicator got activated?
i think more descriptive text could be useful down the road, but for the first implementation i think i'd prefer sticking to an opaque notification and allow the user to use a more secure channel to pull down the actual analysis
Generally I agree, but I prefer that user decides what should be the text. Of course, there should be a little warning, that this is not really secure channel, but I prefer user freedom (based on informed decision).
Just my to cents.