CyberSecurity Project: Transparent Filtering Bridge (+ Extras) 11.0

I wasn't planning on doing a major update to this series for a while, partly due to being busy with working on CCNA certifications. But also due to the general hardware price nightmare of 2026 and OPNSense's general jankiness with its API in version 26 making the automation part of project a bit more suspect.

But when you've got major problems, it's time for a major update.

Table of Contents

The Context

For the first half of the year, things were stable with the older version of the setup file I had created for the wpa_supplicant, which controls the WiFi interface I use to manage OPNSense on the miniPC it runs off of.

OPNSense versions 26.1+ provided no real issues aside from the need to reapply the script whenever an update occurred, because the update would revert the wpa_supplicant file back to its old state.

OPNSense announced a planned upgrade to version 26.7 on July 15, 2026, at which time support for 26.1+ would cease. I waited a few days, checked the r/OPNSense thread on the update, saw that N100 miniPCs like mine had few issues, and proceeded with the update.

The First Problem

After the minor hassle of updating to 26.1.11 to get to update to 26.7, the first real indication of a problem was when I tried to get into the shell to look at wpa_supplicant, and this happened:

OPNSense 26.7 in the midst of a crash.

The above screenshot is a small segment of the fast moving stream of text that would fill the screen before the miniPC crashed.

What was interesting about this crash was OPNSense would boot properly, allow me to enter the shell, and then crash after about 1-2 minutes from boot completion.

I explored several avenues to dealing with this, including reinstalling OPNSense. I couldn't get the installer to work, so I was left with using an option I had never used before: Reset to Default Configuration.

Since I had a backup of the configuration made before the update, I saw little risk in using this option. And it worked.

The Second Problem

The fact that resetting to default configuration solved the problem at all indicated that it was at least partially due to configuration settings, which promised headaches in the future.

However, the new problem was that I would have to figure what to do with the wpa_supplicant, because resetting to default hadn't enabled it to connect to my home network.

Unfortunately, I managed to botch taking a picture of the actual code for the default wpa_supplicant implementation, so I don't have that as a reference. Even more annoying, the source code is not easily discoverable online, so I was not able to reference that instead.

Attempting to use the old script didn't work, so I was left an option I very much did not like: using ChatGPT to generate diagnostic scripts.

If you've read previous posts in this series, you might be wondering why I would say that. And the answer is very simple: since the start of 2026, the functionality of the free ChatGPT account has steadily degraded (aka enshittification). As of July 2026, if you upload too many documents, you get a cooldown before you can upload more. If you want it to do code, it can't be too big, or it won't show up in the chat window and it can't be compiled into a file you can download. If you use too many token, you get a cooldown on the default model and forced to use a worse model or wait. And so.

ChatGPT Actually Helped

The reason I picked ChatGPT over my local models was because I wasn't sure how context was required to produce a useful script - or even if Qwen 3.6 had useful knowledge on FreeBSD shell coding.

So I was taking a huge chance when I provided ChatGPT this prompt:

role: freebsd shell script expert | context:
- FreeBSD 15+
- WiFi handling change
- WiFi no long connecting
- output target: `/usr/local/scripts/`
- keep filename short for easy copying | task:
- generate script diagnosing wifi stack (firmware, settings, etc...)
- dump data to `.log` file for analysis

This generated the following script:

#!/bin/sh

##############################################################################
# FreeBSD WiFi Diagnostic Script
#
# Output:
#   /tmp/wdiag-YYYYMMDD-HHMMSS.log
#
##############################################################################

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

if [ "$(id -u)" != "0" ]; then
    echo "Run as root."
    exit 1
fi

TS=$(date +"%Y%m%d-%H%M%S")
LOG="/tmp/wdiag-${TS}.log"

exec >"$LOG" 2>&1

echo "============================================================="
echo "FreeBSD WiFi Diagnostic"
echo "Started: $(date)"
echo "============================================================="
echo

##############################################################################
section()
{
    echo
    echo "============================================================="
    echo "$1"
    echo "============================================================="
}

run()
{
    echo
    echo ">>> $*"
    "$@"
}

##############################################################################

section "SYSTEM"

run uname -a
run freebsd-version
run hostname
run uptime

##############################################################################

section "PCI DEVICES"

run pciconf -lv

##############################################################################

section "USB DEVICES"

if command -v usbconfig >/dev/null 2>&1
then
    run usbconfig
fi

##############################################################################

section "LOADED KERNEL MODULES"

run kldstat

##############################################################################

section "DEVMATCH"

if command -v devmatch >/dev/null 2>&1
then
    run devmatch
fi

##############################################################################

section "INSTALLED FIRMWARE PACKAGES"

pkg info | grep -Ei 'firmware|iwlwifi|rtw88|rtw89|mediatek|ath|wifi|wireless'

##############################################################################

section "WIRELESS INTERFACES"

IFACES=$(ifconfig -l)

for i in $IFACES
do
    if ifconfig "$i" | grep -qi "IEEE"
    then
        echo
        echo "Wireless interface: $i"
    fi
done

##############################################################################

section "IFCONFIG -A"

run ifconfig -a

##############################################################################

section "WIRELESS STATUS"

for i in $(ifconfig -l)
do
    if ifconfig "$i" | grep -qi "IEEE"
    then
        echo
        echo "Interface: $i"

        ifconfig "$i"

        echo
        ifconfig "$i" list scan >/dev/null 2>&1

        echo
        ifconfig "$i" scan
    fi
done

##############################################################################

section "ROUTING"

run netstat -rn

##############################################################################

section "DNS"

cat /etc/resolv.conf

##############################################################################

section "RUNNING NETWORK PROCESSES"

ps axww | grep -E 'wpa|dhclient|netif|routing' | grep -v grep

##############################################################################

section "SERVICE STATUS"

service netif status
service routing status

##############################################################################

section "WPA_SUPPLICANT VERSION"

if command -v wpa_supplicant >/dev/null 2>&1
then
    wpa_supplicant -v
fi

##############################################################################

section "WPA CONFIG"

for f in \
    /etc/wpa_supplicant.conf \
    /etc/wpa_supplicant-*.conf
do
    if [ -f "$f" ]
    then
        echo
        echo "----- $f -----"
        cat "$f"
    fi
done

##############################################################################

section "RC.CONF"

if [ -f /etc/rc.conf ]
then
    cat /etc/rc.conf
fi

##############################################################################

section "LOADER.CONF"

