PfSense SSH login - decoders and rules

14 views
Skip to first unread message

Giuseppe Ruberto

unread,
Dec 16, 2025, 2:37:17 PM (yesterday) Dec 16
to Wazuh | Mailing List
Hello everyone,
I need to analyse the logs from my virtual machine with pfSense. Specifically, I am trying to capture and analyse the logs associated with SSH access.
I have created a decoder and some customised rules:

<!-- ====================== -->
<!-- Decoders per PfSense   -->
<!-- Accesso su server      -->
<!-- ====================== -->

<decoder name="PfSense-access">
<!--  <program_name>openvpn_server1</program_name>-->
  <prematch type="pcre2">\sVPN-pfSense\.aaa\.local\.lan\ssshd</prematch>
</decoder>

<decoder name="pfSense-ssh-accepted">
  <parent>PfSense-access</parent>
  <prematch type="pcre2">Accepted keyboard-interactive/pam</prematch>
  <regex type="pcre2" offset="after_prematch">for (\S+) from (\d+\.\d+\.\d+\.\d+) port (\d+) .*</regex>
  <order>srcuser,srcip,srcport</order>
</decoder>


<!-- SSH: sessione accettata -->
<!--<decoder name="pfSense-ssh-accepted">
  <parent>PfSense-access</parent>
  <prematch type="pcre2">Accepted keyboard-interactive/pam</prematch>
  <regex type="pcre2" offset="after_prematch"> for (\w+) from (\d+\.\d+\.\d+\.\d+) port (\d+) (\w+)</regex>
  <order>srcuser,srcip,srcport,extra_data</order>
</decoder>-->

<!-- SSH: tentativo fallito con utente errato- failed authentication -->
<decoder name="pfSense-ssh-failed-authentication">
  <parent>PfSense-access</parent>
  <prematch>error: PAM: Authentication error for illegal</prematch>
  <regex type="pcre2" offset="after_prematch"> user (\w+) from (\d+\.\d+\.\d+\.\d+)</regex>
  <order>srcuser,srcip</order>
</decoder>

<!-- SSH: tentativo fallito con utente esistente- failed authentication -->
<decoder name="pfSense-ssh-failed-authentication-with-existing-user">
  <parent>PfSense-access</parent>
  <prematch type="pcre2">error: PAM: Authentication error for</prematch>
  <regex type="pcre2" offset="after_prematch"> (\w+) from (\d+\.\d+\.\d+\.\d+)</regex>
  <order>srcuser,srcip</order>
</decoder>

<!-- SSH: tentativo fallito proxmox- failed authentication -->
<decoder name="pfSense-ssh-failed-authentication-proxmox">
  <parent>PfSense-access</parent>
  <prematch>could not authenticate for login</prematch>
  <regex type="pcre2" offset="after_prematch">user (\S+) could not authenticate for login</regex>
  <order>srcuser</order>
</decoder>


<decoder name="PfSense-ttyv-access">
  <prematch type="pcre2">VPN-pfSense.aziendapanico.local.lan login</prematch>
</decoder>


<!-- SSH: tentativo accettato proxmox- accepted authentication -->
<decoder name="pfSense-ssh-accepted-auhentication-proxmox">
  <parent>PfSense-ttyv-access</parent>
  <prematch type="pcre2">login\s+on\s+ttyv\d+as</prematch>
  <regex type="pcre2" offset="after_prematch">login on ttyv\d+ as (\w+)</regex>
  <order>srcuser</order>
</decoder>

