Flint GL-AX1800 Restricting WiFi Access Based on MAC

Hello. First of all, the Flint is miss so many of the typical router features and have numerous limitations, that it is frustrating…

So filtering by MAC.
According to the that Mac whitelist for wifi post, the user have to set up this with iwpriv command each time… cra…
Why?
There are the functions in /lib/wifi/qcawifi.sh that should read the config and setup this already.

So i just copypasted the

    option macfilter 'allow'
    list maclist 'aa:bb:cc:dd:ee:ff'

sections from the /etc/config/wireless of the old router…

Ah… Does not work… Lol…

uci show wireless shows that the configuration is correct…

Well… Ok… This is forcing me to write my own cr.py parser-script.
path and name: /etc/init.d/iwmf
Content:

#!/bin/sh /etc/rc.common

START=99
USE_PROCD=1

service_triggers()
{
        procd_add_reload_trigger iwmf
}

start_service() 
{
        # Trying to catch all ifaces
        for i in $(uci -q -X show wireless | grep "ifname" | cut -d'.' -f1,2); do
        # Ignring disabled ifaces for $i
        if [ "$(uci -q get $i.disabled)" = "0" ]; then
                # Setting up variables for check for $i
                maclist="$(uci -q get $i.maclist)"
                # If there were configured the maclist for the iface, we proceed
                if [ -n "$maclist" ]; then
                        # Get the policy
                        macfilter="$(uci -q get $i.macfilter)" 
                        # Get ifname
                        ifname="$(uci -q get $i.ifname)"
                        # flush MAC list                                                            
                        iwpriv "$ifname" maccmd 3                                                   
                        # Send the MACs to the card
                        for mac in $maclist; do                                                     
                                iwpriv "$ifname" addmac "$mac"                                      
                        done
                        # Set up the policy on the card                                                                        
                        case "$macfilter" in
                                allow)
                                        iwpriv "$ifname" maccmd 1
                                ;;
                                deny)
                                        iwpriv "$ifname" maccmd 2
                                ;;
                                *)
                                        # So, there policy is not setted, but there is maclist... Why?..
                                        # May be the user turned off the policy, but keep the maclist?..
                                        # If that is true, we should flush the maclist on the iface
                                        iwpriv "$ifname" maccmd 3 
                                ;;
                        esac
                fi
        fi
        done
}

stop_service() 
{
        return 0
}

reload_service()                                
{                                                        
        start_service                          
}

restart_service()
{
        start_service
}

After copypasteing that snippet to the /etc/init.d/iwmf just enable that service by executing

 chmod +x /etc/init.d/iwmf
 /etc/init.d/iwmf enable
 /etc/init.d/iwmf start

Obviously you need to setup the maclist and macfilter policy in the /etc/config/wireless in the first [OpenWrt Wiki] Wi-Fi /etc/config/wireless

There was some problems… the helper functions like config_get from /lib/functions.sh and etc… I couldn’t get it to work. Therefore, I just parsed the output of the uci show from scratch…
And in the /lib/wifi/qcawifi.sh there is piece

 2235                 config_get macfilter "$vif" macfilter
 2236                 case "$macfilter" in
 2237                         allow)
 2238                                 iwpriv "$ifname" maccmd 1
 2239                         ;;
 2240                         deny)
 2241                                 iwpriv "$ifname" maccmd 2
 2242                         ;;
 2243                         *)
 2244                                 # default deny policy if mac list exists
 2245                                 [ -n "$maclist" ] && iwpriv "$ifname" maccmd 2
 2246                         ;;
 2247                 esac

The last # default deny policy if mac list exists... is not very wisefull. What if the user configured the maclist earlier, and then disabled the macfilter for a while?

Update.
Well… I have updated the script… it works pretty well when you restart it…

I kind of came close to the root of the problem.
The system file that sets up the maclist and macfilter in our case is /lib/wifi/qcawificfg80211.sh
I slightly modified it:

