Cisco IOS / IOS-XE
This page covers administrative access — engineers logging in to the CLI — on Cisco IOS and IOS-XE. It is the device-side counterpart to TACACS+ and RADIUS.
For endpoint access control (802.1X and MAB) on the same platforms, see Build an 802.1X lab, which walks the switch side end to end. The NAC section below records what differs between software trains, and what Taranac sends to a Cisco device.
Verified on
Section titled “Verified on”| Platform | Software | What was verified |
|---|---|---|
Cisco IOSv (vios_l2) | 15.2 | TACACS+ login, enable, command authorization and accounting at levels 0/1/15; RADIUS administrative login with exec authorization and accounting |
Cisco IOL (X86_64BI_LINUX_L2) | 17.12.1 (Dublin) | TACACS+ login, enable, command authorization and accounting at levels 0/1/15 |
Both are virtual platforms. The AAA configuration below is not platform-specific — it is the same on Catalyst, ISR and Nexus-adjacent IOS-XE gear — but output formats differ slightly between trains, and those differences are called out where they matter.
The good news for anyone running a mixed estate: the TACACS+ device-administration
configuration is identical on 15.x and 17.x. The named tacacs server block replaced
the legacy tacacs-server host global on 15.x already, so one template covers both.
Device administration over TACACS+
Section titled “Device administration over TACACS+”This is the standard shape: Taranac authenticates the login, decides the privilege level, authorizes every command, and records everything.
aaa new-model!! ── The server and its group ────────────────────────────────────tacacs server TARANAC-1 address ipv4 10.0.0.20 key <TACACS_SECRET> timeout 30!aaa group server tacacs+ TARANAC server name TARANAC-1!! ── Authentication ──────────────────────────────────────────────aaa authentication login default group TARANAC localaaa authentication login CONSOLE localaaa authentication enable default group TARANAC enable!! ── Authorization ───────────────────────────────────────────────aaa authorization config-commandsaaa authorization exec default group TARANAC localaaa authorization commands 0 default group TARANAC localaaa authorization commands 1 default group TARANAC localaaa authorization commands 15 default group TARANAC local!! ── Accounting ──────────────────────────────────────────────────aaa accounting exec default start-stop group TARANACaaa accounting commands 0 default start-stop group TARANACaaa accounting commands 1 default start-stop group TARANACaaa accounting commands 15 default start-stop group TARANAC!! ── Source the packets from the registered address ──────────────ip tacacs source-interface Vlan1!line con 0 login authentication CONSOLE privilege level 15line vty 0 4 login authentication default transport input sshDo not save it yet. Apply it to the running configuration, then verify a fresh
login before write memory. While the startup configuration is still clean, a console
reload undoes a lockout in one step. Once a new session logs in and lands where it
should, save it: a switch that reloads with half of this missing fails in ways that look
nothing like a missing configuration.
Every privilege level needs its own line
Section titled “Every privilege level needs its own line”This is the single most misunderstood part of Cisco AAA, and it fails silently in the permissive direction, which is the worst way for a security control to fail.
aaa authorization commands and aaa accounting commands take one privilege level per
line. There is no all keyword, no range, and no wildcard. IOS will not warn you about
levels you did not list — it simply never sends those commands to Taranac.
Levels 0, 1 and 15 cover the stock IOS command set and are what the example
configures:
| Level | What lives there |
|---|---|
0 | enable, disable, exit, help, logout — five commands, easy to forget, and enable is not a command you want unaudited |
1 | User EXEC — the read-only show commands an operator has by default |
15 | Privileged EXEC and configuration mode — everything else |
If you use custom privilege levels, you must add a line for each one. Any deployment
that has run privilege exec level 7 … to build a tiered operator role needs
aaa authorization commands 7 and aaa accounting commands 7 as well. Otherwise the
tier you carefully built is the one tier nobody is checking. The rule is simply: every
privilege level in use on the device needs both lines.
aaa authorization config-commands is the related trap one level up. Without it,
commands typed in configuration mode are not sent for authorization even when
aaa authorization commands 15 is present — exec-mode commands are checked, config-mode
commands sail through. Since configuration mode is where the damage happens, the line
belongs in every deployment that authorizes commands at all.
Keep a way back in
Section titled “Keep a way back in”Every line in the block above routes authentication to a server that can become unreachable. Two safeguards make that survivable, and both are in the example:
- The
localfallback keyword.group TARANAC localtries Taranac first and falls back to the local user database only when the server does not answer. It does not fall back when Taranac answers with a reject — a denied login stays denied, which is what you want. This requires a local account to actually exist: keep ausername … privilege 15 secret …on the device. - A separate console method list.
aaa authentication login CONSOLE localbound toline con 0keeps the console on local authentication permanently. When the network is down and the TACACS+ server is unreachable, the console is how you get in. A device whose console also points atdefaultcan lock you out completely. privilege level 15on that same console line. Without it the rescue account gets you a prompt and nothing else — see the box below.
aaa authentication enable default group TARANAC enable ends in the enable keyword,
falling back to the locally configured enable secret. That fallback fires only when the
server is unreachable. A reject is a valid answer, and no local or enable keyword
rescues you from one.
Source interface and NAS-IP
Section titled “Source interface and NAS-IP”ip tacacs source-interface Vlan1 pins the source address of TACACS+ packets to that
interface’s IP. That address is what Taranac matches against the registered device.
Leave it out and IOS picks the egress interface closest to the server, which is usually right — until a routing change, a second uplink or an SVI renumbering makes it wrong. The failure is unhelpful: Taranac sees a request from an unregistered client and drops it without logging a policy decision, so the device reports a timeout and falls back to local while Taranac’s logs show nothing at all. Pin it explicitly.
The same applies to RADIUS via ip radius source-interface.
Timeouts and push MFA
Section titled “Timeouts and push MFA”The example sets timeout 30, not the familiar 5 seconds. That is deliberate.
When a user is enrolled in push MFA, Taranac holds the AAA exchange open while it
sends a push to their phone and waits for them to approve it. The device must stay
willing to wait for a human. At timeout 5 the switch gives up long before anyone can
reach into a pocket, and the login fails over to the local database — which looks exactly
like a server outage.
The effective approval window is the smaller of the device timeout and Taranac’s own server-side cap. Raising one side alone changes nothing; if you want to give admins more time to tap “approve”, raise both together.
For TACACS+ this is clean — the TCP connection simply stays open for the duration. See the RADIUS section for why the UDP case behaves differently.
Numbered AV-pairs — inacl#1, route#1
Section titled “Numbered AV-pairs — inacl#1, route#1”Cisco’s PPP and interface authorization families carry their index inside the attribute
name: inacl#1, outacl#1, route#1, interface-config#1, rte-fltr-in#1. They go on
a TACACS+ profile as raw AV-pairs, against the service the device actually asks for
(ppp, slip) rather than shell.
Taranac accepts # anywhere in an attribute name except as the first character. #
is tac_plus-ng’s comment character, but only when it opens a token: set inacl#1 = "…"
parses, while set #attr = "…" comments out the rest of its own line and stops the whole
configuration from loading. That is why the ban stays exactly where it is — one bad
attribute name would take AAA down for every device, not just the profile carrying it.
Verify it
Section titled “Verify it”show tacacs is the first stop. The output differs between trains, and 17.x is
considerably more useful:
SW#show tacacs
Tacacs+ Server - public : Server name: TARANAC-1 Server address: 10.0.0.20 Server port: 49 Socket opens: 875 Socket closes: 875 Socket aborts: 0 Socket errors: 0 Socket Timeouts: 0 Failed Connect Attempts: 0 Total Packets Sent: 938 Total Packets Recv: 938Health has to be inferred from the counters. Socket opens matching Socket closes with
zeros across aborts, errors and timeouts is a healthy server. Any movement in
Socket Timeouts or Failed Connect Attempts means reachability trouble — wrong address,
wrong port, or a firewall in the path.
SW#show tacacs
Tacacs+ Server - public : Server name: TARANAC-1 Server address: 10.0.0.20 Server port: 49 Socket opens: 50409 Socket closes: 50404 Socket aborts: 0 Socket errors: 0 Socket Timeouts: 0 Failed Connect Attempts: 0 Total Packets Sent: 99965 Total Packets Recv: 99964 Server Status: AliveContinous Authc fail count: 0Continous Authz fail count: 017.x adds three lines worth having. Server Status: Alive is the direct reachability
answer, and the two consecutive-failure counters separate a reachability problem from a
policy problem: a climbing Continous Authz fail count with Server Status: Alive
means the server is answering fine and denying you — go look at the policy rules and
command sets, not at the network. (The spelling is Cisco’s.)
Then confirm the whole chain end to end:
test aaa group TARANAC <user> <password> legacy— authenticates without risking your session, and tells you whether the secret and policy are right.- Log in from a second session and run something your policy should deny. A denial arriving from Taranac is the only real proof that command authorization is live; a successful login proves only authentication.
- Check the accounting records in Taranac. Commands appearing under the right user, with the right privilege level, confirms the accounting lines took effect — and is how you catch a missing privilege level before an auditor does.
Device administration over RADIUS
Section titled “Device administration over RADIUS”Some estates standardise on RADIUS for administrative login. IOS supports it, with real
limitations. Note the named method list (VTY) rather than default — it keeps the
console untouched, which serves the same rescue purpose as the CONSOLE list above.
aaa new-model!radius server TARANAC-1 address ipv4 10.0.0.20 auth-port 1812 acct-port 1813 timeout 30 retransmit 1 key <RADIUS_SECRET>!aaa group server radius TARANAC-R server name TARANAC-1!aaa authentication login VTY group TARANAC-R localaaa authorization exec VTY group TARANAC-R localaaa accounting exec VTY start-stop group TARANAC-R!! enable has one method list on IOS, and it is always 'default'aaa authentication enable default group TARANAC-R enable!ip radius source-interface Vlan1radius-server attribute 6 on-for-login-authradius-server attribute 8 include-in-access-reqradius-server attribute 25 access-request include!line con 0 ! no AAA here — local console rescueline vty 0 4 login authentication VTY authorization exec VTY accounting exec VTY transport input sshTaranac returns the privilege level as a Cisco AV-pair, shell:priv-lvl=15, rendered from
a RADIUS profile — see RADIUS profiles. aaa authorization exec
is what makes the device apply it; without that line the user authenticates and lands at
privilege 1 regardless of what the profile said.
A profile that leaves the timeouts blank still sends them. The built-in Cisco IOS /
IOS-XE RADIUS template — vendor ID 9, Cisco-AVPair as VSA 1, one templated
shell:priv-lvl={level} attribute — defaults to Service-Type = Login-User,
Session-Timeout = 3600 and Idle-Timeout = 600, and the renderer falls back to those
whenever the profile itself carries nothing. Both seeded profiles, General Full Access
(priv 15) and General Read-Only (priv 1), inherit them. Set the timeouts explicitly on
the profile if an hour is not what an administrative session should get.
The three radius-server attribute lines are worth keeping. They make the switch include
Service-Type on login authentication, Framed-IP-Address, and the Class attribute in
accounting — the last one is what lets Taranac correlate an accounting record back to the
session that produced it.
Enable over RADIUS
Section titled “Enable over RADIUS”RADIUS has no privilege-escalation exchange in any RFC, but IOS sends one anyway.
enable at a privilege-1 prompt produces an ordinary Access-Request whose User-Name is
the synthetic $enab<N>$ — there is no person in it at all. Three things were measured on
IOSv 15.2 and are in no Cisco document:
- The name generalises.
enable 7andenable 5send$enab7$and$enab5$, not only$enab15$. Service-Typedoes not carry the level. It isAdministrative-User (6)for every level; the level exists only inside the username.- A bare Access-Accept is enough. The switch reached privilege 15 on a reply carrying no vendor attributes whatsoever.
Since 1.2.5 Taranac answers these instead of rejecting them as an account nobody
created. The password is a single global enable password on Settings → RADIUS,
accepted for every requested level. Because the request names nobody, there is no user, no
group, no policy rule and nothing for MFA to apply to — which is the argument for the main
path: grant the level at login through shell:priv-lvl, where the person is known and
MFA works. The mechanism, the log badge and the rejection reasons are on
RADIUS → Privilege escalation (enable).
Cisco IOS / IOS-XE is in the family this covers, alongside Cisco Business, H3C Comware 7 and Eltex ESR. Cisco ASA is not — it sends the operator’s real name for an escalation, so Taranac answers it as an ordinary login and always did.
Push MFA over RADIUS deserves one note. RADIUS is UDP, so the instinct is to raise
retransmit to widen the approval window. It does not work that way: the push budget is
capped on the server side, and retransmits arriving during the wait are deduplicated and
answered from cache — they neither extend the window nor trigger a second push. The cap is
radius.max_request_time, 30 seconds by default, which is why the device example uses
timeout 30. Raise the two together; leave retransmit low.
Verify with show aaa servers, which reports RADIUS only — TACACS+ never appears there,
which is why a TACACS-only device returns nothing at all:
SW#show aaa servers
RADIUS: id 1, priority 1, host 10.0.0.20, auth-port 1812, acct-port 1813 State: current UP, duration 674590s, previous duration 0s Dead: total time 0s, count 0 Authen: request 3, timeouts 0, failover 0, retransmission 0 Response: accept 3, reject 0, challenge 0 Response: unexpected 0, server error 0, incorrect 0, time 131ms Account: request 5, timeouts 0, failover 0, retransmission 0 Request: start 3, interim 0, stop 2 Response: start 3, interim 0, stop 2State: current UP with Dead: count 0 is what healthy looks like. The challenge
counter is the one to watch when MFA is in play — a non-zero value means Access-Challenge
exchanges are happening, which is the multi-step authentication working as intended.
NAC on this platform
Section titled “NAC on this platform”The switch-side 802.1X and MAB configuration for Cisco IOS is covered step by step in
Build an 802.1X lab — global plumbing, the NAC server group on
ports 1814/1815, the CoA listener, and the access-port template with authentication open as monitor mode. It is not repeated here.
What belongs on this page is the part that changed between software trains. IOS 15’s
authentication port commands and IOS-XE’s session manager are different generations of
the same feature, and the verification commands are not interchangeable:
| Task | IOS 15.x | IOS-XE 17.x |
|---|---|---|
| List sessions | show authentication sessions | show access-session |
| One port in detail | show authentication sessions interface Gi1/1 details | show access-session interface Gi1/1 details |
| Port configuration style | authentication commands on the interface | IBNS 2.0 — policy-map type control subscriber |
On 17.x, show authentication sessions is rejected outright as an invalid command rather
than deprecated with a hint, which sends people looking for a configuration fault that
does not exist. If a session list command errors out, try the other spelling before
assuming the port is broken.
Both trains accept the same Taranac-side authorization results, since those arrive as RADIUS attributes rather than CLI. What Taranac sends for a Cisco device:
| Profile setting | Attributes sent |
|---|---|
| VLAN | Tunnel-Type = VLAN, Tunnel-Medium-Type = IEEE-802, Tunnel-Private-Group-ID = <vlan> |
| Named ACL | Filter-Id = <name> — the ACL must already exist on the switch |
| Downloadable ACL | one Cisco-AVPair += ip:inacl#<rule> per rule, <rule> being the text you typed |
| URL redirect | Cisco-AVPair += url-redirect=<url> and url-redirect-acl=<acl> |
| Session timeout | Session-Timeout, Termination-Action = RADIUS-Request |
Cisco IOS / IOS-XE is the only vendor in the shipped dictionary that declares
url_redirect at all, which makes the captive-portal redirect flow a Cisco capability out
of the box. Downloadable ACLs are declared by four — Cisco IOS, Cisco NX-OS, Juniper and
Huawei; everywhere else the inline rules are skipped and the render warns about it.
For CoA, Cisco IOS / IOS-XE is the best-covered platform in the dictionary. It is one of
only three vendors — with Cisco NX-OS and Juniper — whose re-authentication is a
native CoA-Request (subscriber:command=reauthenticate plus
subscriber:reauthenticate-type=last); every other vendor falls back to a Disconnect and
waits for the endpoint to come back on its own. Bounce port
(subscriber:command=bounce-host-port) is shared with Aruba, Extreme EXOS and Ruckus ICX;
port shutdown (subscriber:command=disable-host-port) only Cisco and Ruckus ICX
declare at all. A VLAN change is a CoA too, but it carries the Tunnel-* triplet
rather than a subscriber:command.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause |
|---|---|
| Login hangs, then succeeds with local credentials | Server unreachable. Check Socket Timeouts / Failed Connect Attempts in show tacacs, or State in show aaa servers. |
| Login rejected, and Taranac logs show nothing | The request never arrived as a known client — source address does not match the registered device (ip tacacs source-interface), or the secret does not match. Unknown clients are dropped without a policy decision. |
| Login works, user lands at privilege 1 | Missing aaa authorization exec, or the matched policy rule returns no profile. |
| Push MFA always denies | Device timeout too low. Raise it to 30 s and match the server-side cap. |
| Commands run that policy should deny | No aaa authorization commands line for that privilege level, or aaa authorization config-commands missing for config mode. |
| Commands missing from the audit trail | No aaa accounting commands line for that privilege level. |
| Locked out after applying AAA | No CONSOLE method list, or no local account for the local fallback. Recover via console or password recovery — or, if you have not saved yet, by reloading. |
Console rescue logs in, but enable is denied | Expected under aaa new-model: the console lands at privilege 1 and enable asks the server for $enab15$. Bind privilege level 15 to line con 0. |
| Enable over RADIUS rejected as an unknown user | Before 1.2.5 $enab<N>$ was looked up as an account. On 1.2.5+ set the global enable password on Settings → RADIUS: a wrong one is reported as enable_bad_password, an unset one as enable_not_configured. |
Saving a TACACS+ profile holding inacl#1 returns 422 | Releases 1.2.2 – 1.2.7 banned # in an attribute name. Fixed in 1.2.8. |
| dACL is accepted but the rules do nothing | The sequence number is missing — the rule must start with <n>=, since Taranac appends it to ip:inacl# verbatim. |
show authentication sessions is invalid | IOS-XE 17.x — use show access-session. |
show aaa servers returns nothing | Expected on a TACACS-only device. Use show tacacs. |
Related
Section titled “Related”- Network devices — registering the device and its secrets
- TACACS+ — profiles, command sets, the enable chain
- RADIUS — templates and reply attributes
- AAA policy — the rules that decide what a login gets
- Build an 802.1X lab — the NAC side of this platform