if [ -f /boot/loader.conf ]
then
    cat /boot/loader.conf
fi

##############################################################################

section "LOADER.CONF.LOCAL"

if [ -f /boot/loader.conf.local ]
then
    cat /boot/loader.conf.local
fi

##############################################################################

section "SYSCTL (WIRELESS)"

sysctl -a | grep -Ei \
'80211|wlan|wifi|iwl|rtw|ath|net.wlan'

##############################################################################

section "WLANDEBUG"

if command -v wlandebug >/dev/null 2>&1
then
    wlandebug
fi

##############################################################################

section "DHCLIENT LEASES"

find /var/db -name "dhclient*.leases" -exec sh -c '
for f
do
    echo
    echo "----- $f -----"
    cat "$f"
done
' sh {} +

##############################################################################

section "FIRMWARE DIRECTORIES"

for d in \
    /usr/local/share/firmware \
    /boot/firmware \
    /lib/firmware
do
    if [ -d "$d" ]
    then
        echo
        echo "$d"
        ls -laR "$d"
    fi
done

##############################################################################

section "DMESG (WIRELESS)"

dmesg | grep -Ei \
'iwl|iwx|iwm|ath|rtw|rtwn|urtw|run|ral|rum|otus|rsu|wifi|wlan|firmware|80211'

##############################################################################

section "LAST 500 DMESG LINES"

dmesg | tail -500

##############################################################################

section "BOOT MESSAGES"

if [ -f /var/run/dmesg.boot ]
then
    cat /var/run/dmesg.boot
fi

##############################################################################

section "PKG INFO"

pkg info

##############################################################################

section "PACKAGE VERSIONS"

pkg info | grep -Ei \
'wpa|supplicant|firmware|drm|wifi|wireless'

##############################################################################

section "NETWORK CONFIG FILES"

for f in \
    /etc/hosts \
    /etc/resolv.conf
do
    if [ -f "$f" ]
    then
        echo
        echo "----- $f -----"
        cat "$f"
    fi
done

##############################################################################

section "END"

echo
echo "Completed: $(date)"
echo
echo "Diagnostic log:"
echo "$LOG"

I transferred the script to the MiniPC on a USB, and executed it. Uploading the generated log to ChatGPT provided this analysis:

Based on the diagnostic log, the Wi-Fi hardware and firmware are functioning correctly. The failure occurs later in the initialization process.

## Primary root cause

The most significant error is:

```text
ifconfig: interface wlan0 already exists
/etc/rc.d/wpa_supplicant: ERROR: Failed to create wlan0
```

This indicates that the system is attempting to create the cloned `wlan0` interface even though it already exists.

This is **not** a firmware failure or a driver crash.

Instead, it points to one of:

* duplicate interface creation
* duplicate network initialization
* OPNsense startup scripts conflicting with FreeBSD rc scripts
* stale interface configuration after migration to the new `iwlwifi` driver

---

## Evidence

### 1. Driver loads successfully

The Intel AX101 is detected correctly.

```text
Detected Intel(R) Wi-Fi 6 AX101
successfully loaded firmware image
loaded firmware version ...
```

No firmware errors appear.

---

### 2. Firmware is present

The correct firmware exists:

```
iwlwifi-so-a0-hr-b0-89.ucode
```

---

### 3. Hardware initializes

The interface obtains a MAC address:

```
base HW address:
Ethernet address:
```

This means

* PCI
* DMA
* firmware upload
* RF initialization

all completed successfully.

---

### 4. The interface already exists

Later the log reports

```
Wireless interface:
iwlwifi0_wlan0
```

which means the clone **already exists**.

Yet rc later attempts

```
create wlan0
```

again.

That fails.

---

## 5. No association attempt

I do **not** see any of:

* authentication
* association
* RSN negotiation
* WPA handshake
* scan failures

There are no messages like

```
Associated
AUTH
DEAUTH
4-way handshake
SSID
```

That means Wi-Fi never reached the stage of talking to the AP.

---

## 6. No DHCP attempt

The DHCP lease section is empty.

This is expected because there was never a usable wireless interface.

---

# Things that are NOT the problem

### Firmware

Firmware loads correctly.

---

### Unsupported chipset

The card is fully recognized.

```
Intel Wi-Fi 6 AX101
```

---

### Missing kernel module

The module is loaded.

```
if_iwlwifi.ko
```

---

### Missing firmware package

Firmware exists.

---

### RF kill

```
RFIm is deactivated, reason = 4
```

This message is common for Intel LinuxKPI drivers and is **not** itself an indication that the radio is disabled. The device proceeds to initialize and receives its MAC address afterward. 

---

# What I suspect

Given the log, my confidence ranking is:

| Likelihood | Cause                                                                                                                  |
| ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| ★★★★★      | OPNsense creating the WLAN interface twice                                                                             |
| ★★★★★      | Stale interface configuration after migration to `iwlwifi`                                                             |
| ★★★★☆      | `/etc/rc.conf` or generated configuration still references `wlan0` while OPNsense has already created `iwlwifi0_wlan0` |
| ★★★☆☆      | Race between interface creation and `wpa_supplicant` startup                                                           |
| ★☆☆☆☆      | Driver bug                                                                                                             |

---

# Information missing from the diagnostic

The diagnostic script did not collect the configuration needed to identify *why* the duplicate creation is happening. Specifically, it is missing:

* `/etc/rc.conf`
* `/conf/config.xml` (OPNsense)
* `ifconfig iwlwifi0_wlan0`
* `service netif status`
* `service wpa_supplicant status`
* `ifconfig -g wlan`
* `cloned_interfaces`
* `wlans_iwlwifi0`
* output of `sysrc -a`
* `/var/run/wpa_supplicant`
* `sockstat -4 -6 | grep wpa`

These would distinguish between an OPNsense configuration issue and a FreeBSD networking configuration issue.

## Conclusion

The log does **not** indicate a hardware, firmware, or Intel `iwlwifi` driver failure. The Wi-Fi adapter initializes successfully, the correct firmware loads, and the wireless interface is created.

The failure occurs because the system later attempts to create `wlan0` a second time, causing `wpa_supplicant` initialization to fail before any scan, association, or DHCP activity can occur. The evidence points most strongly to duplicate WLAN interface creation or conflicting network initialization logic, likely involving OPNsense's network configuration rather than the wireless driver itself.

I then used the missing information section to create new prompt for updating the script:

