Inability to Implement Per-User Authentication Exceptions With a Global RADIUS authentication

10 views
Skip to first unread message

malformed packet

unread,
Jun 16, 2026, 6:06:48 AM (4 days ago) Jun 16
to Event-Driven Servers
Hi All,

I was trying to utilize the LDAP (to fetch group membership) and Radius (to Authenticate with MFA) based authentication.... Both are working fine after a lot of configuration changes but unable to fulfill the specific usecase and that is to bypass radius authentication and use AD Authentication for few specific users while rest will be authenticated via radius


Sample config - 

# ==============================================================================
# 1. DAEMON & NETWORK CONNECTION CONFIGURATION
# ==============================================================================
id = spawnd {
        listen = { address = 0.0.0.0 port = 49 }
        spawn = {
                instances min = 1
                instances max = 32   # Safely expanded to support multi-user login holds
        }
        background = no
}

# ==============================================================================
# 2. MAIN CORE SERVICE REGION (Unified Modern Architecture Blueprint)
# ==============================================================================
id = tac_plus-ng {

        # SECURITY LOCKDOWN: Restrict inbound processing strictly to standard TACACS+ TCP.
        aaa.protocol.allowed = tacacs.tcp

        # ----------------------------------------------------------------------
        # LOGGING ARCHITECTURE
        # ----------------------------------------------------------------------
        log accesslog { destination = /var/log/tacacs/access.log }
        log authorlog { destination = /var/log/tacacs/authorization.log }
        log acctlog   { destination = /var/log/tacacs/accounting.log }
        log connlog   { destination = /var/log/tacacs/connection.log }

        access log        = accesslog
        authorization log = authorlog
        accounting log    = acctlog
        connection log    = connlog

        # ----------------------------------------------------------------------
        # GLOBAL BACKEND ROUTING BINDINGS
        # ----------------------------------------------------------------------
        user backend  = mavis
        login backend = mavis
        pap backend   = mavis

        # ----------------------------------------------------------------------
        # THE MODERN UNIFIED MAVIS GROUPS & EXTERNAL FILTERS PIPELINE
        # ----------------------------------------------------------------------
        # This native optimization handles group filtering natively on execution,
        # stripping long AD paths down into clean strings before hitting rulesets.
#       mavis module = groups {
#               groups filter = /^(MA-RW|MA-RO|F5-OP|WLC|MA-NCM_Backup)$/i
#       }

        mavis module = external {
                # Sequential Execution: RADIUS authenticates first -> LDAP resolves groups second
#                default = yes
                exec = /usr/local/tacacs/lib/mavis/mavis_tacplus_radius.pl

                # ======================================================================
                # RADIUS PARAMETERS
                # ======================================================================
                setenv RADIUS_HOST         = "10.86.32.46:1812"
                setenv RADIUS_SECRET       = "aY9cort29rhRiyD1TbR3WbC7Vby8oOcxOT2UNPv3"
                setenv RADIUS_AUTH_ONLY    = "1"
                setenv RADIUS_DICT         = "/usr/share/freeradius/dictionary"
                setenv RADIUS_TIMEOUT      = "60"

                # Structural flags to keep variables safe between script handoffs
                setenv TACTYPE             = "PAP"
                setenv MAVIS_PASS          = "1"
                setenv MAVIS_AUTO_PASSWORD = "1"
                }
                # ======================================================================
                # LDAP / ACTIVE DIRECTORY PARAMETERS
                # ======================================================================
        mavis module = external {
                # Sequential Execution: RADIUS authenticates first -> LDAP resolves groups second
                exec = /usr/local/tacacs/lib/mavis/mavis_tacplus_ldap.pl

                setenv LDAP_SERVER_TYPE    = "microsoft"
                setenv LDAP_HOSTS          = "redacted"
                setenv LDAP_SCOPE          = "sub"
                setenv LDAP_BASE           = "dc=test,dc=local"

                # Valid positional substitution token matching your backend release version
                setenv LDAP_FILTER         = "(sAMAccountName=%s)"
                setenv LDAP_USER           = "t...@test.local"
                setenv LDAP_PASSWD         = "modified"
                setenv USE_TLS             = "0"
#               setenv LDAP_GROUP_ATTR     = "memberOf"
                setenv FLAG_USE_MEMBER     = "1"
#               setenv LDAP_GROUP_REGEX    = "(?i)^cn=([\s\w-]+),.*"
                setenv TACACS_GROUP_PREFIX = "(MA-|F5-|WLC)"
                setenv LDAP_GROUP_DEFAULT  = "MA-RO"
                setenv MAVIS_DEBUG = "1"
                setenv MAVIS_LDAP_DEBUG = "1"
                setenv MAVIS_LDAP_TRACE = "1"
        }

        # ----------------------------------------------------------------------
        # GLOBAL DYNAMIC AUTHENTICATION ROUTING RULE
        # ----------------------------------------------------------------------
        user = DEFAULT {
                password login = mavis
                password pap   = mavis
        }

        # ----------------------------------------------------------------------
        # NETWORK ACCESS SERVER (NAS) / DEVICE DEFINITIONS
        # ----------------------------------------------------------------------
        device CE-TACACs-Device-Group {
                key = "modified"
                welcome banner = "Welcome to the Network Management Domain\n"

                device network_devices {
                        address = 0.0.0.0/0
                }
        }

        # ----------------------------------------------------------------------
        # EXPLICIT GROUP OBJECT DECLARATIONS
        # ----------------------------------------------------------------------
        group "MA-RW" { }
        group "MA-RO" { }
        group "F5-OP" { }
        group "WLC" { }
        group "MA-Backup" { }

        # ----------------------------------------------------------------------
        # SHELL & COMMAND ACCESS PROFILES
        # ----------------------------------------------------------------------
        profile prof-MA-RW {
                script {
                        if (service == shell) {
                                set priv-lvl = 15
                                set cisco-av-pair = "shell:domains = all/admin/,common// admin"
                                permit
                        }
                        if (service == junos-exec) { set local-user-name = remote-su; permit }
                        if (service == fortigate) { set memberof = FWA-MGMT-RW; set admin_prof = super_admin; permit }
                        if (service == ciscowlc) { set role1 = ALL; permit }
                        if (service == ppp && protocol == ip) {
                                set F5-LTM-User-Info-1 = adm; set F5-LTM-User-Console = 1; set F5-LTM-User-Role = 0; set F5-LTM-User-Partition = all; permit
                        }
                        if (service == PaloAlto) {
                                set PaloAlto-Admin-Role = superuser; set PaloAlto-Panorama-Admin-Role = superuser; set priv-lvl = 1; permit
                        }
                }
        }

        profile prof-MA-RO {
                script {
                        if (service == shell) {
                                set priv-lvl = 15
                                if (cmd == "" || cmd =~ /^show/ || cmd == "ping" || cmd == "exit" || cmd == "traceroute" || cmd =~ /^terminal/) {
                                        permit
                                }
                                message = "Read-Only Access: Configuration commands are denied."
                                deny
                        }
                        if (service == ciscowlc) { set role1 = LOBBY; permit }
                        if (service == ppp && protocol == ip) {
                                set F5-LTM-User-Info-1 = guest; set F5-LTM-User-Console = 1; set F5-LTM-User-Role = 700; set F5-LTM-User-Partition = all; permit
                        }
                        if (service == PaloAlto) {
                                set PaloAlto-Admin-Role = readonly; set PaloAlto-Panorama-Admin-Role = readonly; set priv-lvl = 1; permit
                        }
                }
        }

        profile prof-MA-Backup {
                script {
                        if (service == shell) {
                                set priv-lvl = 15
                                if (cmd == "" || cmd =~ /^terminal length/ || cmd =~ /^show (running|startup)-config/ || cmd == "end" || cmd == "exit") {
                                        permit
                                }
                                message = "Backup Access Only: Only specific show and sync commands permitted."
                                deny
                        }
                        if (service == ciscowlc) { set role1 = LOBBY; permit }
                        if (service == ppp && protocol == ip) {
                                set F5-LTM-User-Info-1 = guest; set F5-LTM-User-Console = 1; set d= 700; set F5-LTM-User-Partition = all; permit
                        }
                        if (service == PaloAlto) {
                                set PaloAlto-Admin-Role = readonly; set PaloAlto-Panorama-Admin-Role = readonly; set priv-lvl = 1; permit
                        }
                }
        }

        # ----------------------------------------------------------------------
        # NETWORK ASSET LISTS (NAC)
        # ----------------------------------------------------------------------
        net backup_nac {
                address = X.X.X.X/32
        }

        # ----------------------------------------------------------------------
        # AUTHORIZATION POLICY RULESET (Strict Production Matching)
        # ----------------------------------------------------------------------
        ruleset {
                rule {
                        script {
                                # 1. Handle transit restricted exceptions safely using blocks
                                if (user == aaalee || user == pqiu || user == aarsharma) {
                                        if (device == network_devices) { profile = prof-MA-RW permit }
                                        deny
                                }
                                # 2. Process standard team users inside a safe 'else' container block
                                else {
                                        # Validated target syntax matches clean group strings extracted by MAVIS
                                        if (memberof =~ /^CN=MA-RW,/) { profile = prof-MA-RW permit }
                                        if (memberof =~ /^CN=MA-RO,/) { profile = prof-MA-RO permit }
                                        if (memberof =~ /^CN=F5-OP,/) { profile = prof-MA-RO permit }
                                        if (memberof =~ /^CN=WLC,/) { profile = prof-MA-RO permit }

                                        # Automated backup tools subnet restriction rule
                                        if (memberof =~ /^CN=MA-Backup,/) {
                                                if (nac == backup_nac) { profile = prof-MA-Backup permit }
                                                deny
                                        }
                                }
                        }
                }
        }
}


Please suggest

Marc Huber

unread,
Jun 17, 2026, 12:06:38 PM (3 days ago) Jun 17
to event-driv...@googlegroups.com

Hi,

please git pull.and rebuild. After that, the following should work:

mavis module radius = external {
...
    script in { if (custom_0 == "skip_mfa") skip }
}

mavis module ldap = external {
...
}

login backend = mavis prefetch
pap backend = mavis prefetch

script {
    if (member == no_mfa) # or whatever you condition you need for skipping RADIUS
        custom_0 = "skip-mfa"
}

Cheers,

Marc

--
You received this message because you are subscribed to the Google Groups "Event-Driven Servers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to event-driven-ser...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/event-driven-servers/65f4328b-1894-4ae5-bd2a-97c63f3d0b59n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages