Back to blog

Cisco / IOS  ·  Security  ·  September 2026

Cisco IOS
Device-Admin AAA

A local username on every box doesn't scale and doesn't audit. AAA centralises device login against TACACS+ or RADIUS — one place to add or revoke an engineer, per-command control, and an accounting trail of who typed what. This is admin access to the gear itself, not 802.1X port authentication for endpoints. The MikroTik twin is login via RADIUS & User Manager.

Cisco IOS AAA TACACS+ RADIUS Hardening

Local users are fine for one lab switch. Across a fleet they rot: a leaver's account lingers on forty boxes, nobody can say who changed the ACL at 2am, and rotating a shared password means a maintenance window. AAA — Authentication, Authorization, Accounting — moves all three off the box to a central server (TACACS+ or RADIUS) so identity, permissions and audit live in one place.

TACACS+ (Cisco's protocol, TCP/49) is the right tool for device admin: it encrypts the whole payload and does per-command authorization and accounting. RADIUS (UDP/1812-1813) authenticates fine and can hand back a privilege level, but its command-level control is coarse. Use TACACS+ for the network team; RADIUS is the fallback when that's all you have (or you're already running it for 802.1X). The golden rule throughout: never remove your local escape hatch.

Prerequisites

01

Turn On AAA — With a Local Escape Hatch First

The instant you type aaa new-model the login behaviour changes. Build the local fallback and open a second session before you point anything at a server.

IOS — safety net before anything else
# 1. A real local admin that survives a dead AAA server.
R1(config)# username breakglass privilege 15 secret S0me-Str0ng-Pass

# 2. Enable AAA. Login prompts now follow method lists, not the vty password.
R1(config)# aaa new-model

# 3. Keep an enable secret so 'enable' still works if AAA is unreachable.
R1(config)# enable secret An0ther-Str0ng-Pass
⚠ Gotcha — This Is the Command That Locks People Out

More engineers have been locked out by AAA than by any other feature. Two rules make it safe: (1) every method list ends in local (or enable) so a dead server falls back to the box, and (2) you keep a second SSH session open the whole time — if the new config breaks login, that session is still authenticated and can undo it. Test from a new session; never from your only one.

02

Point at TACACS+ and Build the Method Lists

Define the server, group it, then attach method lists for authentication (who are you), authorization (what may you do), and accounting (what did you do). Each list falls back to local.

IOS — TACACS+ server + default method lists
# Define the server (IOS 15.x+ syntax) and the shared secret.
R1(config)# tacacs server TAC-1
R1(config-server-tacacs)# address ipv4 10.0.0.10
R1(config-server-tacacs)# key 0 SharedSecretHere   # stored as type 7 — obfuscated, not safe
R1(config)# aaa group server tacacs+ TAC-GRP
R1(config-sg-tacacs+)# server name TAC-1

# Authentication: try the group, fall back to the LOCAL user database.
R1(config)# aaa authentication login default group TAC-GRP local
R1(config)# aaa authentication enable default group TAC-GRP enable

# Authorization: exec = may you open a shell + what privilege you land in.
R1(config)# aaa authorization exec default group TAC-GRP local

# Source AAA from a stable interface (loopback) so the server sees one IP.
R1(config)# ip tacacs source-interface Loopback0
💡 Pro Tip — Source-Interface = Fewer Mystery Failures

If the router picks a different egress IP per packet, the AAA server's client entry won't match and auth silently fails. Pin ip tacacs source-interface (and ip radius source-interface) to a loopback, and register that exact IP on the server. Same discipline as pinning your syslog/SNMP source.

03

Per-Command Authorization & Accounting

This is why TACACS+ exists: authorize each command against the server and log every one. It's also the fastest way to lock the team out — layer it on only once login works.

IOS — command control + audit trail
# Authorize privilege-15 commands against the server (fall back to local).
R1(config)# aaa authorization commands 15 default group TAC-GRP local

# Accounting: record who ran what, and every exec (shell) session.
R1(config)# aaa accounting commands 15 default start-stop group TAC-GRP
R1(config)# aaa accounting exec default start-stop group TAC-GRP

# By default the CONSOLE bypasses authorization. Turn it on explicitly
# only after you have proven console local login still works.
R1(config)# aaa authorization console
⚠ Gotcha — Command Authorization Fails Closed

If aaa authorization commands 15 points only at the server and the server is unreachable, privileged commands are denied — you can log in but not do anything. The trailing local helps only if a matching local privilege is defined. Roll command authorization out in monitor-mode thinking: prove the server returns the right command sets for your groups before you rely on it, and keep breakglass at privilege 15 so it's never subject to the server's command rules.

04

RADIUS — When That's What You Have

RADIUS authenticates admins and can set a privilege level via a vendor attribute, but it can't do clean per-command control. Good enough for read-mostly access or when you're already running it.

IOS — RADIUS admin login + privilege via AV-pair
R1(config)# radius server RAD-1
R1(config-radius-server)# address ipv4 10.0.0.11 auth-port 1812 acct-port 1813
R1(config-radius-server)# key 0 RadiusSecret
R1(config)# aaa group server radius RAD-GRP
R1(config-sg-radius)# server name RAD-1
R1(config)# aaa authentication login default group RAD-GRP local
R1(config)# aaa authorization exec default group RAD-GRP local
# The server returns the privilege level in a Cisco AV-pair on the user:
#     cisco-avpair = "shell:priv-lvl=15"     (drop to 1 for read-only staff)
TACACS+RADIUS
TCP/49, whole packet encryptedUDP/1812-1813, only the password hidden
Per-command authz + accountingPrivilege level via AV-pair; no clean per-command
Best for the network teamFine for read access / reusing 802.1X infra

05

Verify Before You Trust It Safe to Run

Prove authentication, the reachability of the server, and the fallback path — from a second session — before you close the first.

IOS — prove it works and fails safe
R1# test aaa group TAC-GRP alice C1sco legacy   # server-side auth check
R1# show tacacs                              # socket opens, failures
R1# show aaa sessions                        # active accounted sessions
R1# debug aaa authentication                 # on a lab / quiet box only
# The real test: from a NEW ssh session, log in as a TACACS user, then
# shut the server's reachability and confirm 'breakglass' still gets in.

Takeaways

  1. Create a local breakglass user and an enable secret before aaa new-model, and keep a second session open the whole time.
  2. Every method list ends in local / enable so a dead AAA server falls back to the box instead of bricking access.
  3. TACACS+ for the network team — encrypted, per-command authorization and accounting; RADIUS for coarse or read-mostly access.
  4. Pin the source-interface to a loopback so the server always sees one client IP.
  5. Add command authorization last — it fails closed, so prove the server returns correct command sets before relying on it.
  6. Enable aaa authorization console only after proving console local login still works.

Need centralised, audited access to your network gear?

Shared passwords on switches are a finding waiting to happen. I roll out TACACS+/RADIUS admin access across Cisco and MikroTik fleets — role-based, accounted, and with a tested break-glass path so a server outage never locks you out.

Book a Discovery Call →