Bring up TACACS+ on a lab switch
When you need this
Section titled “When you need this”- “I want to confirm a real Catalyst actually authenticates against l2trace before I stand up AD and the database.”
- “The mock NAS in the test suite passes. Does a physical switch agree?”
- “I’m bringing up a lab switch and don’t want to provision LDAP and Postgres just to test the handshake.”
The test suite proves l2trace is self-consistent — it talks to its own
mock NAS and they agree. Only a real switch proves l2trace is
RFC-consistent: that a Catalyst’s MD5 pad, its ASCII login dialog, and
the way it reads shell-authorization arguments all match l2trace’s wire
format. l2trace tacacs-lab exists to close that gap with the least
possible scaffolding — no Active Directory, no database, just a network
path to the switch.
What it is (and isn’t)
Section titled “What it is (and isn’t)”tacacs-lab runs the same TACACS+ server the production service runs, but
wired to in-memory stand-ins instead of the real backends: a static
credential map instead of AD, a static shell-profile resolver instead of
group lookups, and a database-free accounting sink that logs each
record instead of writing the bitemporal store. It holds cleartext test
passwords in memory and is explicitly not a production path — production
is l2trace tacacs with an identity source, covered in
the device-administration how-to.
Enforcement stays off. The shell profile you attach to a --user is
computed and logged, not applied: the switch keeps its own default
privilege. The tool’s job is to prove the handshake and touch nothing —
“the mock NAS proves we are self-consistent; only a Catalyst proves we are
RFC-consistent,” and it proves that without changing a single privilege on
the box.
Run it
Section titled “Run it”l2trace tacacs-lab \ --switch-ip 192.0.2.10 \ --secret 'the-shared-secret-on-the-switch' \ --user test=Passw0rd=15 \ --dialect ios| Flag | Default | Description |
|---|---|---|
--switch-ip | (required) | The lab switch’s source IP — the NAS l2trace will accept |
--secret | (required) | The shared secret configured on the switch |
--user | (required, repeatable) | name=password[=priv_lvl], e.g. --user test=Passw0rd=15. At least one required |
--listen-addr | 0.0.0.0 | Bind address |
--port | 4949 | Bind port. Port 49 needs root; the default is high so you publish or redirect 49 → 4949 |
--dialect | generic | Shell dialect: ios | nxos | arista | generic |
The --user parser reads the privilege only as a trailing all-digits
field, so a password may itself contain =: --user u=a=b=7 is user u,
password a=b, priv 7. A digits-only password with no priv is read as
the password, not a level.
On start it logs the switch, bind address, dialect, and users, notes that
enforcement is off (profiles are logged, not applied), and reminds you to
point the switch at it with a group tacacs+ local method list and to log
in with the local account first to confirm the fallback path. Every
login and command then prints as an accounting line (tacacs-lab: ACCT ...) — no database needed.
Point the switch at it
Section titled “Point the switch at it”On the lab switch (IOS shown), after the break-glass account is in place and tested:
tacacs server l2trace-lab address ipv4 <l2trace-host> key the-shared-secret-on-the-switch port 49aaa authentication login default group tacacs+ localaaa authorization exec default group tacacs+ localIf l2trace listens on 4949, publish or redirect host 49 to it (the same
host 49 → container 4949 split the production overlay uses, or the
--port 49 bind if you run it as root). Then log in with your --user
credential. It authenticates against the static map; the shell profile is
computed and logged; accounting scrolls past in the terminal.
What a clean run tells you
Section titled “What a clean run tells you”A successful lab login proves the three things the mock NAS structurally cannot:
- the MD5 pad l2trace derives from the shared secret matches what the Catalyst expects, so the obfuscated body decodes;
- the ASCII login dialog (the START / GETUSER / GETPASS exchange) lines up turn-for-turn with a real supplicant;
- the switch reads the shell-authorization arguments l2trace sends in
the dialect you selected (
priv-lvlfor IOS,shell:rolesfor NX-OS/EOS).
Once those agree on real hardware, you can move on to the full service with confidence that the wire format is right — the remaining work is identity and storage, not protocol. This exact runner was validated live against a Catalyst 9300L on IOS-XE 17.15.
Then move to the real service
Section titled “Then move to the real service”tacacs-lab deliberately stops at the handshake. To get AD-backed logins,
group-driven privilege and command sets, the bitemporal audit trail, and
(eventually, lab-only) enforcement, follow
Stand up TACACS+ device administration —
the same switch config, pointed at l2trace tacacs with an identity source
and database behind it.
See also
Section titled “See also”- Stand up TACACS+ device administration — the production path this lab run is a rehearsal for.
- The TACACS+ lockout doctrine — why the local break-glass account comes first, in the lab too.