update script to add capture:
- `/etc/rc.conf`
- `ifconfig iwlwifi0_wlan0`
- `service netif status` 
- `service wpa_supplicant status`
- `ifconfig -g wlan` - `cloned_interfaces` 
- `wlans_iwlwifi0`
- `output of sysrc -a`
- `/var/run/wpa_supplicant`
- `sockstat -4 -6 | grep wpa`

To my irritation, ChatGPT didn't generate a complete, updated script, just sections that I had to manually add. I then transferred this updated script to the miniPC, ran it, and brought the logs back to ChatGPT for analysis. This is the result:

The updated diagnostic changes the diagnosis significantly. It eliminates several earlier hypotheses and identifies a configuration inconsistency that is likely the actual root cause.

## Executive summary

The Intel AX101 hardware, firmware, LinuxKPI layer, and RF subsystem are all functioning correctly.

The system can:

* detect the adapter
* load firmware
* create the wireless interface
* scan for nearby access points
* receive beacons from the target SSID

However, **`wpa_supplicant` never takes control of the interface**, so the interface remains:

* `ssid ""`
* `authmode OPEN`
* `privacy OFF`
* `status: no carrier`

even though the desired WPA2 network is visible. 

---

# Root Cause #1 (Highest Confidence)

## Mismatch between rc.conf and sysrc configuration

Your diagnostic captured something that was previously missing:

`/etc/rc.conf`

contains

```text
wpa_supplicant_iface="iwlwifi0_wlan0"
```

but

`sysrc -a`

reports

```text
wpa_supplicant_iface: wlan0
wpa_supplicant_parent: iwlwifi0
```

while the remaining variables point to the renamed interface:

```text
wpa_supplicant_conf=/var/etc/wpa_supplicant_iwlwifi0_wlan0.conf
```

These settings are internally inconsistent.

One component believes the interface is:
```
wlan0
```

while another believes it is
```
iwlwifi0_wlan0
```

That exactly matches the boot error:
```
ifconfig: interface wlan0 already exists
/etc/rc.d/wpa_supplicant: ERROR: Failed to create wlan0
```

---

# Root Cause #2

## Duplicate interface creation

The boot log shows
```
wlan0
```
being created,

then immediately renamed
```
iwlwifi0_wlan0
```

Then later
```
wpa_supplicant
```

tries to create
```
wlan0
```
again.

```
wlan0
→ renamed to iwlwifi0_wlan0
→ create wlan0
→ already exists
→ failure
```

This is almost certainly occurring because OPNsense's interface management and the FreeBSD `rc.d/wpa_supplicant` script are both attempting to manage the WLAN interface. 

---

# Root Cause #3

## wpa_supplicant never actually starts

The new log contains:

```
SERVICE WPA_SUPPLICANT

```

with no running status or process, and `/var/run/wpa_supplicant` contains only the directory itself with no control socket. 

If `wpa_supplicant` were active, you would normally expect:

* a control socket named after the interface
* an active process in `sockstat`
* association state transitions

None are present.

---

# Evidence the driver is healthy

## Firmware

Firmware loads correctly.

```
successfully loaded firmware image
```

---

## Interface creation

The interface exists.

```
iwlwifi0_wlan0
```

---

## RF subsystem

The interface scans successfully.

Detected APs include

```
HomeMesh
HomeMesh_IoT
```

Signal strength:

```
-58 dBm
```

which is excellent. 

If firmware or the radio were failing, no scan results would appear.

---

## Driver state

Current interface:

```
status: no carrier
ssid ""
authmode OPEN
privacy OFF
```

This means:

* radio operational
* scan operational
* not authenticated
* not associated
* WPA not active

---

# Why DHCP is not the problem

The interface still has an IPv4 address from a previous configuration:

```
inet ...13/24
```

yet

```
status: no carrier
```

That address is stale and does not indicate a current wireless connection.

---

# Why the WPA configuration is probably not the issue

Your diagnostic shows a valid WPA configuration file with an SSID and a PSK. 

The issue is not that the configuration file is missing; it is that no active `wpa_supplicant` instance appears to be using it.

---

# Likelihood assessment

| Cause                                                                | Confidence |
| -------------------------------------------------------------------- | ---------- |
| `wpa_supplicant` never starts because of interface creation conflict | **99%**    |
| OPNsense and FreeBSD rc scripts both creating the WLAN interface     | **98%**    |
| `wpa_supplicant_iface` mismatch (`wlan0` vs `iwlwifi0_wlan0`)        | **95%**    |
| Intel AX101 driver bug                                               | **5%**     |
| Firmware issue                                                       | **<1%**    |
| Hardware failure                                                     | **<1%**    |
| Weak signal                                                          | **0%**     |

## Recommended next diagnostic steps

To confirm the remaining hypothesis, collect:

* `ps auxww | grep wpa_supplicant`
* `service wpa_supplicant onestatus`
* `service wpa_supplicant forcestart`
* `ifconfig wlan0`
* `ifconfig iwlwifi0`
* `cat /var/etc/wpa_supplicant_iwlwifi0_wlan0.conf`
* `grep -i wpa /conf/config.xml`
* `grep -R "create_args" /etc/rc* /usr/local/etc/rc*`

The strongest evidence from the updated logs is that the wireless stack itself is healthy: the adapter initializes, firmware loads, nearby networks are discovered with strong signal strength, and the interface is present. The failure occurs at the configuration layer, where conflicting interface names (`wlan0` versus `iwlwifi0_wlan0`) and duplicate interface creation prevent `wpa_supplicant` from successfully starting and associating with the access point.

I then asked it to generate a new script based on its recommended next steps:

#!/bin/sh
#
# wifi_stage2_diagnostics.sh
#
# FreeBSD / OPNsense WiFi Diagnostics
#
# Collects additional information needed to diagnose
# Intel iwlwifi / wpa_supplicant startup failures.
#

##############################################################################
# Initialization
##############################################################################

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
HOST=$(hostname)

OUTDIR="/tmp/wifi_stage2_${HOST}_${TIMESTAMP}"

mkdir -p "${OUTDIR}"

LOGFILE="${OUTDIR}/diagnostics.txt"

##############################################################################
# Helper Functions
##############################################################################

section()
{
    echo
    echo "===================================================================="
    echo "$1"
    echo "===================================================================="
}

run_cmd()
{
    echo
    echo "--------------------------------------------------------------------"
    echo "$1"
    echo "--------------------------------------------------------------------"

    sh -c "$1" 2>&1

    echo
}

