(:trumpet: Note: This project has been archived following the release of Wireshark 4.0, which includes native support for Secure Connect. 🎺)
With this plugin, you can view and analyze BACnet Secure Connect (BACnet/SC) traffic from within Wireshark. This plugin has been tested with node-to-hub communication and node-to-node (direct connect) communication.
Ensure that you have a recent (>= 3.0.0) version of Wireshark installed. Then, add the included bsc.lua
file to your Wireshark Plugin Directory. That's it.
- Open
Help -> About Wireshark
on Windows and Linux orWireshark -> About Wireshark
on MacOS.
- Go to the
Folders
tab.
- Click on the link in the row labeled
Personal Lua Plugins
. If the folder doesn't already exist, Wireshark will offer to create it for you.
- A folder will open. This is where you should put the included
bsc.lua
file.
BACnet/SC is different than other BACnet data links because it runs on top of another existing transport layer called WebSockets. WebSockets run on top of HTTP, HTTP runs on top of TLS, and TLS runs on top of TCP (wowsers).
If your traffic is on TCP port 80 or 443, you can skip this part.
-
Open
Analyze -> Decode As
and click the+
icon to add a new row to the table. -
If your traffic is TLS encrypted, set
Field
toTLS Port
. Otherwise, setField
toTCP port
. -
Set
Value
to the TCP port number you are using, andCurrent
toHTTP
. If you are using port 47808, it should look like this:
If your traffic is in plain text, you can skip this part.
BACnet/SC traffic is encrypted over the wire, which is good because no one else on the network can read it or tamper with it. It's also frustrating if you want to troubleshoot a device.
Fortunately, Wireshark has support for decrypting TLS traffic. Doing this requires having access to one of the nodes' private keys OR having access to to a key log file. Getting access to either of these things is usually application and device specific.
If you're a software developer looking to add support for key log files to your application, here are a few links that might get you started:
- The original SSLKEYLOGFILE from NSS
- An Agent for Java programs
- The relevant function call for OpenSSL
- The relevant property in recent versions of Python
-
Open
Edit -> Preferences
on Windows and Linux orWireshark -> Preferences
on MacOS. -
Expand the tree item labeled
Protocols
and click onTLS
.- If you have a private key from a node, register it by clicking
Edit
button and adding it to theRSA keys list
. - If you have a key log file, click
Browse
to set the(Pre)-Master-Secret log filename
.
- If you have a private key from a node, register it by clicking
-
Click
OK
to save your changes.
Once the plugin is installed and TLS decryption is working, you should be able to explore and analyze BACnet APDUs and NPDUs like normal.
Additionally, you will be able to view fully dissected BACnet/SC headers and payloads.
This plugin supports dissecting the following BACnet/SC message types:
- BVLC-Result
- Encapsulated-NPDU
- Address-Resolution
- Address-Resolution-ACK
- Advertisement
- Advertisement-Solicitation
- Connect-Request
- Connect-Accept
- Disconnect-Request
- Disconnect-Accept
- Heartbeat-Request
- Heartbeat-ACK
Additionally, limited support is provided for working with Proprietary-Message messages.
With this plugin, you can filter messages based on over forty different fields. Here are some examples:
Description | Expression |
---|---|
All BACnet messages | bsc |
Link layer broadcast messages | bsc.destination_vmac == ff:ff:ff:ff:ff:ff |
Connect requests from 96742512-60b0-4e50-bd0e-accaadcf164e |
bsc.connect_request.uuid == 96742512-60b0-4e50-bd0e-accaadcf164e |
Nodes connected to a secondary hub | bsc.advertisement.conn_status == 2 |
Proprietary header options from vendor 510 |
bsc.option.vendor_id == 510 |
Field | Selector | Data Type |
---|---|---|
Function | bsc.function |
uint8 |
Control | bsc.control |
uint8 |
Reserved Bits | bsc.control.reserved |
uint8 |
Originating Virtual Address | bsc.control.has_orig_vmac |
bool |
Destination Virtual Address | bsc.control.has_dest_vmac |
bool |
Destination Options | bsc.control.has_dest_opts |
bool |
Data Options | bsc.control.has_data_opts |
bool |
Message ID | bsc.message_id |
uint16 |
Originating Virtual Address | bsc.originating_vmac |
ether |
Destination Virtual Address | bsc.destination_vmac |
ether |
Destination Option | bsc.destination_option |
none |
Data Option | bsc.data_option |
none |
Header Option Marker | bsc.option.marker |
none |
More Options Follow? | bsc.option.has_more |
bool |
Must Understand? | bsc.option.must_understand |
bool |
Header Option Data Present? | bsc.option.has_data |
bool |
Option Type | bsc.option.type |
uint8 |
Option Length | bsc.option.length |
uint16 |
Option Data | bsc.option.data |
none |
Vendor ID | bsc.option.vendor_id |
uint16 |
Proprietary Type | bsc.option.proprietary_type |
uint8 |
Data | bsc.option.proprietary_data |
none |
Payload | bsc.payload |
none |
Field | Selector | Data Type |
---|---|---|
Function | bsc.bvlc_result.function |
uint8 |
Result | bsc.bvlc_result.code |
uint8 |
Error Marker | bsc.bvlc_result.error_marker |
uint8 |
Error Class | bsc.bvlc_result.error_class |
uint16 |
Error Code | bsc.bvlc_result.error_code |
uint16 |
Error Details | bsc.bvlc_result.error_details |
string |
Field | Selector | Data Type |
---|---|---|
WebSocket URI | bsc.address_resolution.uri |
string |
Field | Selector | Data Type |
---|---|---|
Hub Connection Status | bsc.advertisement.conn_status |
uint8 |
Accepts Direct Connects | bsc.advertisement.accepts_direct_connects |
uint8 |
Maximum BVLC Length | bsc.advertisement.maximum_bvlc_len |
uint16 |
Maximum NPDU Length | bsc.advertisement.maximum_npdu_len |
uint16 |
Field | Selector | Data Type |
---|---|---|
VMAC Address | bsc.connect_request.vmac |
ether |
Device UUID | bsc.connect_request.uuid |
guid |
Maximum BVLC Length | bsc.connect_request.maximum_bvlc_len |
uint16 |
Maximum NPDU Length | bsc.connect_request.maximum_npdu_len |
uint16 |
Field | Selector | Data Type |
---|---|---|
VMAC Address | bsc.connect_accept.vmac |
ether |
Device UUID | bsc.connect_accept.uuid |
guid |
Maximum BVLC Length | bsc.connect_accept.maximum_bvlc_len |
uint16 |
Maximum NPDU Length | bsc.connect_accept.maximum_npdu_len |
uint16 |
Field | Selector | Data Type |
---|---|---|
Vendor ID | bsc.proprietary_message.vendor_id |
uint16 |
Function | bsc.proprietary_message.function |
uint8 |
Proprietary Data | bsc.proprietary_message.data |
bytes |
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Getting BACnet/SC support into Wireshark is my ultimate goal.
Rather than developing a built-in dissector right away, I thought it might be nice to build some consensus around what sort of information needs to be surfaced from BACnet/SC messages and what the best way to present it is.
Like Wireshark, this software is licensed under the GPL