JoelBender / bacpypes

BACpypes provides a BACnet application layer and network layer written in Python for daemons, scripting, and graphical interfaces.
MIT License
298 stars 129 forks source link

Remote network responds to WhoIsIAm but not ReadProperty #518

Closed edavis0 closed 6 months ago

edavis0 commented 7 months ago

Hello,

I'm running BACpypes on a device that is connected to a local BACnet network. Running a WhoIsIAm.py shows that there are two BACnet networks. One is the same subnet that my device is on, and the other is a remote network that I can not see through an nmap.

For the sake of this example, let's use the following network information: Local network: 192.100.100.xxx/24 Remote network: 192.123.123.xxx/24

When I run WhoIsIAm.py, I receive a response from BACnet devices on the local and remote networks.

Here's an example output: pduSource = <Address 192.100.100.123> iAmDeviceIdentifier = ('device', 1) maxAPDULengthAccepted = 1024 segmentationSupported = segmentedBoth vendorID = 8 pduSource = <Address 192.123.123.123> iAmDeviceIdentifier = ('device', 2) maxAPDULengthAccepted = 1024 segmentationSupported = segmentedBoth vendorID = 8

However, when I run ReadProperty.py, I can only interrogate devices on the local network (192.100.100.xxx/24). If I interrogate devices on the remote network (192.123.123.xxx/24) using ReadProperty.py, I receive noResponse.

I believe the router is located at 192.100.100.1. Do you have any advice for how I could resolve this? Is it possible due to my .ini file? Here is my .ini structure:

[BACpypes] objectName: Betelgeuse address: 192.100.100.23/24 objectIdentifier: 599 maxApduLengthAccepted: 1024 segmentationSupported: segmentedBoth vendorIdentifier: 15

Feel free to let me know if there is a better place to submit this question!

bbartling commented 7 months ago

just a suggestion here... but if your just starting out you could probably just dive right into the bacpypes3 which is the new asyncio based version. There is a samples directory to get started with and you dont need the .ini file in bacpypes3 as well.

https://github.com/JoelBender/BACpypes3

Python 3.12 and above drops some core modules which may force people to migrate to bacpypes3 anyways.

edavis0 commented 7 months ago

Thanks, @bbartling. Unfortunately, I'll need to use this version in this scenario. I appreciate the advice, though.

JoelBender commented 6 months ago

When you are sending out a broadcast Who-Is request it is being picked up by a local BBMD, forwarded to its peer on the other network, then re-broadcast. Similarly, its I-Am is also broadcast, picked up by the BBMD on its network, forwarded to the BBMD on your network, then re-broadcast. If the two BBMD's can chat with each other with unicast traffic then all of the devices on the two should also be able to chat back and forth.

Another test is to send a unicast Who-Is directly to the device on the remote network and see if you get a response. If there are firewall rules blocking your request you won't get a response because the remote device didn't get the request. The remote device could be responding with a broadcast, so you'll get the response as before, but until unicast requests and responses can pass between the devices then confirmed services won't work.

Also try running Wireshark on your client and see if that I-Am is being sent to you directly (it will be an Original-Unicast-NPDU) or forwarded by the BBMD, when looking at the application layer of the packet those details are abstracted away. Modern BACnet devices use unicast I-Am responses, older ones use broadcast.

It's possible that the two BBMD's are actually on the same host, like a dual NIC (multi-link multi-homing) or VLAN (single-link multihoming), and even though there is an IPv4 router between the two networks that doesn't show up in the unicast or broadcast packets between the two devices (e.g., it's not in the IP and UDP headers), so I'm still thinking it's a firewall rule problem.

edavis0 commented 6 months ago

Thanks for the explainer, @JoelBender. When I send a Who-Is to the entire network, the remote network devices respond with an Original-Unicast-NPDU I-Am.

When I use WhoIsIAm.py to send a Who-Is directly to a device on the remote network (ex. whois 2 2), the Who-Is is sent as an Original-Broadcast-NPDU, and the I-Am response is received as an Original-Unicast-NPDU.

It's not clear to me how to force a unicast Who-Is request with the WhoIsIam.py tool. To test unicast traffic, I also tried to ping the remote device. I was not able to get a response.

Unless this message tells you differently, I think your firewall assumption is correct. I'll investigate that path and report back.

Thanks again.

edavis0 commented 6 months ago

After further investigation, I found that firewall rules were not the culprit of the issue.

The issue was instead due to lack of proper routing in the IP routing table. There was not a defined route to the remote network, and my device was using another NIC for unicast traffic. Once I added a route to the remote network for the correct NIC, I was able to send unicast traffic to the remote network devices.