1 Grundlagen
In einem BACnet/SC-Netzwerk gibt es genau ein Gerät, das als Hub fungiert. Die Kommunikation zwischen anderen Geräten, als Nodes bezeichnet, erfolgt über diesen Hub. Weiterhin kann es - muss aber nicht - einen FailoverHub im Netzwerk geben. Der FailoverHub übernimmt die Aufgabe eines Hubs, wenn der ursprüngliche Hub ausgefallen ist. Die Nodes müssen die Adresse des Hubs und des FailoverHubs kennen.
Der Netzwerkverkehr ist verschlüsselt.
Es kann auch "DirectConnections" zwischen jeweils zwei Nodes geben, sofern die Geräte so etwas unterstützen. Sobald diese eingerichtet ist, wird der Hub nicht mehr als "Kommunikationszentrale" benutzt. Die SC Geräte werden anhand ihrer VMAC-Adresse (Beispiel: 2b7b1abbb33c) adressiert bzw. unterschieden.
Jedes SC Gerät hat eine eineindeutige UUID (Beispiel: 4Zb6794-9c57-4b6c-88f8-d728ae328d70)
2 BACnet/SC allgemeine Hinweise
Vorlagen für BACnet SC-Skripte werden von BTF bereitgestellt unter:
C:\Program Files (x86)\MBS\BTF\Documentation\SampleScripts\SC_Tests\
Es ist sinnvoll, diese Dateien einschließlich der gcom_ports.py und config_files, in das Projektverzeichnis zu kopieren, damit sie in einem BTF-Export enthalten sind.
Für einen BTF-Export wird empfohlen, die Pfade der Wireshark Secrets-Dateien (in pre_shared_secret_log_file) für BTF und die Auto-Scripte identisch zu setzen und im Projektverzeichnis zu platzieren. Die Dateinamen müssen unterschiedlich sein. Die Zertifikate sollten ebenfalls im Projektverzeichnis gespeichert werden.
Es ist ggf. sinnvoll, für Tests mit verschiedenen bacstackd.ini Dateien auch verschiedene ROOT-Verzeichnisse bei den Tests anzulegen. Wenn in einem Test-ROOT-Verzeichnis verschiedene bacstackd.ini Dateien benutzt werden, dann ist nicht reproduzierbar, mit welcher ini-Datei ein Test gelaufen ist.
In den bacstackd.ini-Dateien, insbesondere in den Auto-Scripten, die auf bacstackd.ini-Dateien verweisen, werden IP-Adressen angegeben. Diese müssen auf dem TD-Netzwerkadapter konfiguriert sein.
HINWEIS: In den BACnet-Einstellungen im BTF wird die VMAC des IUT als MAC-Adresse für IUT festgelegt.
Die IP-Logger-Verbindungen können wie folgt eingestellt werden:
[TD] -i "TD-net" -w <FN>
mit "TD-net" = Name des Netzwerkadapters
3 Verschlüsselung der Datenübertragung
Für die Verschlüsselung und Entschlüsselung benötigt jedes BACnet/SC-Gerät drei Zertifkatsdateien:
Eine Zertifikatsdatei der Zertifizierungsstelle (oft ca-cert.crt genannt).
Eine Zertifikatsdatei für das TD/BTF selbst (z.B. btf-cert.crt für BTF).
Eine Schlüsseldatei für das Gerät selbst (z.B. btf-key.pem für BTF).
In jedem BACnet/SC-Gerät müssen diese drei Dateien vorhanden oder konfiguriert sein. Zum Einstieg in die SC-Tests kann es sinnvoll sein, identische Zertifikatsdateien für jedes Gerät zu verwenden, um potenzielle Fehlerquellen zu minimieren. Im Verlauf des Tests sollte jedoch für jedes Gerät unterschiedliche Zertifikatsdateien verwendet werden. Die Zertifikatsdatei der Zertifizierungsstelle muss jedoch für jedes BACnet/SC-Gerät gleich sein. Die Dateinamen und Dateierweiterungen sind grundsätzlich frei wählbar.
4 Einrichten für IUT EPICS
Im IUT EPICS müssen im DeviceObjekt folgende Einträge vorhanden sein, inklusive der Kommentarzeichen "--":
-- BTF-Extension Data_Layer_VMAC_Address: 2b7b1abbb33c
-- BTF-Extension Data_Layer_Net_Number: 20
-- BTF-Extension Device_UUID: 4Wb67949c574b6c88f82b7b1abbb33c
-- BTF-Extension Server_External_Visible_Uri: wss://169.254.1.179:47808
Es ist sicherzustellen, dass die Daten gemäß den IUT-Spezifikationen angepasst sind. Die Daten sind absichtlich
an mehreren Stellen redundant, da verschiedene Tests auf unterschiedliche Quellen angewiesen sind.
Die Netzwerknummer muss für alle Geräte einheitlich eingestellt sein (Routing wird an dieser Stelle nicht behandelt). Die Server_External_Visible_Uri muss mit der des IUT übereinstimmen. Sie wird aber nur benötigt wen das IUT auch Hub ist.
Unter Data Link Layer Option einstellen: BACnet/SC
Unter Special Functionality sollte eingestellt sein, wenn das IUT ein Hub sein kann: BACnet/SC Hub
5 Einrichten für TD EPICS
Für bestimmte Tests oder IUTs ist es sinnvoll, ein TD EPICS ohne externe Referenzen zu verwenden.
Andernfalls können Tests, die ein Timeout erwarten, fehlschlagen, weil das BTF periodisch nach externen Geräten sucht.
Beispiele:
- Das Setzen von Trend-log, 2 enable=FALSE verhindert die automatische Benachrichtigung von BTF.
oder
- Das Löschen des Inhalts der recipient-list in Notification-Class Objekten das Suchen nach den hinterlegten Geräten.
Ebenso könnte unter den Systempflege - Einstellungen in BTF
Verbose true beim Testen von DirectConnect stören, insbesondere wenn das IUT am Anfang des Tests nichts von einem anderen Gerät wissen sollte. In solchen Fällen Verbose false einstellen.
6 Einrichten der bacstackd.ini
Beispiel für die bacstatd.ini eines Nodes:
#############################################################
# bacstac.ini
# BacStack configuration file example for the BACnet Test Framework with Secure Connect
#
# MBS GmbH
# (C) 2010-2021
# www.mbs-software.de
#############################################################
#############################################################
# defines the general settings for this file
#############################################################
[general] # general settings for this file
cnt_data_link = 1 # number of data-link-layers defined in this file
# if you have only one data-link-layer (no OD)
# reduce cnt_data_link to 1
max_msg_req = 100 # message queue between physical layer and
#############################################################
# defines the BACnet SC (TD)
#############################################################
[data_link 1]
pre_shared_secret_log_file =
C:\BTF\Projects\2021_1006209_main\packet_logs\secrets\secrets_btf_node.log
port_id = 1
type = wssc
max_msg_req = 50
net_number = 180
lan_name = 168.152.32.244
port = 47808
mode = regular # regular / primary / failover
virtual_mac_address = d728ae328d70 # if missing last 6 bytes of UUID will be used
###node_uuid = 4fbb6794-9c57-4b6c-88f8-d728ae328d70 --- Erforderlich bei den Auto-Skripten wie
D3, D4
hub_uri = wss://168.152.32.142:47808/
#failover_hub_uri = wss://192.168.16.248:47808/
accepts_connections = 0 # always 1 for any hub mode (primary / failover) --- für DirectConnect
initiates_connections = 0 # if set node will initiate direct connections (but not as a hub) --- für DirectConnect
keep_alive_interval = 90 # 30-300 seconds --- Heartbeat
connect_timeout = 10 # 5-300 seconds --- Wartezeit für ConnectAccept
reconnect_delay = 10 # 2-300 seconds --- Wartezeit für Wiederholung des ConnectRequest
reconnect_retries = 5 # 1-50
activate_ws_ping_pong = 0 # uses websocket ping pong for keep alive checking
allow_unsecured_connections = 0 # do not use ssh encryption
allow_self_signed_certs = 1 # allow self signed certificates
allow_non_strict_hostname_certs = 1 # do not check hostname against host data in certificate
allow_expired_certs = 0 # allow also expired certs
allow_client_server_ssl_v2 = 0 # allow SSL V2
allow_client_server_ssl_v3 = 0 # allow SSL V3
allow_client_server_tls_v1_0 = 0 # allow TLS V1.0
allow_client_server_tls_v1_1 = 0 # allow TLS V1.1
allow_client_server_tls_v1_2 = 0 # allow TLS V1.2
accept_any_server_cert = 0 # we accept any certificate received from server
accept_any_client_cert = 0 # we accept any certificate received from client
server_checks_client_certs = 1 # server checks client certificate on connection
#server_external_visible_uri = wss://168.152.32.2:47808/
cert_revoke_list_file_path = # optional certificate revokation list
server_ca_cert_file_path = C:\BTF\Projects\ProjectName\user_data\certs2\btf_ca-cert.crt
server_cert_file_path = C:\BTF\Projects\ ProjectName \user_data\certs2\btf_btf1-cert.crt
server_pkey_file_path = C:\BTF\Projects\ ProjectName \user_data\certs2\btf_btf1-key.pem
#server_pkey_pass_phrase = # optional pass phrase for private key
client_global_pkey_pass_phrase = # optional global pass phrase for client private key
client_ca_cert_file_path = .\user_data\certs2\btf_ca-cert.crt
client_global_cert_file_path = .\user_data\certs2\btf_btf1-cert.crt
client_global_pkey_file_path = .\user_data\certs2\btf_btf1-key.pem
cnt_vmac_entries = 0 # number of static VMAC => URI bindings
#vmac_addr_0 = 001122334455
#vmac_uri_0 = wss://192.168.16.254:47808/
#vmac_addr_1 = 0123456789AB
#vmac_uri_1 = wss://192.168.16.254:47808/
Für eine Hub Konfiguration sind die folgenden Parameter anzupassen:
mode = primary # regular / primary / failover
server_external_visible_uri = wss://168.152.32.2:47808/
Secure-Connect DirectConnections erweiterte Konfiguration
Um überhaupt direkte Verbindungen zuzulassen: initiate_connections = 1
Um direkte Verbindungen, wenn sie nicht mehr benötigt werden wieder abzubauen, kann man angeben nach welcher Anzahl von Keep-Alives wieder abgebaut wird: direct_conn_idle_count = xxx
Wenn generell direkte Verbindungen erlaubt werden sollen, dann: allow_unconfigured_direct_conn = 1
Ansonsten Anzahl der Einträge für die Konfiguration angeben: cnt_direct_conn_entries = xx
Und spezifizieren wohin bzw. wohin nicht:
direct_conn_entry_0 = <6Byte MAC Adresse z.B AABBCCDDEEFF>,<Flag 0/1 if connection allowed 1 or not 0>,<number of idle counts for disconnection (in seconds)>
Beispiel: direct_conn_entry_0 =AABBCCDDEEFF,0,120
Erläuterungen zu den o.g. Parametern
pre_shared_secret_log_file: bezeichnet den Pfad und Dateinamen der Secrets Logdatei, die BTF erzeugt und benötigt wird, um in Wireshark den Netzverkehr unverschlüsselt angezeigt zu bekommen. Der Pfad zu dieser Datei muss existieren bzw. neu angelegt werden. Der Projektpfad (im Beispiel ProjectName) muss dazu u.U. angepasst werden.
net_number, lan_name und port: entsprechend anpassen
mode: Modus von BTF (Node, Hub, Failover)
virtual_mac_address: VMAC von BTF
node_uuid: ist auskommentiert. BTF benutzt die im TD EPICS genannte device_uuid
hub_uri und failover_hub_uri (falls erforderlich): hier die Adressen des Hubs und des FailoverHubs und hinterlegen.
server_external_visible_uri: Adresse des TD, wenn es als Hub oder FailoverHub eingerichtet. Für BTF als Node kann die Zeile auskommentiert werden.
server_ca_cert_file_path, server_cert_file_path, server_pkey_file_path sowie client_ca_cert_file_path, client_global_cert_file_path, client_global_pkey_file_path: Pfade zu den Zertifikatsdateien. Die Pfade und Dateien müssen existieren und passend hinterlegt sein. Wie im Beispiel oben sind relative und absolute Pfade möglich. Die Client- und Server-Zertifikatsdateien dürfen wie im Beispiel identisch sein.
7 BACnet/SC mit Wireshark extern (außerhalb von BTF)
Da die Kommunikation nach dem TLS-Handshake ("Server Hello" und "Client Hello") bei SecureConnect grundsätzlich verschlüsselt ist, benötigt man ein zusätzliches unverschlüsseltes Log-File (Secrets Logdatei), welches sowohl von BTF wie auch von den verschiedenen Node-Hilfsskripten zur Verfügung gestellt wird. Beim Einbinden in Wireshark werden die Paketdaten dann "live" ohne spürbare Verzögerung entschlüsselt dargestellt.
Will man neben dem automatischen BTF-Logging den Test in einem externen Wireshark verfolgen, so können nur diejenigen Pakete dekodiert werden, deren Secret Logdatei im Wireshark hinterlegt ist. Es ist mitunter sinnvoll mehrere Wireshark Instanzen mit unterschiedlichen eingebundenen Secrets Logdateien laufen zu lassen, um die gesamte Kommunikation verfolgen zu können.
BTF erzeugt nach einem Test aus allen Secrets Logdateien eine so genannte "Merged" Logdatei. Diese fasst die unterschiedlichen Secrets-Logdateien in einer zusammen.
HINWEIS: Das Decodieren funktioniert nur dann, wenn der jeweilige SC-Handshake mit aufgezeichnet wird. Es ist daher immer darauf zu achten, dass zuerst der Test gestartet wird und danach erst die Skripte für die weiteren Nodes (D2, D3, D4, usw.).
Einbinden der Secret Logdatei in Wireshark
Wireshark öffnen und unter Bearbeiten / Einstellungen / Protokolls / TLS - (Pre)-Master-Secret log filename die gewünschte Secrets Logdatei einladen. Wird z.B. secrets_d2.log ausgewählt, dann zeigt Wireshark den Netzwerkverkehr für das Gerät D2 unverschlüsselt. Als Filter ist in Wireshark TLS nützlich, um mehr Übersicht bei der Kommunikation zu erhalten. Gibt es bereits Probleme beim Zustandekommen des WebSockets, kann mit dem Filter bacnet or tcp or bvlc or lts gearbeitet werden. Ein TCP Stream (die benutzten Ports sind jeweils identisch) kann mit Rechtsklick - Folgen - TCP Stream angesehen werden.
8 Einrichten der Auto-Skripte
Bei vielen Tests werden weitere Nodes (Clients) benötigt, die entweder Requests empfangen oder senden. Diese "weiteren BACnet/SC Geräte" werden mit Hilfe von Auto-Skripten zur Verfügung gestellt und über das jeweilige zugehörige AUTO.py-Skript gestartet. Die Auto-Skripte bestehen aus z.B. einer Datei D2_AUTO.py, die manuell gestartet und nicht weiter angepasst werden muss.
Die Auto-Skripte liegen in folgendem Pfad:
C:\Program Files (x86)\MBS\BTF\Documentation\SampleScripts\SC_Tests\auto_scripts
Angepasst werden müssen die folgende Dateien:
d2_auto_head.py muss angepasst werden und verweist auf eine Datei D2.ini. Dieser Verweis, d.h. Pfad und Datei, muss existieren und angepasst werden.
Die Datei D2.ini ist wiederum eine bacstackd.ini für das "Gerät" D2. Diese Datei muss ebenfalls angepasst werden, und zwar wie im Abschnitt oben genannt. Der mode, die eigene vmac und uuid werden nicht geändert.
Die not_connected.ini Dateien müssen bis auf einen Punkt identisch sein mit den normalen ini-Dateien, außer in den Parametern hub_uri (bzw. failover_hub_uri). Hier soll die Portnummer auf eine ungültige Nummer gesetzt werden, z.B 47813.
HINWEIS: Diese not_connected.ini Dateien müssen auch dann korrekt konfiguriert sein, wenn diese im aktuellen Test nicht genutzt werden. Auch diese Geräte/Skripte erzeugen eine eigene Wireshark Secrets-Logdatei. Wichtig ist eineindeutiger Dateiname für die Secrets-Datei.
Beispiel für eine D2.ini: pre_shared_secret_log_file = C:\BTF\Projects\ProjectBane\packet_logs\secrets\secrets_d2.log
Die ini-Dateien zu den Autoscripten z.B. D3-Node müssen für verschiedene Tests angepasst werden bezüglich der HUB-Verbindung: BTF oder IUT.
9 Einrichten von Direct Connections
Bei dieser Funktion kann ein Node zu einem anderen Node ohne über den Umweg eines Hubs kommunizieren; der Hub wird aber für das Zustandekommen der DirectConnection benötigt. In der bacstackd.ini müssen die beiden Einträge:
- accepts_connections
- initiates_connections
passend gesetzt sein.
Beide dürfen auch auf 1 gesetzt sein. Dies sind die beiden generellen Schalter für DirectConnections des Geräts. Weiterhin muss auch server_external_visible_uri auf die eigene Adresse gesetzt sein. Ansonsten wird eine AddressResolution Anfrage von BTF nicht beantwortet.
Wenn BTF DirectConnections initiieren soll, dann muss in der bacstackd.ini gesetzt sein:
- allow_unconfigured_direct_conn = 1
BTF initiiert DirectConnections, wenn es irgendeine Nachricht zu einem anderen Node verschicken soll. Das können beliebig viele sein. Dieser Parameter ist unabhängig von cnt_direct_conn_entries:
- direct_conn_idle_count = xxx
Wenn der Parameter nicht vorhanden oder = 0 ist, dann bleiben die Verbindungen bestehen. Wenn er vorhanden ist, dann wird die Verbindung nach xxx Sekunden ohne Netzwerktraffic beendet.
- cnt_direct_conn_entries = xxx
Dieser Eintrag wird nur benötigt, wenn es den/die Parameter direct_conn_entry_x gibt. Der Parameter gibt die Anzahl der mit direct_conn_entry_x konfigurierten DirectConnections an, bzw. sollte damit identisch sein. Ist xx kleiner als die Anzahl der direct_conn_entry_x, dann werden nur die ersten xx Einträge berücksichtigt.
- direct_conn_entry_0 = d123ae328de2,1,20
Format: <VMAC des SC Nodes, zu dem eine DirectConnection aufgebaut werden soll>,<Flag 0/1 ob Verbindung erlaubt 1 oder nicht 0>,<Anzahl direct_conn_idle_count zum Verbindungsabbau, wenn kein Traffic vorliegt>
Ist der Node, zu denen eine DirectConnection aufgebaut werden soll. Weitere Nodes können mit direct_conn_entry_1, direct_conn_entry_2 usw. zugefügt werden.
Die folgenden Parameter können eine Initiierung von DirectConnections unterbinden:
- allow_unconfigured_direct_conn = 0
- cnt_direct_conn_entries = 0