diff --git a/integrations/unifi_controller/README.md b/integrations/unifi_controller/README.md new file mode 100644 index 0000000..52825b2 --- /dev/null +++ b/integrations/unifi_controller/README.md @@ -0,0 +1,87 @@ +### UniFi Controller–Wazuh Integration + +#### **Table of Contents** + + * [Introduction](#introduction) + * [Prerequisites](#prerequisites) + * [Initial UniFi Controller Configuration](#initial-unifi-controller-configuration) + * [Installing and Configuring the Integration](#installing-and-configuring-the-integration) + * [Integration Testing](#integration-testing) + +### Introduction + +This guide outlines the steps to integrate UniFi Network Application (controller) CEF syslog events with Wazuh. This integration relies on parsing CEF activity logs (`CEF:0|Ubiquiti|UniFi Network|...`) to track WiFi client connect, disconnect, and roam events, as well as administrator access to the UniFi Network UI/API. + +This ruleset is separate from the UniFi AP syslog ruleset (the `unifi_ap` integration). + +### Prerequisites + +Before starting, ensure the following: + + * A functioning UniFi Network Application generating CEF activity logs over syslog. + * A Wazuh Manager (or a designated Wazuh Agent) installed and configured to receive those syslog events. + +### Initial UniFi Controller Configuration + +To forward UniFi controller logs to Wazuh, configure the UniFi Network Application to send activity notifications/logs in CEF format to a syslog destination (the Wazuh manager or an agent that relays them). + +Ensure log collection is active so Wazuh can ingest the raw CEF lines and begin parsing fields like `unifi_event_id`, `unifi_client_mac`, `unifi_wifi_name`, `unifi_ap_name`, `srcip`, and `srcuser`. + +### Installing and Configuring the Integration + +#### Copy the Custom Decoders + +The custom decoders instruct Wazuh on how to parse the UniFi Network Application CEF format. Copy the decoders file to the Wazuh Manager's custom decoders directory: + +```bash +cp integrations/unifi_controller/unifi_controller_decoder.xml /var/ossec/etc/decoders/ +``` + +Or navigate to **Server Management** --\> **Decoders** --\> **Add new decoders file** --\> paste the content, save the file and reload the cluster. + +#### Copy the Custom Rules + +The custom rules map the decoded fields to specific connectivity and auditing alerts, such as alerting when a WiFi client connects, disconnects, or roams, or when an administrator accesses UniFi Network. Copy the rules file to the Wazuh Manager's custom rules directory: + +```bash +cp integrations/unifi_controller/unifi_controller_rules.xml /var/ossec/etc/rules/ +``` + +Or navigate to **Server Management** --\> **Rules** --\> **Add new rules file** --\> paste the content, save the file and reload the cluster. + +#### Set File Permissions + +Ensure that the Wazuh user has the appropriate permissions to read the newly added files: + +```bash +chown wazuh:wazuh /var/ossec/etc/decoders/unifi_controller_decoder.xml +chown wazuh:wazuh /var/ossec/etc/rules/unifi_controller_rules.xml +chmod 660 /var/ossec/etc/decoders/unifi_controller_decoder.xml +chmod 660 /var/ossec/etc/rules/unifi_controller_rules.xml +``` + +#### Restart the Wazuh Manager (If using CLI) + +If you copied the files directly via the command line, apply the new decoders and rules by restarting the Wazuh Manager service: + +```bash +systemctl restart wazuh-manager +``` + +### Integration Testing + +#### Test Using Wazuh-Logtest + +You can verify that the decoders and rules are working correctly by using the `wazuh-logtest` tool with a log from your `log_samples.txt`: + +1. Navigate to **Server Management** --\> **Ruleset Test** on the Dashboard. +2. Paste a raw CEF log from UniFi into the prompt (e.g., `CEF:0|Ubiquiti|UniFi Network|10.4.57|400|WiFi Client Connected|1|UNIFIcategory=Client Devices UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIconnectedToDeviceName=UNIAP-01 UNIFIclientAlias=PHONE-01 UNIFIclientIp=10.0.1.50 UNIFIclientMac=aa:bb:cc:11:11:11 UNIFIwifiName=CORP-WIFI UNIFIauthMethod=wpapsk UNIFIWiFiRssi=-60 ...`). +3. Verify that Phase 2 correctly identifies the `unifi-controller` decoder (and child field extractions) and Phase 3 triggers the appropriate rule (e.g., Rule `111551` for a client connected, `111552` for disconnected, `111553` for roamed, or `111554` for Network Accessed). + +#### Verify in Wazuh Dashboard + +1. Open the Wazuh Dashboard. +2. Navigate to the **Discover** tab. +3. Add a filter: `Field` `rule.groups`, `Operator` `is`, `Value` `unifi_controller`. +4. Alternatively, filter by `Field` `decoder.name`, `Operator` `is`, `Value` `unifi-controller`. +5. Save the filter or view the dashboard to monitor ingested UniFi controller events in real-time. diff --git a/integrations/unifi_controller/log_samples.txt b/integrations/unifi_controller/log_samples.txt new file mode 100644 index 0000000..817e8f9 --- /dev/null +++ b/integrations/unifi_controller/log_samples.txt @@ -0,0 +1,5 @@ +2026-07-17T10:51:14+02:00 unifi.example.local Jul 17 10:51:14 CONTROLLER CEF:0|Ubiquiti|UniFi Network|10.4.57|400|WiFi Client Connected|1|UNIFIcategory=Client Devices UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIconnectedToDeviceName=UNIAP-01 UNIFIconnectedToDeviceIp=10.0.0.10 UNIFIconnectedToDeviceMac=aa:bb:cc:00:00:01 UNIFIconnectedToDeviceModel=U6-LR UNIFIconnectedToDeviceVersion=6.7.54 UNIFIclientAlias=PHONE-01 UNIFIclientHostname=phone-01 UNIFIclientIp=10.0.1.50 UNIFIclientMac=aa:bb:cc:11:11:11 UNIFIwifiChannel=52 UNIFIwifiChannelWidth=40 UNIFIwifiName=CORP-WIFI UNIFIwifiBand=na UNIFIauthMethod=wpapsk UNIFIWiFiRssi=-60 UNIFInetworkName=USERS UNIFInetworkSubnet=10.0.1.0/24 UNIFInetworkVlan=3 UNIFIutcTime=2026-07-17T08:51:14.660Z msg=PHONE-01 connected to CORP-WIFI on UNIAP-01. Connection Info: Ch. 52 (5 GHz, 40 MHz), -60 dBm. IP: 10.0.1.50 +2026-07-17T10:50:35+02:00 unifi.example.local Jul 17 10:50:35 CONTROLLER CEF:0|Ubiquiti|UniFi Network|10.4.57|401|WiFi Client Disconnected|2|UNIFIcategory=Client Devices UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIlastConnectedToDeviceName=UNIAP-01 UNIFIlastConnectedToDeviceIp=10.0.0.10 UNIFIlastConnectedToDeviceMac=aa:bb:cc:00:00:01 UNIFIlastConnectedToDeviceModel=U6-LR UNIFIlastConnectedToDeviceVersion=6.7.54 UNIFIclientAlias=PHONE-01 UNIFIclientHostname=phone-01 UNIFIclientIp=10.0.1.50 UNIFIclientMac=aa:bb:cc:11:11:11 UNIFIwifiChannel=6 UNIFIwifiChannelWidth=20 UNIFIwifiName=CORP-WIFI UNIFIwifiBand=ng UNIFIwifiAirtimeUtilization=10 UNIFIwifiInterference=10 UNIFIlastConnectedToWiFiRssi=-67 UNIFIduration=31m 59s UNIFIusageDown=16,52 KB UNIFIusageUp=18,08 KB UNIFInetworkName=USERS UNIFInetworkSubnet=10.0.1.0/24 UNIFInetworkVlan=3 UNIFIutcTime=2026-07-17T08:50:35.355Z msg=PHONE-01 disconnected from CORP-WIFI. Time Connected: 31m 59s. Data Used: 18,08 KB (up) / 16,52 KB (down). Last Connected To: UNIAP-01 at -67 dBm. +2026-07-17T10:40:42+02:00 unifi.example.local Jul 17 10:40:42 CONTROLLER CEF:0|Ubiquiti|UniFi Network|10.4.57|402|WiFi Client Roamed|1|UNIFIcategory=Client Devices UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIconnectedToDeviceName=UNIAP-02 UNIFIconnectedToDeviceIp=10.0.0.11 UNIFIconnectedToDeviceMac=aa:bb:cc:00:00:02 UNIFIconnectedToDeviceModel=U6-LR UNIFIconnectedToDeviceVersion=6.7.54 UNIFIlastConnectedToDeviceName=UNIAP-01 UNIFIlastConnectedToDeviceIp=10.0.0.10 UNIFIlastConnectedToDeviceMac=aa:bb:cc:00:00:01 UNIFIlastConnectedToDeviceModel=U6-LR UNIFIlastConnectedToDeviceVersion=6.7.54 UNIFIclientAlias=LAPTOP-01 aa:11 UNIFIclientHostname=LAPTOP-01 UNIFIclientIp=10.0.1.49 UNIFIclientMac=aa:bb:cc:22:22:22 UNIFIwifiChannel=36 UNIFIwifiChannelWidth=40 UNIFIwifiName=CORP-WIFI UNIFIwifiBand=na UNIFIWiFiRssi=-72 UNIFIlastConnectedToWiFiChannel=44 UNIFIlastConnectedToWiFiChannelWidth=40 UNIFIlastConnectedToWiFiBand=na UNIFIlastConnectedToWiFiRssi=-76 UNIFIutcTime=2026-07-17T08:40:42.057Z msg=LAPTOP-01 aa:11 roamed from UNIAP-01 to UNIAP-02. Connection Info: Ch. 36 (5 GHz, 40 MHz), -72 dBm. Roaming Decision: -76 dBm to -72 dBm. +2026-07-17T10:14:14+02:00 unifi.example.local Jul 17 10:14:14 CONTROLLER CEF:0|Ubiquiti|UniFi Network|10.4.57|544|Network Accessed|4|UNIFIcategory=Audit UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIaccessMethod=web UNIFIadmin=admin src=10.0.1.38 UNIFIutcTime=2026-07-17T08:14:14.329Z msg=admin accessed UniFi Network using the web. Source IP: 10.0.1.38 +2026-07-17T10:51:20+02:00 unifi.example.local Jul 17 10:51:20 CONTROLLER CEF:0|Ubiquiti|UniFi Network|10.4.57|400|WiFi Client Connected|1|UNIFIcategory=Client Devices UNIFIsite=Site A UNIFIhost=CONTROLLER UNIFIconnectedToDeviceName=UNIAP-01 UNIFIconnectedToDeviceIp=10.0.0.10 UNIFIconnectedToDeviceMac=aa:bb:cc:00:00:01 UNIFIconnectedToDeviceModel=U6-LR UNIFIconnectedToDeviceVersion=6.7.54 UNIFIclientAlias=TV-01 UNIFIclientIp=10.0.1.206 UNIFIclientMac=aa:bb:cc:33:33:33 UNIFIwifiChannel=44 UNIFIwifiChannelWidth=40 UNIFIwifiName=CORP-WIFI UNIFIwifiBand=na UNIFIauthMethod=wpapsk UNIFIWiFiRssi=-51 UNIFInetworkName=USERS UNIFInetworkSubnet=10.0.1.0/24 UNIFInetworkVlan=3 UNIFIutcTime=2026-07-17T08:51:20.000Z msg=TV-01 connected to CORP-WIFI on UNIAP-01. Connection Info: Ch. 44 (5 GHz, 40 MHz), -51 dBm. IP: 10.0.1.206 diff --git a/integrations/unifi_controller/unifi_controller_decoder.xml b/integrations/unifi_controller/unifi_controller_decoder.xml new file mode 100644 index 0000000..021033d --- /dev/null +++ b/integrations/unifi_controller/unifi_controller_decoder.xml @@ -0,0 +1,194 @@ + + + CEF:0\|Ubiquiti\|UniFi Network\| + + + + unifi-controller + Ubiquiti\|UniFi Network\|(\S+)\|(\d+)\|(\.+)\|(\d+)\|UNIFI + unifi_version,unifi_event_id,unifi_event_name,unifi_severity + + + + unifi-controller + UNIFIcategory=(\.+) UNIFI\w+= + unifi_category + + + unifi-controller + UNIFIsite=(\.+) UNIFI\w+= + unifi_site + + + unifi-controller + UNIFIhost=(\S+) + unifi_host + + + unifi-controller + UNIFIclientAlias=(\.+) UNIFI\w+= + unifi_client_alias + + + unifi-controller + UNIFIclientHostname=(\S+) + unifi_client_hostname + + + unifi-controller + UNIFIclientIp=(\d+.\d+.\d+.\d+) + srcip + + + unifi-controller + UNIFIclientMac=(\w+:\w+:\w+:\w+:\w+:\w+) + unifi_client_mac + + + unifi-controller + UNIFIwifiName=(\S+) + unifi_wifi_name + + + unifi-controller + UNIFIwifiChannel=(\d+) + unifi_wifi_channel + + + unifi-controller + UNIFIwifiChannelWidth=(\d+) + unifi_wifi_channel_width + + + unifi-controller + UNIFIwifiBand=(\S+) + unifi_wifi_band + + + unifi-controller + UNIFIWiFiRssi=(\S+) + unifi_wifi_rssi + + + unifi-controller + UNIFIlastConnectedToWiFiRssi=(\S+) + unifi_last_connected_wifi_rssi + + + unifi-controller + UNIFIauthMethod=(\S+) + unifi_auth_method + + + unifi-controller + UNIFInetworkName=(\S+) + unifi_network_name + + + unifi-controller + UNIFInetworkSubnet=(\S+) + unifi_network_subnet + + + unifi-controller + UNIFInetworkVlan=(\d+) + unifi_network_vlan + + + unifi-controller + UNIFIconnectedToDeviceName=(\S+) + unifi_ap_name + + + unifi-controller + UNIFIconnectedToDeviceIp=(\d+.\d+.\d+.\d+) + unifi_ap_ip + + + unifi-controller + UNIFIconnectedToDeviceMac=(\w+:\w+:\w+:\w+:\w+:\w+) + unifi_ap_mac + + + unifi-controller + UNIFIconnectedToDeviceModel=(\S+) + unifi_ap_model + + + unifi-controller + UNIFIlastConnectedToDeviceName=(\S+) + unifi_last_ap_name + + + unifi-controller + UNIFIlastConnectedToDeviceIp=(\d+.\d+.\d+.\d+) + unifi_last_ap_ip + + + unifi-controller + UNIFIlastConnectedToDeviceMac=(\w+:\w+:\w+:\w+:\w+:\w+) + unifi_last_ap_mac + + + unifi-controller + UNIFIduration=(\.+) UNIFI\w+= + unifi_duration + + + unifi-controller + UNIFIusageDown=(\.+) UNIFI\w+= + unifi_usage_down + + + unifi-controller + UNIFIusageUp=(\.+) UNIFI\w+= + unifi_usage_up + + + unifi-controller + UNIFIwifiAirtimeUtilization=(\d+) + unifi_airtime_utilization + + + unifi-controller + UNIFIwifiInterference=(\d+) + unifi_wifi_interference + + + + unifi-controller + UNIFIaccessMethod=(\S+) + unifi_access_method + + + unifi-controller + UNIFIadmin=(\S+) + srcuser + + + unifi-controller + src=(\d+.\d+.\d+.\d+) + srcip + + + unifi-controller + UNIFIutcTime=(\S+) + unifi_utc_time + + + unifi-controller + msg=(\.+)$ + unifi_msg + diff --git a/integrations/unifi_controller/unifi_controller_rules.xml b/integrations/unifi_controller/unifi_controller_rules.xml new file mode 100644 index 0000000..ac510bd --- /dev/null +++ b/integrations/unifi_controller/unifi_controller_rules.xml @@ -0,0 +1,45 @@ + + + + unifi-controller + UniFi Controller: generic CEF event. + unifi_controller_debug, + + + + 111550 + ^400$ + UniFi Controller: WiFi client $(unifi_client_alias) ($(unifi_client_mac)) connected to $(unifi_wifi_name) on $(unifi_ap_name) (rssi=$(unifi_wifi_rssi), auth=$(unifi_auth_method), ip=$(srcip)). + unifi_controller_client,authentication_success, + + + + 111550 + ^401$ + UniFi Controller: WiFi client $(unifi_client_alias) ($(unifi_client_mac)) disconnected from $(unifi_wifi_name) (duration=$(unifi_duration), last AP=$(unifi_last_ap_name), rssi=$(unifi_wifi_rssi)). + unifi_controller_client, + + + + 111550 + ^402$ + UniFi Controller: WiFi client $(unifi_client_alias) ($(unifi_client_mac)) roamed from $(unifi_last_ap_name) to $(unifi_ap_name) on $(unifi_wifi_name) (rssi=$(unifi_wifi_rssi)). + unifi_controller_client,unifi_controller_roaming, + + + + 111550 + ^544$ + UniFi Controller: admin $(srcuser) accessed UniFi Network via $(unifi_access_method) from $(srcip) (site=$(unifi_site)). + unifi_controller_audit,authentication_success, + + + + + 111552 + unifi_client_mac + UniFi Controller: client $(unifi_client_mac) ($(unifi_client_alias)) disconnected repeatedly - possible client flapping or RF/connectivity issue. + unifi_controller_client, + + +