copy_file()
{
    FILE="$1"

    echo
    echo "--------------------------------------------------------------------"
    echo "$FILE"
    echo "--------------------------------------------------------------------"

    if [ -e "$FILE" ]; then
        cat "$FILE"
    else
        echo "File not found."
    fi

    echo
}

##############################################################################
# Begin Logging
##############################################################################

exec >"${LOGFILE}" 2>&1

echo
echo "WiFi Stage 2 Diagnostics"
echo

echo "Date:      $(date)"
echo "Hostname:  $(hostname)"
echo "Kernel:    $(uname -a)"

##############################################################################
section "SYSTEM"

run_cmd "uptime"
run_cmd "uname -a"
run_cmd "freebsd-version -ku"
run_cmd "sysctl kern.osrelease"
run_cmd "sysctl kern.version"

##############################################################################
section "BOOT LOG"

run_cmd "dmesg | grep -Ei 'iwl|wifi|wlan|firmware|linuxkpi|wpa|80211'"

##############################################################################
section "KERNEL MODULES"

run_cmd "kldstat"

##############################################################################
section "PCI DEVICES"

run_cmd "pciconf -lv"

##############################################################################
section "NETWORK INTERFACES"

run_cmd "ifconfig -a"

run_cmd "ifconfig wlan0"

run_cmd "ifconfig iwlwifi0"

run_cmd "ifconfig iwlwifi0_wlan0"

run_cmd "ifconfig -g wlan"

##############################################################################
section "WIRELESS STATUS"

run_cmd "ifconfig iwlwifi0_wlan0 list scan"

run_cmd "ifconfig iwlwifi0_wlan0"

##############################################################################
section "ROUTING"

run_cmd "netstat -rn"

run_cmd "route -n get default"

##############################################################################
section "RC.CONF"

copy_file "/etc/rc.conf"

##############################################################################
section "SYSRC"

run_cmd "sysrc -a"

run_cmd "sysrc cloned_interfaces"

run_cmd "sysrc wlans_iwlwifi0"

run_cmd "sysrc ifconfig_wlan0"

run_cmd "sysrc ifconfig_iwlwifi0"

run_cmd "sysrc ifconfig_iwlwifi0_wlan0"

run_cmd "sysrc wpa_supplicant_enable"

run_cmd "sysrc wpa_supplicant_iface"

run_cmd "sysrc wpa_supplicant_conf"

##############################################################################
section "SERVICES"

run_cmd "service netif status"

run_cmd "service routing status"

run_cmd "service devd status"

run_cmd "service wpa_supplicant status"

run_cmd "service wpa_supplicant onestatus"

##############################################################################
section "PROCESS LIST"

run_cmd "ps auxww"

run_cmd "ps auxww | grep -i wpa"

run_cmd "pgrep -laf wpa_supplicant"

##############################################################################
section "SOCKETS"

run_cmd "sockstat -4 -6"

run_cmd "sockstat -4 -6 | grep wpa"

##############################################################################
section "WPA CONTROL SOCKETS"

run_cmd "ls -alR /var/run/wpa_supplicant"

##############################################################################
section "WPA CONFIGURATION"

copy_file "/var/etc/wpa_supplicant_iwlwifi0_wlan0.conf"

copy_file "/etc/wpa_supplicant.conf"

##############################################################################
section "OPNSENSE CONFIG"

copy_file "/conf/config.xml"

run_cmd "grep -ni wpa /conf/config.xml"

run_cmd "grep -ni wlan /conf/config.xml"

run_cmd "grep -ni iwl /conf/config.xml"

##############################################################################
section "RC SCRIPTS"

run_cmd "grep -R \"create_args\" /etc/rc* /usr/local/etc/rc* 2>/dev/null"

run_cmd "grep -R \"wpa_supplicant\" /etc/rc* /usr/local/etc/rc* 2>/dev/null"

run_cmd "grep -R \"iwlwifi\" /etc/rc* /usr/local/etc/rc* 2>/dev/null"

##############################################################################
section "DEVCTL"

run_cmd "devctl status"

##############################################################################
section "SYSCTL"

run_cmd "sysctl net.wlan"

run_cmd "sysctl compat.linuxkpi"

##############################################################################
section "DHCP"

run_cmd "ps auxww | grep dhclient"

run_cmd "cat /var/db/dhclient.leases.* 2>/dev/null"

##############################################################################
section "LOG FILES"

run_cmd "tail -200 /var/log/messages"

run_cmd "grep -Ei 'wpa|wlan|iwl|firmware|linuxkpi' /var/log/messages"

##############################################################################
section "PING TEST"

run_cmd "ping -c 3 127.0.0.1"

run_cmd "ping -c 3 $(route -n get default 2>/dev/null | awk '/gateway/ {print \$2}')"

##############################################################################
section "FINAL SUMMARY"

echo
echo "Diagnostic completed:"
echo

echo "Output directory:"
echo "    ${OUTDIR}"

echo

echo "Main log:"
echo "    ${LOGFILE}"

echo

cd /tmp

tar czf "$(basename "${OUTDIR}").tar.gz" "$(basename "${OUTDIR}")"

echo "Archive:"
echo "    /tmp/$(basename "${OUTDIR}").tar.gz"

echo
echo "Done."

After going through the process of importing it onto the miniPC, running, and coming back with the logs, I got this analysis:

After reviewing the Stage 2 diagnostic, the root cause is much clearer.

## Conclusion

This is **not**:

* an Intel `iwlwifi` driver bug
* a firmware problem
* a LinuxKPI issue
* a hardware failure
* a WPA configuration syntax error

The failure is caused by **conflicting `wpa_supplicant` configuration sources**, which result in the interface being managed under two different names.

## Root cause (≈99% confidence)

There is a direct configuration conflict between **`/etc/rc.conf`** and **`/etc/rc.conf.local`**.

`/etc/rc.conf` specifies:

```text
wpa_supplicant_iface="iwlwifi0_wlan0"
```

while `/etc/rc.conf.local` specifies:

```text
wpa_supplicant_iface="wlan0"
```

The diagnostic also shows that `sysrc` resolves the active value as:

```text
wpa_supplicant_iface: wlan0
```

even though `/etc/rc.conf` contains `iwlwifi0_wlan0`. 

This means the later-loaded configuration is overriding the earlier one.

---

## The boot sequence explains the failure

The kernel initializes normally:

* detects the Intel AX101
* loads firmware
* creates `wlan0`
* renames it to `iwlwifi0_wlan0`

Immediately afterward:

```
ifconfig: interface wlan0 already exists
/etc/rc.d/wpa_supplicant: ERROR: Failed to create wlan0
```

appears in the boot log. 

This indicates that the `rc.d/wpa_supplicant` script still believes the interface should be named `wlan0` and attempts to create it again.

---

## Why `wpa_supplicant` never starts

The Stage 2 diagnostics show:

* no `wpa_supplicant` process
* `pgrep` returns nothing
* `sockstat` contains no `wpa_supplicant`
* `/var/run/wpa_supplicant` contains only an empty directory with no control socket  

Therefore the daemon never successfully starts.

Without `wpa_supplicant`:

* no authentication
* no association
* no WPA handshake

---

## The wireless driver is healthy

The driver:

* detects the Intel AX101
* uploads firmware successfully
* exposes the wireless interface
* reports the parent interface correctly

The interface exists as:

```
iwlwifi0_wlan0
```

and is operational from the driver's perspective. 

Nothing in the diagnostics suggests a driver fault.

---

## The WPA configuration is valid

The generated configuration file contains:

* `ctrl_interface`
* `network`
* `ssid`
* `psk`
* `key_mgmt=WPA-PSK`

and is syntactically correct. 

The configuration is simply never consumed because the daemon fails before startup.

---

## Secondary finding

The diagnostics reveal another inconsistency:

```
/etc/rc.conf
    wpa_supplicant_iface="iwlwifi0_wlan0"

/etc/rc.conf.local
    wpa_supplicant_iface="wlan0"
```

At the same time, both files reference the same configuration file:

```
/var/etc/wpa_supplicant_iwlwifi0_wlan0.conf
```

This mixed configuration strongly suggests an incomplete migration from the traditional `wlan0` naming convention to `iwlwifi0_wlan0`. 

---

## What is **not** the problem

The Stage 2 logs rule out:

* Firmware loading failure
* Unsupported Intel AX101 hardware
* Missing firmware files
* Invalid WPA-PSK configuration
* Missing `if_iwlwifi` kernel module
* Missing `wpa_supplicant` package

---

## Most likely origin

This appears to be a **configuration generation issue**, not a runtime issue.

Possible sources include:

* OPNsense generating inconsistent `rc.conf.local`
* a stale configuration remaining after switching to the `iwlwifi` driver
* conflicting interface naming logic between OPNsense and the FreeBSD `rc.d/wpa_supplicant` script

The conflict is visible in the configuration files themselves before any network traffic occurs.

## Confidence assessment

| Finding                                                                     | Confidence |
| --------------------------------------------------------------------------- | ---------: |
| Conflicting `wpa_supplicant_iface` values (`wlan0` vs `iwlwifi0_wlan0`)     |        99% |
| `wpa_supplicant` exits before starting                                      |        99% |
| Duplicate interface creation is a consequence of the configuration conflict |        98% |
| Intel `iwlwifi` driver defect                                               |        <1% |
| Firmware defect                                                             |        <1% |
| Hardware failure                                                            |        <1% |

From these diagnostics, the most likely corrective action is to eliminate the conflicting interface-name definitions so that **all** `wpa_supplicant` configuration sources reference the same interface name. Once the interface naming is consistent, `rc.d/wpa_supplicant` should no longer attempt to recreate `wlan0`, allowing the daemon to start and proceed with WPA association.

I then started a new ChatGPT conversation with the following prompt, plus an upload of the original setup script:

role: freebsd 15.1 shell code expert | context:
- wifi not functioning after update to freebsd 15.1 based kernel
- error: `wpa_supplicant not running`
- error: `ifconfig: SIOCIFCREATE2 (iwlwifi0_wlan0): Invalid argument`
- error: `/etc/rc.d/wpa_supplicant: ERROR: Failed to create iwlwifi0_wlan0`
- chat: `Wi-Fi Initialization Issue` | task: update uploaded script to account for freebsd 15.1 updates to `iwlwifi` handling, ensure functioning wifi connection

It gave me this interesting analysis of the problems with the script:

Based on the script and the errors, the problem is **not `wpa_supplicant` itself**. The script assumes the FreeBSD 14.x Intel wireless model, but **FreeBSD 15.1 changed parts of the `iwlwifi`/802.11 initialization sequence**.

The sequence of failures is significant:

```
ifconfig: SIOCIFCREATE2 (iwlwifi0_wlan0): Invalid argument
        ↓
wlan interface never created
        ↓
wpa_supplicant cannot bind to interface
        ↓
wpa_supplicant not running
```

The first failure is therefore the root cause.

## Problems in the current script

### 1. Incorrect interface creation

The script currently does

```sh
ifconfig "${wpa_supplicant_parent}" create \
    wlandev "${wpa_supplicant_parent}"
```

For Intel this expands to

```sh
ifconfig iwlwifi0 create wlandev iwlwifi0
```

This is **no longer reliable** on newer kernels.

The supported form is

```sh
ifconfig wlan create wlandev iwlwifi0 name iwlwifi0_wlan0
```

or

```sh
ifconfig wlan0 create wlandev iwlwifi0
```

depending on configuration.

Using the parent interface as the object being created now returns

```
SIOCIFCREATE2
Invalid argument
```

---

### 2. Script ignores rc.conf

FreeBSD 15 expects the networking framework to own cloned interfaces.

Instead of manually creating

```
iwlwifi0_wlan0
```

the preferred configuration is

```sh
wlans_iwlwifi0="wlan0"
```

or

```sh
wlans_iwlwifi0="iwlwifi0_wlan0"
```

Then

```
service netif start
```

creates it.

The rc.d script should **verify** the interface exists.

It should **not** normally create it itself.

---

### 3. Wrong REQUIRE dependency

Current:

```sh
REQUIRE: NETWORKING
```

`NETWORKING` completes before cloned wlan interfaces exist.

Instead use

```sh
REQUIRE: netif
AFTER: devd
```

or simply

```
REQUIRE: LOGIN netif
```

depending on when you want it.

Otherwise

```
service wpa_supplicant start
```

runs before wlan creation.

---

### 4. Missing parent validation

Before doing anything the script should verify

```sh
ifconfig -l
```

contains

```
iwlwifi0
```

If not

```
kldload if_iwlwifi
```

is insufficient.

It also needs

```
kldload firmware
```

(or the proper Intel firmware module)

and wait for the device.

---

### 5. Race condition