E le regole:
<group name="pfsense,access,ssh,authentication,soc">

  <!-- ============================ -->
  <!--        ACCESSI OK            -->
  <!-- ============================ -->

  <!-- 100080 - SSH LOGIN OK -->
  <rule id="100080" level="5">
    <decoded_as>pfSense-ssh-accepted</decoded_as>
    <description>pfSense SSH login riuscito: utente $(srcuser) da $(srcip) porta $(srcport)</description>
    <group>authentication_success,ssh,pfsense</group>
  </rule>

  <!-- 100081 - LOGIN LOCALE TTY OK -->
  <rule id="100081" level="6">
    <decoded_as>pfSense-ssh-accepted-auhentication-proxmox</decoded_as>
    <description>pfSense login TTY locale: utente $(srcuser)</description>
    <group>authentication_success,local,tty,success,pfsense</group>
  </rule>

  <!-- ============================ -->
  <!--       LOGIN FALLITI          -->
  <!-- (ALLINEATI A SID 2501)       -->
  <!-- ============================ -->

  <!-- 100082 - LOGIN FALLITO USER ESISTENTE -->
  <rule id="100082" level="8">
    <decoded_as>pfSense-ssh-failed-authentication-with-existing-user</decoded_as>
    <if_sid>2501</if_sid>
    <description>pfSense SSH login FALLITO (utente valido): $(srcuser) da $(srcip)</description>
    <group>authentication_failed,ssh,pfsense,bruteforce</group>
  </rule>

  <!-- 100083 - LOGIN FALLITO USER ILLEGALE -->
  <rule id="100083" level="7">
    decoded_as>pfSense-ssh-failed-authentication</decoded_as>
    <if_sid>2501</if_sid>
    <description>pfSense SSH login FALLITO (utente illegale): $(srcuser) da $(srcip)</description>
    <group>authentication_failed,ssh,pfsense,recon</group>
  </rule>

  <!-- 100084 - LOGIN FALLITO PROXMOX -->
  <rule id="100084" level="8">
    <decoded_as>pfSense-ssh-failed-authentication-proxmox</decoded_as>
    <if_sid>2501</if_sid>
    <description>pfSense SSH login FALLITO Proxmox: utente $(srcuser)</description>
    <group>authentication_failed,proxmox,ssh,pfsense</group>
  </rule>

  <!-- ============================ -->
  <!--       BRUTE FORCE            -->
  <!-- ============================ -->

  <!-- 100085 - BRUTE FORCE SSH SU UTENTE -->
  <rule id="100085" level="12" frequency="5" timeframe="60">
    <if_matched_sid>100082</if_matched_sid>
    <same_srcip/>
    <description>BRUTE FORCE SSH su pfSense da $(srcip)</description>
    <group>bruteforce,ssh,pfsense,attack,soc</group>
  </rule>

  <!-- 100086 - BRUTE FORCE SU PIÙ UTENTI -->
  <rule id="100086" level="13" frequency="8" timeframe="90">
    <if_matched_sid>100083</if_matched_sid>
    <same_srcip/>
    <description>ENUMERAZIONE UTENTI / BRUTE FORCE pfSense da $(srcip)</description>
    <group>bruteforce,enum,ssh,pfsense,attack,soc</group>
  </rule>

  <!-- ============================ -->
  <!--    COMPROMISSIONE SOSPETTA  -->
  <!-- ============================ -->

  <!-- 100087 - LOGIN RIUSCITO DOPO BRUTE FORCE -->
  <rule id="100087" level="15">
    <if_matched_sid>100080</if_matched_sid>
    <if_matched_sid>100085</if_matched_sid>
    <same_srcip/>
    <description>POSSIBILE COMPROMISSIONE: login riuscito dopo brute force da $(srcip)</description>
    <group>compromise,ssh,pfsense,critical,soc</group>
  </rule>

  <!-- ============================ -->
  <!--    ACCESSI SOSPETTI          -->
  <!-- ============================ -->

  <!-- 100088 - LOGIN ROOT -->
  <rule id="100088" level="10">
    <if_sid>100080</if_sid>
    <user>root</user>
    <description>pfSense SSH login ROOT da $(srcip)</description>
    <group>privilege,root,ssh,pfsense,soc</group>
  </rule>

</group>

I'm having trouble getting the rules to work, because when I try to analyse some logs using the test, such as:

2025 Dec 16 19:14:18 (VPN-pfSense.aaa.local.lan) any->/var/log/system.log <38>1 2025-12-16T19:14:18.160543+01:00 VPN-pfSense.aaa.local.lan sshd 43682 - - Invalid user test from 10.1.1.111 port 58693