# diff -ub /lib/wifi/qcawificfg80211.0sh /lib/wifi/qcawificfg80211.sh
--- /lib/wifi/qcawificfg80211.0sh       2021-08-23 12:03:03.000000000 +0000
+++ /lib/wifi/qcawificfg80211.sh        2022-01-14 01:18:43.000000000 +0000
@@ -2520,25 +2520,26 @@
                [ -n "$stafwd" ] && "$device_if" "$ifname" stafwd "$stafwd"
 
                config_get maclist "$vif" maclist
+               logger "config_get maclist "$vif" maclist"
                [ -n "$maclist" ] && {
                        # flush MAC list
-                       "$device_if" "$ifname" maccmd 3
+                       "$device_if" "$ifname" maccmd 3 && logger ""$device_if" "$ifname" maccmd 3"
                        for mac in $maclist; do
-                               "$device_if" "$ifname" addmac "$mac"
+                               "$device_if" "$ifname" addmac "$mac" && logger "$device_if" "$ifname" addmac "$mac"
                        done
                }
 
                config_get macfilter "$vif" macfilter
                case "$macfilter" in
                        allow)
-                               "$device_if" "$ifname" maccmd 1
+                               "$device_if" "$ifname" maccmd 1 && logger " "$device_if" "$ifname" maccmd 1"
                        ;;
                        deny)
-                               "$device_if" "$ifname" maccmd 2
+                               "$device_if" "$ifname" maccmd 2 && logger " "$device_if" "$ifname" maccmd 2"
                        ;;
                        *)
                                # default deny policy if mac list exists
-                               [ -n "$maclist" ] && "$device_if" "$ifname" maccmd 2
+                               [ -n "$maclist" ] && "$device_if" "$ifname" maccmd 2 && logger ""$device_if" "$ifname" maccmd 2 "
                        ;;
                esac

for debugging.
and it executes, and fills up the maclist and sets macfilter policy:

Fri Jan 14 01:27:28 2022 user.notice root: config_get maclist cfg103579 maclist
Fri Jan 14 01:27:28 2022 user.notice root: cfg80211tool ath7 maccmd 3
Fri Jan 14 01:27:29 2022 user.notice root: cfg80211tool ath7 addmac **:**:**:**:**:**
Fri Jan 14 01:27:29 2022 user.notice root: cfg80211tool ath7 addmac  **:**:**:**:**:**
Fri Jan 14 01:27:29 2022 user.notice root:  cfg80211tool ath7 maccmd 1
Fri Jan 14 01:27:29 2022 kern.info kernel: [39315.110868] br-IOT: port 3(ath5) entered forwarding state
Fri Jan 14 01:27:30 2022 kern.warn kernel: [39315.531832] __mc_netlink_receive: Disable bridge snooping!
Fri Jan 14 01:27:30 2022 kern.warn kernel: [39316.162582] __mc_netlink_receive: Enable bridge snooping!
Fri Jan 14 01:27:31 2022 kern.info kernel: [39316.437388] 8021q: adding VLAN 0 to HW filter on device ath7
Fri Jan 14 01:27:31 2022 daemon.info hostapd: ath7: IEEE 802.11 driver had channel switch: freq=2462, ht=1, vht_ch=0x0, offset=-1, width=2 (40 MHz), cf1=2452, cf2=0
Fri Jan 14 01:27:32 2022 kern.err kernel: [39317.855581] cnss: Ignore double allocation for QDSS trace, current len 1

But right after that (I have monitored iwpriv ath$i getmac in cycle) something flushes the maclists on the all ifaces at once.

1 Like

Ok, I have learned something about helper functions… and rewrote the script /etc/init.d/iwmf

#!/bin/sh /etc/rc.common                                                                                                           
                                                                                                                                   
START=99                                                                                                                           
USE_PROCD=1                                                                                                                        
                                                                                                                                   