Immediately after loading

```
if_iwlwifi
```

the firmware loads asynchronously.

The script immediately executes

```
ifconfig wlan create
```

before firmware initialization finishes.

The result is

```
Invalid argument
```

A retry loop is much safer:

```sh
i=0

while [ $i -lt 20 ]
do
    if ifconfig iwlwifi0 >/dev/null 2>&1
    then
        break
    fi

    sleep 1
    i=$((i+1))
done
```

---

### 6. Wrong configuration filename

The script defines

```sh
wpa_supplicant_conf="/var/etc/wpa_supplicant_wlan0.conf"
```

but generated

```
/var/etc/wpa_supplicant_iwlwifi0_wlan0.conf
```

These do **not** match.

So even if the interface existed,

```
wpa_supplicant
```

would fail because the configuration file does not exist.

---

### 7. No interface existence check

Before starting

```
wpa_supplicant
```

the script should verify

```sh
ifconfig "${iface}"
```

returns success.

If not

```
err 1 "${iface} does not exist"
```

instead of attempting to launch.

---

### 8. Missing carrier wait

Even after the interface exists,

```
802.11
```

is not immediately ready.

Wait until

```
ifconfig wlan0
```

reports

```
status: no carrier
```

or

```
status: associated
```

before launching `wpa_supplicant`.

---

## Recommended FreeBSD 15.1 startup order

The service should follow this sequence:

```
Load firmware
        ↓
Load if_iwlwifi
        ↓
Wait for iwlwifi0
        ↓
Verify parent exists
        ↓
Verify wlan clone exists
        ↓
Create clone only if missing
        ↓
Bring interface down
        ↓
Bring interface up
        ↓
Wait for 802.11 initialization
        ↓
Launch wpa_supplicant
        ↓
Verify PID
        ↓
Run DHCP
```

---

## The biggest architectural change I recommend

Instead of having the script create interfaces itself:

```
ifconfig create ...
```

delegate interface creation to FreeBSD networking.

Your setup script should generate:

```sh
wlans_iwlwifi0="iwlwifi0_wlan0"

ifconfig_iwlwifi0_wlan0="WPA DHCP"

create_args_iwlwifi0_wlan0="country US"

wpa_supplicant_enable="YES"

wpa_supplicant_conf_file="/var/etc/wpa_supplicant_iwlwifi0_wlan0.conf"
```

Then startup becomes simply

```
service netif restart
service routing restart
```

This uses the networking framework exactly as intended in FreeBSD 15.1, rather than duplicating interface creation logic in a custom rc.d script.

## Additional issues in the uploaded script

I also found these bugs:

* `wpa_supplicant_conf` points to the wrong filename.
* `status_cmd` only checks the PID file and does not verify the process is running.
* `stop_cmd` does not wait for process termination before removing the PID file.
* No retry logic if firmware initialization is delayed.
* No verification that `/var/run/wpa_supplicant` exists before launching.
* No automatic DHCP (`dhclient`) after successful association.
* No logging via `logger` or `syslog`, making failures harder to diagnose.

Given the FreeBSD 15.1 networking changes, I would recommend replacing most of the custom rc.d service logic rather than patching it. A redesigned version that relies on the native `netif` framework, handles Intel firmware initialization, performs robust validation and retry logic, and includes detailed logging will be substantially more reliable than adapting the current script.

When I asked it to actually generate said updated script, it began giving me all sorts of responses about not being able to produce the script in the chat window or as a file. So I responded with a simple command:

generate caveman mode prompt for qwen 3.6 for script generation

Now, this prompt had a massive flaw that I didn't realize until I looked at the output. Namely, I didn't tell ChatGPT to provide context for the uploaded script in the prompt, which forced me to add the script to the Qwen 3.6 prompt.

The final thing I got from ChatGPT before moving over to a local Qwen 3.6 instance was the following prompt:

# ROLE

You are a senior FreeBSD kernel, networking, and POSIX shell engineer with extensive knowledge of FreeBSD 15.1, Intel iwlwifi, rc.d, netif, devd, ifconfig, wpa_supplicant, and the FreeBSD wireless networking stack.

Generate production-quality code only.

Do not simplify solutions.

Do not omit code.

Do not use placeholders.

Do not shorten files.

Think through the entire architecture before writing any code.

---

# OBJECTIVE

Rewrite the supplied script into a robust, production-quality installer and repair utility for configuring Intel `iwlwifi` wireless networking on **FreeBSD 15.1+**.

The final deliverable shall be a **single POSIX-compliant shell script**.

The script must work correctly on modern FreeBSD releases without requiring manual editing after generation.

---

# IMPORTANT

Do NOT preserve the existing implementation.

Treat the uploaded script only as a reference for desired functionality.

Redesign everything as necessary.

Correct every architectural mistake.

Prefer FreeBSD base-system tools over custom implementations.

---

# PRIMARY GOALS

The generated script shall:

* detect FreeBSD version
* detect FreeBSD wireless subsystem
* detect Intel iwlwifi interfaces
* detect firmware
* load required modules
* wait for firmware initialization
* safely create wlan clone interfaces
* configure rc.conf.local
* configure wpa_supplicant
* verify interface creation
* verify association
* verify DHCP
* provide detailed diagnostics
* provide repair mode
* provide uninstall mode
* provide status mode
* be idempotent
* never corrupt an existing installation
* automatically back up modified files
* automatically roll back failed changes

---

# ROOT CAUSE TO FIX

The existing script fails because it assumes FreeBSD 14 wireless behavior.

Observed errors:

```
wpa_supplicant not running

ifconfig:
SIOCIFCREATE2
Invalid argument

ERROR:
Failed to create iwlwifi0_wlan0
```

The generated script MUST eliminate these failures.

---

# FREEBSD 15.1 REQUIREMENTS

The script MUST account for changes introduced in FreeBSD 15.x.

Do NOT rely on outdated assumptions.

Examples include:

* asynchronous firmware initialization
* newer wlan clone behavior
* proper netif integration
* correct interface creation sequence
* proper rc.conf usage
* correct dependency ordering

---

# REQUIRED DESIGN

DO NOT generate a custom rc.d service unless absolutely necessary.

Prefer native FreeBSD services.

Use:

```
service netif
service routing
service devd
service dhclient
```

where appropriate.

The script should configure the base system rather than replace it.

---

# WLAN CREATION

Never assume the interface exists.

Automatically detect:

```
iwlwifi0
iwlwifi1
...
```