2025 Dec 16 19:19:36 (VPN-pfSense.aaa.local.lan) any->/var/log/system.log <38>1 2025-12-16T19:19:36.307956+01:00 VPN-pfSense.aaa.local.lan sshd 2270 - - Accepted keyboard-interactive/pam for test from 10.1.1.111 port 58959 ssh2

I get this:
**Messages: WARNING: (7003): '9c78205f' token expires INFO: (7202): Session initialized with token 'cc07d1ce' **Phase 1: Completed pre-decoding. full event: '2025 Dec 16 19:14:18 (VPN-pfSense.aaa.local.lan) any->/var/log/system.log <38>1 2025-12-16T19:14:18.160543+01:00 VPN-pfSense.aaa.local.lan sshd 43682 - - Invalid user test from 10.1.1.111 port 58693' timestamp: '2025 Dec 16 19:14:18' **Phase 2: Completed decoding. name: 'pfsense-ssh' parent: 'pfsense-ssh' srcip: '10.1.1.111' srcport: '58693' srcuser: 'test' What could be the problem? I welcome any advice.
Thank you for your help.

Olamilekan Abdullateef Ajani

unread,
Dec 16, 2025, 3:41:44 PM (24 hours ago) Dec 16
to Wazuh | Mailing List
Hello Giuseppe,

I reviewed your decoder and rule, I find the first log you shared for the invalid user missing from the decoders, so I created one for you, please find it below. The other log matched.

<decoder name="pfsense-ssh-invalid-user">
  <parent>PfSense-access</parent>
  <prematch>sshd\s+\d+\s+-\s+-\s+Invalid user</prematch>
  <regex type="pcre2">Invalid user\s+(\S+)\s+from\s+(\d{1,3}(?:\.\d{1,3}){3})\s+port\s+(\d+)</regex>
  <order>srcuser,srcip,srcport</order>
</decoder>


For the rule, I could not see a match again with the logs you shared, but I created a sample.
For: 2025 Dec 16 19:14:18 (VPN-pfSense.aaa.local.lan) any->/var/log/system.log <38>1 2025-12-16T19:14:18.160543+01:00 VPN-pfSense.aaa.local.lan sshd 43682 - - Invalid user test from 10.1.1.111 port 58693
and: 2025 Dec 16 19:19:36 (VPN-pfSense.aaa.local.lan) any->/var/log/system.log <38>1 2025-12-16T19:19:36.307956+01:00 VPN-pfSense.aaa.local.lan sshd 2270 - - Accepted keyboard-interactive/pam for test from 10.1.1.111 port 58959 ssh2

<group name="pfsense,access,ssh,authentication,soc">


  <!-- 100080 - SSH LOGIN OK -->
  <rule id="100080" level="5">
    <decoded_as>PfSense-access</decoded_as>
    <match>Accepted keyboard-interactive/pam</match>
    <description>pfSense keyboard-interactive/pam for $(srcuser) da $(srcip) porta $(srcport)</description>
    <group>authentication_success,ssh,pfsense</group>
  </rule>

  <rule id="100081" level="9">
    <decoded_as>PfSense-access</decoded_as>
    <match>Invalid user</match>
    <description> invalid $(srcuser) da $(srcip) porta $(srcport)</description>
    <group>authentication_success,ssh,pfsense</group>
  </rule>

</group>

If you noticed from the rules above, they reference the same parent decoder but are matching different logs because of the <match> tag I introduced. This is to ensure the rule is associated with the right logs.
Depending on what you are trying to achieve, you can reference anything you want to be as a triggering point in your log; it could be the source IP or a specific tag. You can find more configurable references in the documentation below:

That being said, I would advise you to keep your base rules separated from the correlation rule to keep the ruleset file cleaner for proper management. Once you sought out matching the right logs to each rule, then you can look at correlation. One step at a time.

I hope the above provides the right guideline, please let me know if you require further assistance on this.
pfsense-ssh.png
Reply all
Reply to author
Forward
0 new messages