service_triggers()                                                                                                                 
{                                                                                                                                  
        procd_add_reload_trigger wireless                                                                                          
}                                                                                                                                  
                                                                                                                                   
start_service()                                                                                                                    
{                                                                                                                                  
        config_load wireless                                                                                                       
        # Trying to catch all ifaces                                                                                               
        for vif in $(uci -q -X show wireless | grep "ifname" | cut -d'.' -f2); do                                                  
        # Ignring disabled ifaces for $i                                                                                           
        local disabled                                                                                                             
        config_get_bool disabled "$vif" disabled                                                                                   
        if [ "$disabled" = "0" ]; then                                                                                             
                # Setting up variables for check for $vif                                                                          
                config_get maclist "$vif" maclist                                                                                  
                #If there were configured the maclist for the iface, we proceed                                                    
                if [ -n "$maclist" ]; then                                                                                         
                        # Get ifname                                                                                               
                        config_get ifname "$vif" ifname                                                                            
                        # flush MAC list                                                                                           
                        iwpriv "$ifname" maccmd 3                                                                                  
                        # Send the MACs to the card                                                                                
                        for mac in $maclist; do                                                                                    
                                iwpriv "$ifname" addmac "$mac"                                                                     
                        done                                                                                                       
                        # Get the policy                                                                                           
                        config_get macfilter "$vif" macfilter                                                                      
                        # Set up the policy on the card                                                                            
                        case "$macfilter" in                                                                                       
                                allow)                                                                                             
                                        iwpriv "$ifname" maccmd 1                                                                  
                                ;;                                                                                                 
                                deny)                                                                                              
                                        iwpriv "$ifname" maccmd 2                                                                  
                                ;;                                                                                                 
                                *)                                                                                                 
                                        # So, there policy is not setted, but there is maclist... Why?..                           
                                        # May be the user turned off the policy, but keep the maclist?..                           
                                        # If that is true, we should flush the maclist on the iface                                
                                        iwpriv "$ifname" maccmd 3                                                                  
                                        return 0                                                                                   
                                ;;                                                                                                 
                        esac                                                                                                       
                fi                                                                                                                 
        fi                                                                                                                         
        done                                                                                                                       
}                                                                                                                                  
                                                                                                                                   
stop_service()                                                                                                                     
{                                                                                                                                  
        return 0                                                                                                                   
}                                                                                                                                  
                                                                                                                                   
restart_service()                                                                                                                  
{                                                                                                                                  
        start_service                                                                                                              
}

For debugging purposes I replaced the iwpriv and cfg80211tool with wrappers to discover how and by whom they are run on the entire system.

In the first it turned out that the cfg80211tool ath# blockdfschan 1 wipes out all macs from the card…

Ok, I have moved the maclist and macfilter blocks to the bottom of the configuring function in the /lib/wifi/qcawificfg80211.sh So they are executed last in the queue.

But it didn’t helped.
There is still something other, that mess with maclist without executing cfg80211tool or iwpriv.
I can’t figure out what’s going on…

Another problem is the init-script with procd_add_reload_trigger wireless doesn’t reload on the wireless config changes. It certainly should, but doesn’t

You can edit /etc/config/wireless:

option macfilter ‘allow’
list maclist “11:22:33:44:55:66 aa:bb:cc:dd:ee:ff”

then wifi to make the configuration take effect.

And /etc/init.d/iwmf

if [ “$disabled” = “0” ]; then
—>You need to fix it: if [ “$disabled” = “0” -o “$disabled” = “” ]; then

Thanks for your reply, very appreciated.

What about triggering of the init-scripts reloading by procd on event of config file change?
I see this is completely broken.
At this time I did nasty hack - placed /etc/init.d/iwmf start at the end of wifi_reload_legacy and wifi_load functions in the /sbin/wifi file. It certainly will not survive upgrades.

You can edit /etc/config/wireless:

option macfilter ‘allow’
list maclist “11:22:33:44:55:66 aa:bb:cc:dd:ee:ff”

then wifi to make the configuration take effect.

Lizh, yes, I did that at the first.
And it actually works. I can see how /lib/wifi/qcawificfg80211.sh is configuring the maclfilter and fill maclists on the card. In log, and by monitoring it in cycle with i=0; while [ $i -lt 8] ; do iwpriv ath$i getmac; echo $((i++)) ;done

The main problem is after that something erases all maclists on the card at once.
The first culprit is cfg80211tool ath# blockdfschan 1 command that is executed after setting up the macfilter by /lib/wifi/qcawificfg80211.sh: It erases the maclists or resets the card, if I run this command after manually setting up the maclists by iwpriv.
I tried to turn off the blockdfschan, or change the commands queue in /lib/wifi/qcawificfg80211.sh so that maclists and macfilter sets up after the cfg80211tool ath# blockdfschan 1, No luck. Something continues resetting maclists on the card even without calling cfg80211tool or iwpriv at all (I am logging their runs by custom wrapper). So there is another culprit. May be hostapd… I dont know…

So at this time i can properly set up the maclist and macfilter only by custom script that is executed after a wifi load or reload is completed.

Updated the /etc/init.d/iwmf init-script with fixes from lizh

#!/bin/sh /etc/rc.common

START=99
USE_PROCD=1

service_triggers()
{
        procd_add_reload_trigger wireless
}

start_service()
{
        config_load wireless
        # Trying to catch all ifaces
        for vif in $(uci -q -X show wireless | grep "ifname" | cut -d'.' -f2); do
        # Ignoriing disabled ifaces for $i
        local disabled
        config_get_bool disabled "$vif" disabled
        if [ "$disabled" = "0" -o "$disabled" = "" ]; then
                # Setting up variables for check for $vif
                config_get maclist "$vif" maclist
                #If there were configured the maclist for the iface, we proceed
                if [ -n "$maclist" ]; then
                        # Get ifname
                        config_get ifname "$vif" ifname
                        # flush MAC list
                        iwpriv "$ifname" maccmd 3
                        # Send the MACs to the card
                        for mac in $maclist; do
                                iwpriv "$ifname" addmac "$mac"
                        done
                        # Get the policy
                        config_get macfilter "$vif" macfilter
                        # Set up the policy on the card
                        case "$macfilter" in
                                allow)
                                        iwpriv "$ifname" maccmd 1
                                ;;
                                deny)
                                        iwpriv "$ifname" maccmd 2
                                ;;
                                *)
                                        # So, there policy is not setted, but there is maclist... Why?..
                                        # May be the user turned off the policy, but keep the maclist?..
                                        # If that is true, we should flush the maclist on the iface
                                        iwpriv "$ifname" maccmd 3
                                        return 0
                                ;;
                        esac
                fi
        fi
        done
}

stop_service()
{
        return 0
}

restart_service()
{
        start_service
}

Hi akagane:

1,I have test it.‘cfg80211tool ath# blockdfschan 1’ don’t clear maclist.

2,/etc/init.d/iwmf
First,you need to implement a function:
reload_service(){xxxx}

Second,you need a notification event,example:
ubus call service event '{"type":"config.change","data":{"package":"wireless"}}'

# iwpriv ath1 getmac
ath1      getmac:**:**:**:**:**:**
                 **:**:**:**:**:**
# cfg80211tool ath1 blockdfschan 1
# iwpriv ath1 getmac
ath1      getmac:

Hi akagane:

very strange… I have reverted the firmware (v3.208), did the initial setup on the web admin panel (nothing special, just the password and the first SSID), and reproduced:

root@GL-AX1800:~# iwpriv ath0 maccmd 3
root@GL-AX1800:~# iwpriv ath0 getmac
ath0      getmac:root@GL-AX1800:~# 
root@GL-AX1800:~# iwpriv ath0 addmac 11:22:33:44:55:66
root@GL-AX1800:~# iwpriv ath0 getmac
ath0      getmac:11:22:33:44:55:66
root@GL-AX1800:~# iwpriv ath0 maccmd 1
root@GL-AX1800:~# iwpriv ath0 getmac
ath0      getmac:11:22:33:44:55:66
root@GL-AX1800:~# cfg80211tool ath0 blockdfschan 1
root@GL-AX1800:~# iwpriv ath0 getmac
ath0      getmac:root@GL-AX1800:~#

Same with cfg80211tool:

root@GL-AX1800:~# cfg80211tool ath0 maccmd 3
root@GL-AX1800:~# cfg80211tool ath0 addmac 11:22:33:44:55:66
root@GL-AX1800:~# cfg80211tool ath0 getmac
ath0    getmac:11:22:33:44:55:66
root@GL-AX1800:~# cfg80211tool ath0 maccmd 1
root@GL-AX1800:~# cfg80211tool ath0 getmac
ath0    getmac:11:22:33:44:55:66
root@GL-AX1800:~# cfg80211tool ath0 blockdfschan 1
root@GL-AX1800:~# cfg80211tool ath0 getmac
root@GL-AX1800:~#

Something weird is happening: some of ath# lose mac addresses from their maclists periodically without running iwpriv or cfg80211tool… the log shows that only hostapd works with these aths when it happens.

The following thing doesn’t work too.
It is there for history log and if somebody are obsessively trying the all of methods sequentially

$ diff -ub ./lib/wifi/hostapd.sh.0 ./lib/wifi/hostapd.sh
--- ./lib/wifi/hostapd.sh.0     2021-12-13 11:19:05.000000000 +0300
+++ ./lib/wifi/hostapd.sh       2022-01-22 20:39:45.582390348 +0300
@@ -1125,6 +1125,40 @@
                sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' /var/run/hostapd_cred_tmp.conf | xargs printf >> /var/run/hostapd_cred_$device.bin
 }
 
+hostapd_config_macfilter() {
+       config_load wireless
+       local vif="$1"
+       local var="$2"
+       local maclist nmaclist macfilter
+       config_get maclist "$vif" maclist
+       #If there was configured the maclist for the iface, we proceed
+       if [ -n "$maclist" ]; then
+               for mac in $maclist; do
+                       append nmaclist "$mac" "$N"
+               done
+               # Get the policy
+               config_get macfilter "$vif" macfilter
+               # Set up the maclist
+               case "$macfilter" in
+                       allow)
+                               echo -n "$nmaclist" > "/var/run/hostapd-$ifname.accept"
+                               append "$var" "macaddr_acl=0" "$N"
+                               append "$var" "accept_mac_file=/var/run/hostapd-$ifname.accept" "$N"
+                       ;;
+                       deny)
+                               echo -n "$nmaclist" > "/var/run/hostapd-$ifname.deny"
+                               append "$var" "macaddr_acl=0" "$N"
+                               append "$var" "deny_mac_file=/var/run/hostapd-$ifname.deny" "$N"
+                       ;;
+                       *)
+                               # So, there policy is not setted, but there is maclist... Why?..
+                               # May be the user turned off the policy, but keep the maclist?..
+                               # If that is true, we should do nothing.
+                               return 0
+                       ;;
+               esac
+       fi
+}
 
 hostapd_setup_vif() {
        local vif="$1" && shift
@@ -1528,6 +1562,8 @@
                config_get_bool hidden "$vif" hidden 0
                append hostapd_cfg "ignore_broadcast_ssid=$hidden" "$N"
 
+               hostapd_config_macfilter "$vif" hostapd_cfg
+
        fi  #end of nl80211
 
        hostapd_set_bss_options hostapd_cfg "$vif"

Hmm just a thought but could it be something in the mwan3 default script that triggers something?

I do know the default script is doing some stuff to but im not sure if it does something related to iwpriv I could’t check since im not on a pc.