Automatically create

```
wlan0
```

or

```
iwlwifi0_wlan0
```

using the correct FreeBSD 15 syntax.

Validate creation before continuing.

Retry when firmware is still initializing.

---

# WPA SUPPLICANT

Generate

```
/var/etc/wpa_supplicant_<interface>.conf
```

using modern syntax.

Verify:

* permissions
* ownership
* readability
* syntax
* existence

Launch only after interface validation.

Confirm PID.

Confirm process exists.

---

# RC.CONF

Automatically configure:

* wlans_<parent>
* ifconfig_<wlan>
* create_args_<wlan>
* cloned_interfaces (if needed)
* hostname preservation
* existing configuration preservation

Never duplicate entries.

Never corrupt formatting.

Update in-place when possible.

---

# INSTALLER FEATURES

Support:

```
--install

--repair

--status

--diagnose

--remove

--backup

--restore

--verbose

--debug

--dry-run

--help
```

---

# DIAGNOSTICS

Collect:

```
uname -a

freebsd-version

kldstat

pciconf

ifconfig -a

ifconfig -g wlan

sysrc -a

service netif status

service routing status

service devd status

sockstat

wpa_cli status

dhclient output

dmesg

journal

routing table

firmware modules

wireless capabilities

scan results

association state

RSSI

driver state

country code

regulatory domain
```

Generate a timestamped report.

---

# LOGGING

Implement structured logging.

Levels:

```
INFO

WARN

ERROR

DEBUG
```

Support:

* stdout
* stderr
* syslog
* log file

---

# ERROR HANDLING

Every command shall:

* check exit status
* print useful diagnostics
* explain probable causes
* recommend corrective action

Never silently ignore failures.

---

# SAFETY

Before modifying anything:

Automatically back up:

```
/etc/rc.conf

/etc/rc.conf.local

/var/etc

/etc/wpa_supplicant*

/var/run/wpa_supplicant
```

Rollback automatically if installation fails.

---

# SCRIPT QUALITY

Produce:

* POSIX shell only
* shellcheck clean
* shfmt formatted
* heavily commented
* modular functions
* minimal duplication
* consistent naming
* safe quoting
* strict mode
* traps
* cleanup handlers

---

# DO NOT

Do NOT:

* use placeholders
* omit functions
* abbreviate code
* shorten comments
* skip validation
* assume interface names
* assume firmware names
* assume Intel generation
* assume DHCP success
* assume wireless association
* assume rc.conf contents

---

# OUTPUT FORMAT

Return ONLY one complete shell script.

No explanations.

No markdown.

No summaries.

No omitted code.

No "...".

No "remaining code omitted".

No pseudocode.

No placeholders.

Produce the complete file from the first line through the final `exit 0`.

If the script exceeds one response, continue automatically in subsequent responses until the entire file has been produced.

Never restart from the beginning.

Resume exactly where the previous response ended.

The final response must contain the entire completed production-ready script.

Working with Qwen3.6-Uncensored-NEO-CODE

As part of my experimentation with local models, I picked up this DavidAU finetune of Qwen 3.6 for coding purposes. While it is a large model, around 20 GB, loading it into 32 GB of RAM and giving it 32K context window was enough for the ChatGPT generated prompt + including the original setup_wpa.sh script.

What surprised me the most was the model actually did a pretty good job of generating producing the code for the script. It took a good amount of time, due to running on a mobile integrated GPU, but it completed the task.

Unfortunately, it didn't get the job done, and I spent a good number of iterations cracking down on bugs that didn't move me closer to getting the script functional.

So I had to pivot to agentic workflow.

Speeding up the task was the fact that I used the NuExtract3 local OCR model to extract error log details from pictures of the monitor, allowing me to accurately prompt the model for debugging. I maintained this flow through the rest of the process.

Enter OpenCode

Switching over to OpenCode was a reluctant decision. It was driven mostly by the fact that my ~1000 line (at that point) script was pushing my context window limits, and sheer exhaustion with the process of manually debugging with Qwen 3.6. Making things harder was the fact that OpenCode's free models changed partway through the process, and most of them kept running into usage limits.

The first step of the process was uploading the new script to my setup_wpa GitHub repo, then downloading the repo onto my computer. I then pointed OpenCode to the folder and began working with North Mini Code Free, a non-reasoning model. Even with an agentic prompt, its performance was not great, and the only real positive I can say is that it had few availability restrictions.

Most of the work was done with Nemotron 3 Ultra Free and MiMo V2.5, which posed some challenges. Since Nemotron 3 Ultra has a 1 million token context limit, I encountered more and more retry attempts after 7-8AM Eastern time in the US. This got to the point that I finished out one job with Nemotron 3 and switched to MiMoV2.5. This model has a much smaller 200K token context limit, which posed new problems.

MiMo also gave me retry attempts, although few and shorter than Nemotron 3 Ultra, but the major issue was the context limit. On at least 2 occasions, I was forced to generate an agentic prompt to implement a bug fix and use that prompt in a brand new session, because the bug analysis ate up most of the session's context window. As a result, it took me 16 conversation sessions to get a functional minimum viable script:

OpenCode UI showing all conversations related to updating setup_wpa repo.

Configuring OPNSense 26.7

Having anticipated trouble, I downloaded a backup XML version of my OPNSense configuration before initiating the update to 26.7. However, the crashing I saw after doing the update went away after I reset to the default configuration. This meant that the safest course of action was to do a partial setup of the transparent filtering bridge, export an updated OPNSense config XML file, then splice data from the old file into the new file, and then upload that into OPNsense.

Not helping this process were two semi-related problems:

  • OPNSense firewall was in effect on the WiFi interface, forcing me to disable the firewall to access the WebGUI.
  • The WebGUI's performance was pretty terrible.

What would happen is that as I configured settings, saving and applying those settings caused the firewall to restart, forcing me to physically go to the miniPC and type in the command to disable the firewall. A combination of firewall rules and applying a hotfix update eventually improved WebGUI access and performance/loading.

Eventually, I reached a point where I felt comfortable in downloading the then-current configuration and integrating the old data into it. When I did, I discovered that the layouts of the two configuration files greatly differed:

Side by side comparison of the two OPNSense configuration files, showing different layouts.

The completely different layout of the new configuration XML, when combined with the changes to the WiFi stack, probably contributed to why OPNSense kept crashing when I first upgraded.

