Filter messages on the network server, or before?

Hi,

If I understand this correctly: If you use the lora-app-server and have an organization without a gateway you could still send messages?

I’m after a solution that requires someone to ‘join’ a gateway via the GUI. If you haven’t ‘joined’ a gateway, you should not be able to send messages to the network server (aka a proxy should throw the message out, some sort of filtering).

I was thinking that you would implement something (like a proxy) between the packet forwarder and the lora-gateway-bridge. Before sending it further, it would check if that user has access to the gateway.

Is there any existing solution I could use in lora server? Or do I need to implement this?

This is not provided by the LoRa Server project, but could be done by connecting the MQTT broker authentication to the LoRa App Server database for example. Thus implementing this between the LoRa Gateway Bridge and your MQTT broker. How you implement this is up to you :slight_smile: See for example:

https://forum.loraserver.io/t/go-mosquitto-auth-plugin/448

Oh, awesome, Thank you!

One question: that plugin is just to limit what users have access to when subbing to a topic, correct?

Mosquitto normally allows you to restrict authentication and authorization through passwords and acls files, indicating which credentials may connect to the broker and to which topics they may subscribe/publish. But it also allows to plug some library to which it delegates this functionality, which is what the plugin does by offering several backends that can perform authentication and authorization, for example by checking that users exist and passwords match in a given postgres table, or that permissions to publish or subscribe for users are present in some redis instance.

In the repo issue you ask:

When and how is the postgres queries executed? Lets say “select password_hash from “user” where username = $1 and is_active = true limit 1”

In this case, when mosquitto gets a connection request, which contains a username/password, it forwards it to the plugin, which makes the check against the table user.

I think what @brocaar is pointing at is that the plugin allows you to customize those queries in order to match how you want to authenticate and authorize your users, for example having some table that relates gateways with users. But you could also think of and implement some more logic in it, as all the limitation a plugin for mosquitto has is the information mosquitto hands to it on connections and authorization requests (username/password for the former, clientid/username/topic/access for the latter), and what you do with it in some custom plugin is up to you (e.g., log to a DB every access, post requests to some external service, etc.).

Does that help?

Thanks for the explanation!

How does this work if we talk the Gateway Bridge? I know you can specify a username/password - but they are static, so I don’t really know who’s behind the request (expect a specific gateway, but not which user).

| Node | <-Lora-> | Packet Forwarder | ← UDP → | Gateway Bridge | ← MQTT → | Broker

Here the Gateway Bridge just send the messages from the node via MQTT (with lets say -u gw1 and -p gw1). I still don’t know who the user (who owns the node and sent the message) is. And have no idea if the user should have access to that getway (if the system should keep forwarding the messages or not).

I hope you understand what i mean. Thanks for all your help.

I think I get it: by user you mean an end device, i.e. a node’s devEUI, and you are looking to drop messages from devEUIs that should not have access to the gateway at the lora-gateway-bridge level to avoid forwarding them to the loraserver. Is that right?

I think it’s a lot of work for the gateway (not to mention duplicate, as it will be done by loraserver) just to save the trip from the gateway to the loraserver infrastructure, where the message could be easily checked and dismissed when necessary. I think this belongs at the application level and gateways shouldn’t be concerned with origin of messages, after all it doesn’t save them having to receive the message in some channel in order to check it. But I don’t know your use case, so who knows, maybe it is justified.

Anyway, the LoRaWAN expert here is @brocaar, so maybe he has a better response.

Yes @iegomez is correct here. The gateway does not and should not know the owner of the device.

Correct!

But could you explain a little bit more how the plugin work?

As I mentioned before, this is the the username and password for that the Lora Gateway Bridge provides, correct? And those are static. So even if you would filter the message in a later stage, you still don’t know how the user is (because the variable the auth-plugin uses is based on the mqtt username and password)

func GetUser(username, password string) bool {
	return false
}

Those parameters will always be provided (linked) to the mqtt username and password, is that correct?

Yes, that’s correct: mosquitto will only expose username/password for connections, and clientid/username/topic/access for topic’s pub/sub, which in both cases refers to the lora-gateway-bridge MQTT client’s username. Furthermore, that’s the only possible user that could get passed from the lora-gateway-bridge to mosquitto. Node’s have no user: they don’t publish MQTT messages, the gateway-bridge does it for them, so there’s really no concept of mosquitto user for nodes. Nodes only have a device EUI (devEUI) that identifies them, but as Orne says, the gateway doesn’t and should’t know about that devEUI. Finally, even if messages carried some user info in their data, the plugin can’t read the messages, only authenticate and authorize.

Again, identifying the origin of a message, i.e., from what node it comes from, is the network’s server responsibility, and the actual data carried in a message the application server’s one. As an example, TTN’s backend will drop any message from a device whose devEUI doesn’t start with a certain prefix, and that is done at the network server level.

Thanks! I get it now.

Might be OT: But how does the network server link a identity to the message? Is this done via the OTAA/ABP?

EDIT

Or the devaddr I guess.

OTAA and ABP are ways of provisioning keys to the device (with a join for OTAA, hardcoded for ABP), so there’s no difference for this case.

Is it stupid to make the devaddr unique?

Today, it two applications use the same devaddr (and somehow the same nwskey and appskey), the last application saved will get the message.

We want something, in every message, that could link a message to a user (or organisation).

An unique DevAddr will not work as the DevEUI is 64 bits, while the DevAddr address space is way smaller (I believe only 25 bits are used for the address space for LoRaWAN 1.0.x). To find out the risk of collisions, take a look at the “birthday paradox” (https://en.wikipedia.org/wiki/Birthday_problem)

For what is worth, I think you are doing it the wrong way and this belongs at the network server level, but I’m kind of interested in why you’d want to “forbid” devices from using a gateway (though, as said, that’s not possible in the physical RF sense).

Ok. I understand. But then you could get all nws-keys for that ABP session and then validate the MIC of the message with every nws-key you got. And then the devaddr + nws-key will be unique?

EDIT:
Seems you are doing something similar in GetDeviceSessionForPHYPayload() (?).

But this is the network server level? I’m taking the message from the lora-gateway-bridge. I just want the person owning the gateway to approve of every user that wants to use the gateway.

I was referring to the early idea of filtering at the gateway.

I get what you want to do, I was asking why you want to do it. Considering how Lora networks work, I can only imagine trying to prevent messages coming from certain devices through an specific gateway serves as a way to limit connection zones, i.e., there’s a zone covered by certain gateway and there are some devices that shouldn’t be able to communicate from that zone. The thing is it’s impossible to prevent the gateway from listening to the devices (unless they are configured in different channels/bands, but that’s another story), so there’s no “saving” from the gateway’s point of view (and that’s why I consider it shouldn’t be done at the gateway level), so it’s basically reducing coverage. On the other hand, if it doesn’t have anything to do with zones, i.e., gateways interleave in their cover zone, you are just losing throughput by limiting which gateways should be considered. I don’t see why a gateway owner should care if a message that goes through his gateway is dismissed or not later, whereas it is totally reasonable to limit access to that information at an upper level. Maybe I’m lacking some creativity, so if you are willing to comment on it, I’m still interested in what’s the use case. :wink: