Network Security

AAA on Cisco IOS XE: TACACS+ vs RADIUS for Device Administration

Live RADIUS authentication test on Cisco IOS XE: accept, reject, and the debug exchange
In: Network Security, Labs

The moment more than one person can log into your routers, you have an access-control problem. Who is allowed in? What are they allowed to do once they are in? And can you prove, after the fact, who typed the command that took the network down? Answering those three questions is what AAA does, and the choice between TACACS+ and RADIUS decides how well it answers them.

This article configures real AAA on Cisco IOS XE, authenticates a live login against a RADIUS server, and shows the actual protocol exchange on the wire. It is the opening piece of the Infrastructure Security cluster guide.

The Three A's

Authentication
Who are you? Prove it. Username and password, a token, a certificate.
Authorization
Now that I know who you are, what may you do? Which commands, which privilege level.
Accounting
What did you do? A log of commands and sessions, for audit and forensics.

The distinction between the first two matters enormously for the protocol choice, because TACACS+ can separate them cleanly and RADIUS cannot.

TACACS+ vs RADIUS: The Real Differences

They are often presented as interchangeable. They are not. They were designed for different jobs.

Encryption
TACACS+ encrypts the entire payload. RADIUS encrypts only the password field; everything else is cleartext.
Transport
TACACS+ uses TCP 49 (reliable). RADIUS uses UDP 1812/1813 (no guaranteed delivery).
AAA separation
TACACS+ splits the three A's into separate exchanges. RADIUS combines authentication and authorization into one.
Command authorization
TACACS+ can authorize per command, per user. RADIUS effectively cannot.
Vendor
TACACS+ is a Cisco protocol (now an open RFC). RADIUS is an open IETF standard, universal.
Primary use
TACACS+ = device administration. RADIUS = network access (802.1X, VPN, Wi-Fi).

The one-line rule almost everyone uses: TACACS+ for administering the devices, RADIUS for admitting the users. When an engineer SSHes into a switch, that is device administration and TACACS+ is the natural fit, because you want per-command authorization and full-payload encryption. When a laptop authenticates onto the wired port, that is network access and RADIUS owns it, because RADIUS carries the 802.1X attributes that assign a VLAN.

The command-authorization point is the decisive one for device administration. With TACACS+ you can permit a junior operator to run show commands and clear counters but nothing that changes config, and every command they attempt is checked against the server in real time. RADIUS pushes a privilege level at login and then steps out of the way; it cannot vet individual commands.

The Golden Rule: Always Have a Local Fallback

Before a single line of AAA config, internalise this, because it is the difference between a good day and being locked out of your entire network: every method list ends in local.

An AAA method list is an ordered list of ways to authenticate. The router tries them in order. If your only method is the AAA server and that server becomes unreachable (or you fat-finger the shared secret), you cannot log in. Anywhere. The fix is to have already been fired, or a very awkward console cable and a password-recovery procedure.

aaa authentication login VTY-AUTH group RAD-GROUP local

That trailing local means "if the server does not answer, fall back to the local username database." We will see it save the day at the end of this article.

Configuring RADIUS (Live)

The lab points R1 at a real FreeRADIUS server running on a Linux host at 192.168.99.100. Turn on AAA, define the server, group it, and build the method lists:

R1(config)# aaa new-model
R1(config)# radius server PINGLABZ-RAD
R1(config-radius-server)#  address ipv4 192.168.99.100 auth-port 1812 acct-port 1813
R1(config-radius-server)#  key PingLabzRAD123
!
R1(config)# aaa group server radius RAD-GROUP
R1(config-sg-radius)#  server name PINGLABZ-RAD
!
R1(config)# aaa authentication login VTY-AUTH group RAD-GROUP local
R1(config)# aaa authorization exec VTY-AUTH group RAD-GROUP local
!
R1(config)# line vty 0 4
R1(config-line)#  login authentication VTY-AUTH
R1(config-line)#  authorization exec VTY-AUTH

The shared secret (key) must match on both the router and the server, and it is what encrypts the RADIUS password field. On the FreeRADIUS side, the router is registered as a client with the same secret, and a test user exists with a Cisco privilege attribute:

# clients.conf
client pinglabz-r1 {
    ipaddr = 192.168.99.1
    secret = PingLabzRAD123
}
# users
netadmin Cleartext-Password := "Cisco@123"
    Cisco-AVPair = "shell:priv-lvl=15"

The shell:priv-lvl=15 AV-pair is how RADIUS pushes an authorization result: it drops the authenticated user straight to privilege level 15. That is the extent of RADIUS authorization, a level at login, and it is why command authorization needs TACACS+.

Proof it works

The router can test the server group directly. Correct password, then wrong:

R1#test aaa group RAD-GROUP netadmin Cisco@123 legacy
Attempting authentication test to server-group RAD-GROUP using radius
User was successfully authenticated.

R1#test aaa group RAD-GROUP netadmin WrongPassword legacy
Attempting authentication test to server-group RAD-GROUP using radius
User authentication request was rejected by server.

Accepted and rejected, correctly, against a live server. And the server relationship is healthy:

R1#show aaa servers | include RADIUS|State|Authen:
RADIUS: id 1, priority 1, host 192.168.99.100, auth-port 1812, acct-port 1813, hostname PINGLABZ-RAD
     State: current UP, duration 93s, previous duration 0s
     Authen: request 6, timeouts 4, failover 0, retransmission 3

The exchange on the wire

This is what actually happens when the router authenticates, captured with debug radius authentication:

RADIUS(00000000): Send Access-Request to 192.168.99.100:1812 id 1645/4, len 60
RADIUS:  NAS-IP-Address      [4]   6   192.168.99.1
RADIUS:  User-Name           [1]   10  "netadmin"
RADIUS:  User-Password       [2]   18  *
RADIUS(00000000): Started 5 sec timeout
RADIUS: Received from id 1645/4 192.168.99.100:1812, Access-Accept, len 63

Read the security lesson in that output. User-Name is "netadmin", in the clear. NAS-IP-Address is in the clear. Only User-Password is hidden (the *). Anyone sniffing this exchange learns the username and everything else; only the password is protected. This is the RADIUS design, and it is precisely why device administration prefers TACACS+, which would have encrypted the entire packet.

One more thing worth noting: modern IOS XE (17.x) now nags about this. The moment you configure a RADIUS or TACACS+ server without TLS, it emits a security warning pointing you toward RadSec (RADIUS over TLS), which encrypts the whole exchange. On a management network you control this is usually acceptable; across untrusted transport it is not.

Configuring TACACS+ and Command Authorization

The device-administration setup. Note the extra method list that RADIUS could not provide, command authorization:

R1(config)# tacacs server PINGLABZ-TAC
R1(config-server-tacacs)#  address ipv4 10.0.13.2
R1(config-server-tacacs)#  key PingLabzTAC123
!
R1(config)# aaa group server tacacs+ TAC-GROUP
R1(config-sg-tacacs+)#  server name PINGLABZ-TAC
!
R1(config)# aaa authentication login CON-AUTH group TAC-GROUP local
R1(config)# aaa authorization commands 15 CMD-AUTHZ group TAC-GROUP local

That last line is the whole reason TACACS+ exists for device administration. aaa authorization commands 15 means every privilege-15 command a user types is sent to the TACACS+ server, which returns permit or deny before the command runs. The server holds a policy like "user bob may run show and configure but not reload," enforced command by command. RADIUS has no equivalent.

R1#show tacacs
Tacacs+ Server -  public  :
               Server name: PINGLABZ-TAC
            Server address: 10.0.13.2
               Server port: 49
             Server Status: Alive

The Local Fallback, In Action

Here is why the golden rule matters, demonstrated. The TACACS+ server in the lab is unreachable. Watch what the router does:

R1#test aaa group TAC-GROUP admin Cisco@123 legacy
Attempting authentication test to server-group TAC-GROUP using tacacs+
No authoritative response from any server.

The group fails. But the method list was aaa authentication login CON-AUTH group TAC-GROUP local. When the group returns no authoritative response, the router moves to the next method: local. A user in the local database can still log in. The network is not lost.

This is not a hypothetical. AAA servers go down, get isolated by the very outage you are trying to fix, or reject you because someone changed a shared secret. The local keyword is the seatbelt. A method list of group TAC-GROUP with no fallback is a loaded gun pointed at your own access.

Configure a local account with a strong secret on every device, exactly for this. It is the account you will use at 3am when the AAA infrastructure is the thing that broke.

Accounting: The Third A

Authentication and authorization control access. Accounting records it, and it is the part people skip until an auditor asks who ran a command.

R1(config)# aaa accounting commands 15 default start-stop group TAC-GROUP
R1(config)# aaa accounting exec default start-stop group TAC-GROUP

With this, every privilege-15 command and every login/logout is logged to the server with a username, timestamp, and source. That is your audit trail. TACACS+ command accounting is genuinely valuable here because it captures the exact command string; RADIUS accounting is coarser, oriented toward session start/stop and byte counts rather than individual commands.

FAQ

Can I run TACACS+ and RADIUS at the same time?

Yes, and it is common: TACACS+ for device admin logins, RADIUS for 802.1X network access, both pointing at the same identity store (often Cisco ISE, which speaks both). They serve different method lists.

Which is more secure?

TACACS+ for device administration, because it encrypts the full payload and the username is not exposed. For network access the question is moot; RADIUS is what carries the 802.1X attributes.

What happens if I forget the local fallback and the server dies?

You are locked out of every device that used that method list, and you are looking at console access and password recovery on each one. Never omit local.

Why does IOS XE warn about TLS now?

Because plain RADIUS and TACACS+ shared-secret encryption is dated. RadSec (RADIUS/TLS) and TACACS+ over TLS encrypt the transport. On a trusted management network the warning is informational; over untrusted links, act on it.

Is the shared secret the same as the user password?

No. The shared secret authenticates the router to the server and encrypts fields. The user password authenticates the person. Two completely separate credentials.

Key Takeaways

  • AAA is three questions: who are you (authentication), what may you do (authorization), what did you do (accounting).
  • TACACS+ for administering devices, RADIUS for admitting users. TACACS+ encrypts the whole payload and does per-command authorization; RADIUS carries 802.1X attributes.
  • The live RADIUS debug shows the username and everything but the password in the clear. That exposure is why device admin prefers TACACS+.
  • Every method list ends in local. The lab proved it: the TACACS+ server was unreachable, and the local fallback kept access alive.
  • RADIUS authorization is a privilege level at login (shell:priv-lvl=15). TACACS+ authorization is command by command.
  • Turn on accounting, or you cannot prove who did what.
  • IOS XE 17.x nudges you toward RadSec/TLS. Heed it on untrusted transport.

Next: hardening the management plane, or the Infrastructure Security cluster guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.