What I discovered, to my annoyance, was that the import process didn't work for rules - and looking on the OPNSense GitHub Issues page, this seems to be an issue with 26.7, not my work. So I was left with 50+ blank rule files that I had to manually configure anyway.

Blank rules after attempting to import them via config XML editing.

Initially, it also didn't work for Aliases either. However, I made a dummy alias (imaginatively named "Dummy"), then exported the configuration file, replaced the dummy alias with the aliases from the old config, and that properly imported. After doing that, I added a new set of IP block lists to my list of aliases to increase coverage.

Updated Alias list, prior to full update of online lists

Rebuilding my rules took a while, as I chose to implement separate IN/OUT rules with each alias for finer control and logging. This resulted in 56 blocking rules, 2 diagnostic rules for gathering data on connectivity to my ISP's infrastructure, and 2 fallback rules allowing traffic in and out of the bridge. The fallback rules are placed last in the list, executing after all the other rules, to ensure malicious and ad traffic are blocked.

After many long hours of work configuring the device, it was finally time to connect it to the modem and router. And that's when I discovered a new problem.

How Spectrum Handles DHCP

Like many Floridians, my internet access is handled by Spectrum, the Charter owned ISP. You can easily find many reports of dissatisfaction with Spectrum on a wide variety of issues, but this one is a pretty obscure one. That's because most consumers don't put a transparent filtering bridge/firewall between their modem and router.

What I discovered is that Spectrum's DHCP process triggers one of the alias/block list based block rules, preventing the router from receiving an IP address:

OPT2 In [DATE] UDP 0.0.0.0:68 255.255.255.255:67 block Block Firehol_level1 coming IN

Looking at the Virus Total page reveals why someone would put 0.0.0.0 on a block list:

This forced me to implement an in/out pass rule, but I minimized the window of vulnerability with OPNSense's scheduling feature. This allowed me to set a scheduled time for the rule to activate, and the tightest time window possible (15 minutes) was more than sufficient for the DHCP lease/renewal process to complete. (It turns out this is a major issue with the firewall scheduler and requires rebuilding the system.)

Since the DHCP lease seems to hold until either the router restarts or something happens to the network connection on Spectrum's end, this rule only needs to work once a week after I managed to get the rule functional.

Suricata Configuration

This is where things became interesting, because it turns out Suricata is connected to the crashing I was seeing when I began the 26.7 upgrade.

The precise mechanics of this crash are not clear to me, because they only occurred partway through the configuration process. As far as I can tell, it was not the act of enabling Suricata, but something related to either the way it processes packets and/or the data sources it uses that triggered the crash.

This forced me to once again reset OPNSense to default settings, but I had made a backup of the most recent configuration, minus a few additions, that allowed me to quickly restore functionality.

This issue was reported on GitHub.

Future Upgrade Planning

I went into this upgrade process thinking I had a solid plan. If anything bad happened, I could just reload the backed up config file, or at worst, extract data from the old file, splice it into a new file, and upload that into OPNSense. Events proved me completely wrong on that assessment.

The easy part of a better, more comprehensive upgrade plan is all on the OPNsense end:

  • Make a backup of the configuration before upgrading.
  • Make a CSV export of the alias list before upgrading.
  • Make a CSV export of the firewall rule list before upgrading.

This plan would allow me to bypass any and all configuration related issues, albeit at the cost of forcing me to manually rebuild my Suricata config each and every time I couldn't roll it over/import it.

The much harder part of the new upgrade plan is figuring out what to do to prepare a virtual machine environment for OPNSense for testing purposes. For the simple purpose of examining the code for the wpa_supplicant, any virtual machine will do. However, specifically testing out the scripts I've made might be impossible, depending on whether or not I can emulate the devices in the miniPC. Further research is necessary.

Next Steps

After four days wrestling with these problems, I am more than happy to take a step back and monitor the transparent filtering bridge to see if it can operate normally, or there's some other problems that I haven't yet experienced.

Takeaways

  • I used a custom wpa_supplicant setup file for managing OPNSense on a miniPC via WiFi.
  • OPNSense versions 26.1+ were stable, but updates required reapplying the script because they reverted the wpa_supplicant file.
  • I updated to OPNSense 26.7 after confirming minimal issues for N100 miniPCs on Reddit.
  • After updating to 26.7, the miniPC crashed 1-2 minutes after booting when attempting to access the shell.
  • Reinstalling OPNSense failed, so I used “Reset to Default Configuration,” which resolved the crashing.
  • A configuration backup existed prior to the update, reducing the risk of this approach.
  • Resetting to default configuration fixed the crash but left the wpa_supplicant not connected to the home network.
  • The old script failed, leading me to use ChatGPT for diagnostic scripts despite concerns about ChatGPT’s declining functionality (“enshittification”).
  • ChatGPT generated a diagnostic script that identified the issue as duplicate WLAN interface creation or conflicting network initialization logic, not hardware or driver failure.
  • Further diagnostics revealed conflicting interface names (wlan0 vs. iwlwifi0_wlan0) prevented wpa_supplicant from starting.
  • ChatGPT analyzed the original script and identified several bugs, recommending a redesign rather than patching.
  • Due to ChatGPT’s limitations in generating full scripts, I requested a “caveman mode prompt” for Qwen 3.6.
  • I used a local Qwen 3.6 fine-tune for coding, but it failed to produce a functional script despite multiple iterations.
  • I switched to OpenCode due to context window limitations and exhaustion with Qwen 3.6.
  • Various models (North Mini Code Free, Nemotron 3 Ultra Free, MiMo V2.5) were used, with varying success and significant context window issues.
  • It took 16 conversation sessions to achieve a minimum viable script.
  • I performed a partial setup, exported the config, and spliced old data into the new XML file.
  • The new configuration XML layout differed significantly from the old one, likely contributing to the initial crashes.
  • Firewall rules and aliases did not import correctly, requiring manual reconfiguration.
  • Spectrum’s DHCP process triggered a block rule for 0.0.0.0, preventing the router from getting an IP.
  • I created a scheduled pass rule to allow DHCP renewal during a narrow 15-minute window.
  • Enabling Suricata or its packet processing/data sources likely caused the initial crashes.
  • I had to reset OPNSense to default settings again but could quickly restore from a recent backup.
  • A better plan includes backing up the configuration, alias list, and firewall rule list as CSVs before upgrading.
  • Testing in a virtual machine is considered but may be limited by hardware emulation constraints.
  • I will monitor the transparent filtering bridge for stability and any new issues.