TACACS+ is the protocol network devices use to ask a central server three questions about an administrator: who are you, what may you run, and what did you do. It runs over TCP port 49, is documented in RFC 8907 (September 2020), and hides its packet bodies with an MD5 based obfuscation that the RFC itself calls weak. RFC 9887 (December 2025) fixes that by carrying TACACS+ inside mutually authenticated TLS 1.3 on TCP port 300.
This post sits next to our explainers on RADIUS, AAA in general, SNMP and NETCONF, RESTCONF and YANG. Here we stay on TACACS+ itself: where it came from, the 12 byte header and the three session types, exactly what the obfuscation does and why it fails, what changed with TACACS+ over TLS 1.3, how per command authorization and accounting build an audit trail, the classic weaknesses described conceptually with the fix for each, and a step by step lab with an open source server that ends on TLS.
Key takeaways
- TACACS+ is a device administration protocol. A router, switch, firewall or server (the client, sometimes called the NAS) sends authentication, authorization and accounting requests to one or more central TACACS+ servers over TCP. RFC 8907 describes it as "widely deployed today" for exactly that use.
- RFC 8907 is Informational, not a standard. It documents the common subset of a 1997 internet draft ("The Draft", TACACS+ version 1.78) that was never standardized, and removes or deprecates a few unsafe features (SENDPASS, the FOLLOW redirect).
- Authentication, authorization and accounting are three separate packet types (0x01, 0x02, 0x03) that can be used independently. That separation is what lets a device ask the server about every single command an administrator types.
- Every packet starts with a 12 byte cleartext header. Clients send odd sequence numbers, servers send even ones, and the session_id must be cryptographically random.
- The body is "obfuscated" by XORing it with a pad built from chained MD5 hashes of the session_id, the shared secret, the version and the sequence number. RFC 8907 says this provides "no meaningful integrity, privacy, or replay protection" and that an attacker on the path should be assumed able to read and modify every packet.
- RFC 9887 (Standards Track, December 2025, updates RFC 8907) carries TACACS+ over TLS 1.3 or later, requires mutual authentication with certificates as the baseline, forbids 0 RTT early data, obsoletes the obfuscation and uses the new well known port 300 ("tacacss"), allocated by IANA on 15 July 2025.
- Clients must not fall back from TLS to non TLS, and RFC 9887 recommends running TLS and legacy servers on separate hosts. The migration window is the riskiest phase, so keep it short.
- Until TLS is everywhere, RFC 8907's own rule applies: keep TACACS+ on a separate, protected management network, use a unique long secret per device, accept only known clients, and send logs to a system that attackers on the device path cannot edit.
What TACACS+ is and where it came from
TACACS stands for Terminal Access Controller Access Control System. The original idea is older than the commercial internet. RFC 1492, written by Craig Finseth at the University of Minnesota in July 1993, explains the background: ARPANET had dial up routing nodes called TIPs, people wanted to control who could use the dial up lines, and "someone invented a protocol, called TACACS" that let a TIP pass a username and password to a server, which answered yes or no. RFC 1492 itself was written because the author could not obtain the original specification, and it documented the extended version that a large router vendor's terminal servers implemented. That simple TACACS ran over UDP or TCP on port 49, which is still the IANA registration for "tacacs" today.
TACACS+ is a different protocol with the same name family. It was written up as an internet draft, draft-grant-tacacs-02, "The TACACS+ Protocol Version 1.78", by D. Carrel and L. Grant, dated January 1997 in RFC 8907's references. That draft never became a standard, but vendors and open source projects implemented it anyway, and for two decades it was the de facto specification for administrator access to network equipment. (RFC 8907's security section refers to "The Draft" from 1998, while its reference list dates it January 1997; we use the reference list date.)
In September 2020 the IETF published RFC 8907, authored by T. Dahm, A. Ota, D.C. Medway Gash, D. Carrel and L. Grant. It is Informational. Its stated purpose is to clarify the subset of The Draft that implementations share for device administration, so that anything conforming to RFC 8907 also conforms to The Draft. Along the way it removes SENDPASS for security reasons, drops the normative description of legacy features such as the Apple Remote Access Protocol and outbound authentication, and deprecates forwarding to another server with TAC_PLUS_AUTHEN_STATUS_FOLLOW.
The RFC describes TACACS+ as "conceived initially as a general Authentication, Authorization, and Accounting (AAA) protocol" but "mainly confined" today to device administration: authenticating access to network devices, providing central authorization of operations, and auditing those operations. That last part is the real reason the protocol survives.
TACACS+ versus RADIUS for device administration
RADIUS (RFC 2865, June 2000) and TACACS+ both do AAA, and many servers speak both. They were shaped by different jobs.
| Property | TACACS+ (RFC 8907) | RADIUS (RFC 2865 and 2866) |
|---|---|---|
| Main job today | Administrator access to network devices | Network access for users and devices (Wi-Fi, VPN, 802.1X, dial in) |
| Transport | TCP port 49; TLS on TCP port 300 (RFC 9887) | UDP 1812 and 1813; TCP and TLS variants exist (RFC 6613, RFC 6614 on port 2083) |
| What is hidden on the wire | The whole packet body, with MD5 based obfuscation | Only User-Password and a few attributes; most attributes in cleartext |
| Authentication and authorization | Separate packet types and separate exchanges | Combined: Access-Accept carries the authorization attributes |
| Per command authorization | Built in: one REQUEST and REPLY per command, with cmd and cmd-arg | Not designed for it; vendor attributes can carry a privilege level or role |
| Accounting | START, STOP and WATCHDOG records; commonly one record per command | Start, Stop and Interim-Update records, usually per session |
| Typical failure policy | Device falls back to the next server, then to local accounts | Same pattern, often with the same risks |
| Standards status | Informational (RFC 8907); TLS profile is Standards Track (RFC 9887) | Standards Track (RFC 2865); RADIUS/1.1 over TLS is Experimental (RFC 9765) |
The short version: RADIUS answers "may this user or device join the network". TACACS+ answers "may this administrator log in to this router, may they run this exact command, and please write down that they ran it". The second question has to be asked many times per session, over a reliable connection, with a reply that can be more than yes or no. That is why TCP, separate authorization exchanges and per command accounting matter, and why most operators who run both use RADIUS for network access and TACACS+ for the device management plane.
Timeline
| Date | Event | Source |
|---|---|---|
| July 1993 | RFC 1492 documents the original TACACS and a vendor's extended version | RFC 1492 |
| January 1997 | draft-grant-tacacs-02, "The TACACS+ Protocol Version 1.78" ("The Draft") | RFC 8907 references |
| June 2000 | RFC 2865 defines RADIUS on UDP 1812 | RFC 2865 |
| March 2011 | RFC 6151 updates the security considerations for MD5 | RFC 6151 |
| May 2012 | RFC 6614, RADIUS over TLS (Experimental), TCP port 2083 | RFC 6614; IANA |
| August 2018 | RFC 8446 defines TLS 1.3 | RFC 8446 |
| September 2020 | RFC 8907, The TACACS+ Protocol (Informational) | RFC 8907 |
| August 2021 | RFC 9105, YANG data model for TACACS+ clients (ietf-system-tacacs-plus) | RFC 9105 |
| November 2022 | RFC 9325 (part of BCP 195), current TLS recommendations | RFC 9325 |
| 3 to 4 December 2024 | CISA and partners publish Enhanced Visibility and Hardening Guidance for Communications Infrastructure, which names TACACS+ | CISA |
| April 2025 | RFC 9765, RADIUS/1.1 over TLS without MD5 (Experimental) | RFC 9765 |
| 15 July 2025 | IANA registers "tacacss" on TCP port 300 | IANA port registry |
| December 2025 | RFC 9887, TACACS+ over TLS 1.3 (Standards Track, updates RFC 8907) | RFC 9887 |
How a TACACS+ session works
Clients, servers, connections and sessions
RFC 8907 uses four nouns precisely. The client is the device being administered (the network access server, or NAS). The server answers. A connection is a TCP connection between them. A session is one complete authentication, authorization or accounting exchange, identified by a session_id. Normally one connection carries one session and is closed when it ends. If both sides agree to Single Connection Mode, the client can multiplex many sessions over one long lived TCP connection, which saves handshakes on a busy device.
Single Connection Mode is negotiated with a flag in the first two packets only. The client sets TAC_PLUS_SINGLE_CONNECT_FLAG (0x04) in its first packet. The server sets it in its first reply if it agrees. After the second packet the flag is ignored. The server must time out idle single connections to protect its own resources, and the client must cope with that.
The 12 byte header
Every TACACS+ packet starts with the same header, always in cleartext:
| Field | Size | Values and meaning |
|---|---|---|
| major_version | 4 bits | 0xc |
| minor_version | 4 bits | 0x0 default, 0x1 for some authentication types |
| type | 1 byte | 0x01 authentication, 0x02 authorization, 0x03 accounting |
| seq_no | 1 byte | Starts at 1; client sends odd, server sends even; never wraps past 255 |
| flags | 1 byte | 0x01 TAC_PLUS_UNENCRYPTED_FLAG, 0x04 TAC_PLUS_SINGLE_CONNECT_FLAG |
| session_id | 4 bytes | Random, constant for the session; must come from a cryptographically strong generator |
| length | 4 bytes | Length of the body in bytes; servers must let operators cap it, with 2 to the power 16 recommended |
Two details matter for security. The session_id and sequence number are inputs to the obfuscation pad, so a predictable session_id weakens it further; the RFC says failure to use a strong random generator "will compromise security of the session". And because the header is cleartext, anyone who can see the traffic learns the packet type, the length and the session boundaries even if they cannot read the body.
Authentication: START, REPLY, CONTINUE
Authentication is a conversation. The client sends a START packet that says what kind of authentication it wants: the action (login, change password), the privilege level being requested, the authen_type (ASCII, PAP, CHAP, MS-CHAP v1 or v2) and the authen_service (login, enable, and others), plus the username, the port (for example a VTY line or the console) and the remote address the administrator came from.
The server answers with a REPLY. The reply is either final (PASS, FAIL, ERROR, RESTART) or a request for more: GETUSER, GETPASS or the generic GETDATA. For a request for more, the server includes a prompt in server_msg, and can set the NOECHO flag so the device does not echo what the administrator types. The client answers each request with a CONTINUE packet. The classic ASCII login therefore looks like this:
| seq_no | Direction | Packet | Content |
|---|---|---|---|
| 1 | Client to server | START | action login, authen_type ASCII, port, remote address, maybe username |
| 2 | Server to client | REPLY | GETUSER with prompt "Username:" (skipped if the username was sent) |
| 3 | Client to server | CONTINUE | The username |
| 4 | Server to client | REPLY | GETPASS with prompt "Password:" and NOECHO |
| 5 | Client to server | CONTINUE | The password |
| 6 | Server to client | REPLY | PASS or FAIL |
PAP and CHAP put everything in the START packet and get a single REPLY. The ASCII flow matters because it lets the server drive arbitrary prompts, which is how one time password and multi factor schemes have been bolted onto TACACS+: the server simply asks for one more thing.
An ENABLE request is an authentication with the enable service and a target privilege level. It is how an administrator who logged in at a low level asks to be raised to a higher one, and it is checked by the server like any other login.
Authorization: one REQUEST, one REPLY
Authorization is always exactly two packets. The REQUEST repeats how the user was authenticated (authen_method, priv_lvl, authen_type, authen_service, user, port, rem_addr) and adds a list of argument value pairs describing what is being asked for. The REPLY carries a status and its own argument value pairs:
| Status | Value | Meaning |
|---|---|---|
| PASS_ADD | 0x01 | Allowed; apply the request arguments plus any returned ones |
| PASS_REPL | 0x02 | Allowed; use the returned arguments instead of the requested ones |
| FAIL | 0x10 | Denied |
| ERROR | 0x11 | The server could not decide; the client must act as if the server were unreachable |
The argument pairs are what make authorization useful. service is mandatory (shell, tty-server, connection, system, firewall and so on). For service=shell, cmd is mandatory: an empty cmd means "may this user start a shell session", and the reply can set priv-lvl, an automatic command or a timeout. A non empty cmd plus cmd-arg values means "may this user run this specific command with these arguments". Arguments marked mandatory (with "=") must be understood by the client; RFC 8907 says a client that receives an unrecognized mandatory argument must treat the reply as FAIL.
Note what the protocol does not do: RFC 8907 states "there is no provision made at the protocol level to associate authentication requests with authorization requests." The device asserts who the user is and how they logged in, and the server trusts that assertion. That design choice is the root of one of the attacks below.
Accounting: START, STOP, WATCHDOG
Accounting REQUEST packets carry a flags byte with TAC_PLUS_ACCT_FLAG_START (0x02), TAC_PLUS_ACCT_FLAG_STOP (0x04) or TAC_PLUS_ACCT_FLAG_WATCHDOG (0x08, an interim update), plus the same user context as authorization and a list of argument pairs. Accounting arguments come first: task_id (start and stop records for the same event must share it), start_time, stop_time, elapsed_time, timezone, event and reason, followed by the authorization style arguments such as service, cmd and cmd-arg. The server replies SUCCESS or ERROR.
Privilege levels
TACACS+ has a built in scheme of privilege levels from 0 to 15, each a superset of the one below. RFC 8907 names TAC_PLUS_PRIV_LVL_MIN (0, normally unauthenticated), TAC_PLUS_PRIV_LVL_USER (1, a regular authenticated session) and TAC_PLUS_PRIV_LVL_ROOT and TAC_PLUS_PRIV_LVL_MAX (both 15). Which commands sit at which level is entirely up to the device configuration. The RFC is candid that a single monotonic hierarchy is inflexible, which is why per command authorization and role schemes evolved on top of it.
What the RFC 8907 obfuscation protects, and why the RFC calls it weak
How the pad is built
When TAC_PLUS_UNENCRYPTED_FLAG is clear, the body is XORed byte by byte with a pseudo random pad. The pad is a chain of MD5 hashes, each 16 bytes, truncated to the body length:
MD5_1 = MD5(session_id, key, version, seq_no)
MD5_2 = MD5(session_id, key, version, seq_no, MD5_1)
...
MD5_n = MD5(session_id, key, version, seq_no, MD5_n-1)
pseudo_pad = MD5_1 || MD5_2 || ... truncated to len(body)
obfuscated_body = body XOR pseudo_pad
Everything in the hash input except the key sits in the cleartext header. Each packet in a session has a different seq_no and so a different pad, and each session has a different session_id. The shared secret is the only thing an observer does not know.
After de obfuscation the receiver adds up the length fields inside the body and compares the total with the header's length field. A mismatch means a wrong key or a corrupted packet, and the server must return ERROR. That length check is the only consistency check in the protocol. There is no message authentication code.
What it protects
The obfuscation does stop a casual observer from reading passwords, usernames, commands and accounting records in a plain packet capture, provided the secret is long, random and unique to the device. That is worth something on a trusted, separated management network, which is exactly where RFC 8907 says the protocol must live. It also explains a line in the RFC that surprises people: test traffic should stay obfuscated, because modern traffic analysis tools can decode TACACS+ when you give them the shared secret. The Wireshark TACACS+ dissector, for example, exposes decoded fields such as tacplus.acct.flags.start and tacplus.acct.flags.stop.
What it does not protect
RFC 8907 section 10.1 is unusually blunt for an RFC. It says the mechanism is best called "obfuscation" and not "encryption", that it provides "no meaningful integrity, privacy, or replay protection", and that "an attacker with access to the data stream should be assumed to be able to read and modify all TACACS+ packets". It lists the weaknesses:
| Weakness named in RFC 8907 | What it means in practice |
|---|---|
| Brute force made efficient by fast MD5 | Anyone with a captured packet can test candidate secrets offline at hardware speed; a short or dictionary secret falls quickly |
| Known plaintext | Many body bytes are predictable (status codes, flag bytes, lengths, argument names such as "service=shell"), which reveals pad bytes directly and helps confirm guesses |
| Chosen plaintext | An attacker who can trigger logins with chosen usernames controls part of the plaintext |
| No forward secrecy | One recovered secret decrypts every past capture made with it, and the secret rarely changes |
| No integrity | XOR is malleable: flip a bit in the obfuscated body and the same bit flips in the plaintext, undetected |
MD5 itself is the other half of the problem. RFC 6151 (March 2011) updated MD5's security considerations, and RFC 9887 cites it when it says the MD5 based obfuscation "has been shown to be insecure" and that this "prevents TACACS+ from being used in a deployment compliant with" FIPS 140-3.
The section on authorization gives a worked example of malleability. Many sites authorize every command typed on the console port, because the console is assumed to be physically secure. The authen_method field sits at a known offset (the first byte after the header) with a known value. An attacker on the path who knows the plaintext byte knows the pad byte, and can change the method from TACACS+ to "line" so the server sees what looks like a console session and authorizes everything. Nothing in the protocol detects the change. The fix is not a better pad; it is a transport with integrity.
What changed with TACACS+ over TLS 1.3 (RFC 9887)
RFC 9887, "Terminal Access Controller Access-Control System Plus (TACACS+) over TLS 1.3", was published in December 2025 by T. Dahm, J. Heasley, D.C. Medway Gash and A. Ota. Unlike RFC 8907 it is on the Standards Track, and it updates RFC 8907. It came out of the IETF Operations and Management Area Working Group as draft-ietf-opsawg-tacacs-tls13, which reached revision 24 before publication. The core protocol is unchanged: once TLS is up, the same START, REPLY, CONTINUE, REQUEST and REPLY packets flow, with the same sequence numbers and argument pairs. What changes is everything around them.
| Topic | RFC 8907 (legacy) | RFC 9887 (TLS) |
|---|---|---|
| Port | TCP 49 | TCP 300, service name "tacacss"; must differ from the non TLS port |
| Confidentiality and integrity | MD5 pad, no integrity | TLS 1.3 or later; earlier TLS versions must not be used |
| Peer authentication | Implied by knowing the shared secret | Mutual authentication; certificates mandatory to implement; external PSKs and raw public keys optional |
| Obfuscation | Required in production | Obsoleted; TAC_PLUS_UNENCRYPTED_FLAG must be set to 1 on every packet over TLS |
| Upgrade path | Not applicable | No STARTTLS style upgrade; TLS starts immediately after TCP connects |
| Fallback | Implementation specific | Clients must not fall back to non TLS when TLS fails, including during migration |
| Early data | Not applicable | 0 RTT forbidden; servers must disconnect clients that send it |
| Server identity | IP address and secret | RFC 9525 checks against DNS-ID, IP-ID or SRV-ID; SNI must be supported |
| Client identity | Source address plus secret | Certificate path validation with revocation checking, then source address or subjectAltName (dNSName, iPAddress) matching |
Why a new port instead of an upgrade
RFC 9887 section 5.3 explains the choice. A separate port makes it easy to block legacy TACACS+ by port number, leaves existing passive monitoring of legacy traffic unaffected, avoids on path attacks that interfere with an upgrade negotiation, and prevents accidental exposure through misconfiguration. Servers that support TLS must listen on a port distinct from non TLS servers, and RFC 9887 goes further: TLS servers must not accept non TLS connections at all, and running TLS and non TLS servers on the same host is "NOT RECOMMENDED".
Certificates, PSKs and revocation
Certificate based mutual authentication is mandatory to implement and is described as "the primary authentication option". Each side must validate the other's certificate path per RFC 5280, including revocation checking. Because a device may be cut off from its certificate authority during exactly the outage when an administrator needs to log in, RFC 9887 requires support for storing the remote peer's whole chain locally and points to OCSP via the Authority Information Access extension as one revocation path. Operators should plan for "unreachable CA" before they need it.
External pre shared keys are an optional alternative. If implemented, PSKs of at least 16 octets and PSK identities of at least 16 octets must be supported, and the RFC follows the RFC 9257 guidance on external PSKs. One rule is easy to break during migration: the PSKs used for TLS must not be the same as the old obfuscation shared secrets.
Wildcard server certificates are allowed but must follow RFC 9525, and the wildcard must cover a subdomain used only for TACACS+ servers, because one stolen wildcard key impersonates every server under it.
Resumption and keepalives
TLS resumption is encouraged to save round trips: a client holding an unused ticket should use it, tickets are single use, and the server should accept an unexpired, unused ticket. Revocation must still be checked for the period since the ticket was issued, and the ticket lifetime should be configurable down to zero. Connections are usually short lived; outside Single Connection Mode the TCP connection closes when the TACACS+ session ends, so no transport keepalives are required.
What TLS does not fix
RFC 9887 is explicit that it "does not make any changes to the core TACACS+ protocol". Passwords still travel inside the session (now protected), the server still trusts the device's statement of how the user authenticated, and a compromised device is still a compromised device. The RFC notes that further documents are planned to address password based authentication. It also points to a YANG model for configuring TLS on TACACS+ clients, still an internet draft (draft-ietf-opsawg-secure-tacacs-yang) when RFC 9887 was written; the earlier published model, RFC 9105 (August 2021), defines the ietf-system-tacacs-plus module with a shared-secret leaf for legacy servers.
How per command authorization and accounting create an audit trail
Per command authorization and per command accounting are the reason security teams care about TACACS+. Configured fully, every line an administrator types at a device prompt produces two network events: an authorization exchange before it runs, and an accounting record after.
| Step | Packet | Example argument pairs | What you learn |
|---|---|---|---|
| Login | Authentication START to REPLY PASS | user, port tty1, rem_addr 10.20.0.15 | Who logged in, from where, on which line |
| Shell start | Authorization REQUEST, service=shell cmd= (empty) | Reply sets priv-lvl=15 or a lower level | Which role the session received |
| Each command | Authorization REQUEST, service=shell cmd=interface cmd-arg=xe-0/0/1 | Reply PASS_ADD or FAIL | Whether the command was allowed, and attempts that were denied |
| Each command | Accounting REQUEST START or STOP, task_id=, start_time=, cmd= | The command line and timing | What actually ran, when and for how long |
| Logout | Accounting STOP for the shell, elapsed_time= | Session duration | When the session ended |
This maps directly onto audit controls. NIST SP 800-53 Revision 5 includes AC-6 Least Privilege with the enhancement AC-6(9) Log Use of Privileged Functions, AU-2 Event Logging, AU-3 Content of Audit Records, AU-12 Audit Record Generation, AU-6 Audit Record Review, Analysis, and Reporting, and AU-9 Protection of Audit Information with the enhancement AU-9(2) Store on Separate Physical Systems or Components. Command accounting stored on the TACACS+ server, and forwarded from there to a log platform, is one of the most direct ways to generate privileged function records for network devices and keep them off the devices being audited. IA-2 (Identification and Authentication of organizational users) and IA-3 (Device Identification and Authentication) map to the TLS mutual authentication in RFC 9887.
The audit trail is only as good as the transport. RFC 8907 section 10.4 warns that an on path attacker can replace accounting data with new values or garbage to confuse auditors or hide an attack, or inject entries designed to break the systems that process the log. It also notes that some clients have been observed sending passwords and keys inside accounting records, which then sit in logs protected by an obfuscation with no forward secrecy. Two practical consequences: filter or mask sensitive arguments before accounting data leaves the TACACS+ server, and treat legacy TACACS+ accounting as tamper evident only if the management network itself is trusted.
CISA's December 2024 Enhanced Visibility and Hardening Guidance for Communications Infrastructure, published with US and international partners, makes the same points from the operations side. It says to send all AAA logging "to a centralized logging server with modern confidentiality, integrity, and authentication" protections, to apply secure authentication to protocols including TACACS+ where possible, to use a centralized AAA server with multi factor authentication for everyday device management while keeping that AAA server "not linked to the primary corporate identity store", to use local accounts only for emergencies and change their passwords after each use, and to store the TACACS+ key with the strongest local encryption the device supports rather than a reversible encoding.
Attack history, described conceptually
None of the weaknesses below needs a clever trick. Each follows from the design choices described above, and each has a well understood fix. We describe the mechanism, the fix and the lesson, not the steps.
| Weakness | Mechanism (conceptual) | Fix | Lesson |
|---|---|---|---|
| Shared secret recovery | A captured obfuscated packet plus known plaintext lets an attacker test guesses for the secret offline using fast MD5 | Long random secret per device (RFC 8907: support 32 characters, configure at least 16), rotation, then TLS 1.3 | A secret that protects traffic must be treated like a key, not a password |
| Cleartext on the wire | TAC_PLUS_UNENCRYPTED_FLAG set, or an empty key left in place after debugging, sends bodies in cleartext | Servers reject the flag on legacy connections; clients need explicit configuration to set it; audit for empty keys | Test modes leak into production unless the software refuses them |
| Body tampering | XOR malleability lets an on path attacker change known bytes, such as authen_method, without detection | Integrity from TLS; never grant broad rights based on a client asserted field like the login method | Without integrity, every field the server trusts is attacker controlled |
| Server spoofing | Legacy TACACS+ has no server authentication beyond the secret; an attacker who knows or guesses it, or who redirects traffic, can answer as the server | TLS server certificates checked against DNS-ID or IP-ID; dedicated subdomain for wildcards | The device must authenticate the server, not just the reverse |
| Redirect leaking secrets | The deprecated FOLLOW mechanism could send another server's secret to the client | RFC 8907 deprecates it; servers must disable it by default; clients treat FOLLOW as FAIL | A protocol feature that ships keys around will eventually ship them to the wrong place |
| Fallback to local accounts | Making servers unreachable (or returning ERROR) pushes the device to its next method, often a local account with an old shared password | Local accounts for emergencies only, unique per device, vaulted, rotated after each use, alerting on use | The fallback path is part of the authentication system and needs the same care |
| Accounting log tampering or poisoning | Rewritten or injected records hide activity or break log parsers | TLS transport, log integrity, separate log storage, input handling on the log pipeline | An audit trail that can be edited in flight is not evidence |
| TLS downgrade during migration | Blocking port 300 so a dual configured client falls back to port 49 | Clients must not fall back; separate hosts for TLS and legacy; short migration window | Migration states are attack surface; RFC 9887 calls them insecure until complete |
Shared secret recovery in more detail
Because the pad depends only on public header fields and the secret, a single captured packet is enough to start an offline search. The attacker computes the first MD5 block for each candidate secret, XORs it with the first 16 obfuscated body bytes, and checks whether the result looks like a valid body: plausible status or action codes, and internal lengths that add up to the header length. That length sum is the same check the real server uses, which makes it a free oracle. A long, random secret makes the search infeasible. A secret like a site name plus a year does not. Secret length and uniqueness are therefore the single most important legacy control, and they are why RFC 8907 requires servers to support a dedicated secret per client, warn on reuse, track key lifetimes and never log secrets.
Fallback to local accounts in more detail
RFC 8907 section 4.4 says that when a server returns ERROR, the client "MUST behave as if the server could not be connected to", and suggests a list of servers plus a local fallback. That is good for availability. The risk is what the local fallback looks like in practice: one shared administrator password configured on every device years ago. Anyone who can make the TACACS+ servers unreachable from a device, or who just waits for a real outage, gets a login path that skips central authorization and often skips accounting. The fix is a deliberate break glass design: local accounts that work only when servers are unreachable (many network operating systems offer this as a method list order), unique credentials per device kept in a vault, console only access for the emergency account where possible, and an alert on every use.
Step by step: run an open source TACACS+ server and move to TLS
This lab uses tac_plus-ng, an open source event driven TACACS+ daemon from the event-driven-servers project on GitHub. Its documentation states it supports TACACS+ over TLS 1.3 (RFC 9887), is compliant with RFC 8907, and also speaks RADIUS over UDP, TCP, TLS and DTLS. The project README warns it is work in progress and should not be used in production without testing, so treat this as a lab you would then harden. The older tac_plus daemon in the same repository is marked deprecated in favour of tac_plus-ng.
Step 1: build the server
# Debian or Ubuntu lab host; check PREREQUISITES.txt in the repo for your platform
sudo apt install build-essential perl libssl-dev git
git clone https://github.com/MarcJHuber/event-driven-servers.git
cd event-driven-servers
./configure tac_plus-ng
make
sudo make install
The README documents exactly this sequence (./configure tac_plus-ng, make, sudo make install). TLS support depends on building against OpenSSL.
Step 2: write a minimal legacy configuration
tac_plus-ng reads one file that configures the spawnd listener, the daemon and the authentication backend. This version listens on port 49 for a lab subnet, logs to files, and gives two roles: full access, and read only access with per command rules.
#!/usr/local/sbin/tac_plus-ng
id = spawnd {
listen { port = 49 }
spawn { instances min = 1 instances max = 4 }
background = no
}
id = tac_plus-ng {
log authzlog { destination = /var/log/tac_plus/authz/%Y/%m/%d.log }
log authclog { destination = /var/log/tac_plus/authc/%Y/%m/%d.log }
log acctlog { destination = /var/log/tac_plus/acct/%Y/%m/%d.log }
authorization log = authzlog
authentication log = authclog
accounting log = acctlog
mavis module = external {
setenv SHADOWFILE = "/usr/local/etc/tac_plus-ng.shadow"
exec = /usr/local/lib/mavis/mavis_tacplus_shadow.pl
}
login backend = mavis chpass
device lab {
address = 10.20.0.0/24
key = "replace-with-32-plus-random-characters-per-device"
}
profile netadmin {
script {
if (service == shell) {
if (cmd == "") set priv-lvl = 15
permit
}
}
}
profile readonly {
script {
if (service == shell) {
if (cmd == "") { set priv-lvl = 1 permit }
if (cmd =~ /^show /) permit
if (cmd =~ /^ping /) permit
deny
}
}
}
group admins
group operators
user alice { password login = mavis member = admins }
user bob { password login = mavis member = operators }
ruleset {
rule {
script {
if (member == admins) { profile = netadmin permit }
if (member == operators) { profile = readonly permit }
}
}
}
}
The log destinations, the device block with address and key, profiles with script blocks and cmd =~ regular expressions, and the shadow file MAVIS backend all follow the tac_plus-ng manual and its sample tac_plus-ng.cfg-shadow. The manual also documents a key warn form with a date, which logs a warning whenever a device uses the old key. That is a clean way to rotate legacy secrets: add the new key, mark the old one with warn, and watch the log until nothing uses it.
Generate the secret per device rather than inventing it:
openssl rand -base64 33 # about 44 characters, unique per device
Step 3: check the configuration and test without a router
# Parse only; the manual stresses using -P after every edit
sudo /usr/local/sbin/tac_plus-ng -P /usr/local/etc/tac_plus-ng.cfg
# Run in the foreground for the lab
sudo /usr/local/sbin/tac_plus-ng /usr/local/etc/tac_plus-ng.cfg
The project ships tactrace.pl, a TACACS+ and RADIUS validator that runs requests against the configuration. Its documented options include --mode (authc, authz or acct), --username, --key, --nad and --conf, and it takes authorization argument pairs as arguments. It needs the Perl modules Net::IP and Net::TacacsPlus::Packet, which the manual installs with apt install libnet-ip-perl and cpan install Net::TacacsPlus::Packet.
cd event-driven-servers/tac_plus-ng/perl && make
# Should be permitted for an operator
./tactrace.pl --conf /usr/local/etc/tac_plus-ng.cfg --mode=authz \
--username=bob "service=shell" "cmd=show" "cmd-arg=version"
# Should be denied for an operator
./tactrace.pl --conf /usr/local/etc/tac_plus-ng.cfg --mode=authz \
--username=bob "service=shell" "cmd=configure"
Step 4: configure devices, by category
Every network operating system has its own syntax, so here is what to configure in each category rather than one vendor's commands. Check each item in your platform's documentation.
| Category | What to set | Why |
|---|---|---|
| Server group | Two or more TACACS+ servers, each with its own address, port and key; source interface on the management VRF | Redundancy without falling straight to local accounts; traffic stays on the management network |
| Login authentication | TACACS+ group first, local second; console may use a separate list | Central identity for daily use; local only when servers are unreachable |
| Enable or privilege escalation | Authenticate enable through TACACS+ | Escalation is logged and can be denied centrally |
| Shell authorization | Authorize the exec session through TACACS+ and accept the returned privilege level | Roles come from the server, not from each device |
| Command authorization | Authorize commands at every privilege level you use, including configuration mode where the platform separates it | Per command allow and deny, with denied attempts recorded |
| Accounting | Start stop accounting for exec sessions and for commands at every level; system events if supported | The audit trail described above |
| Timeouts and dead time | Short connect timeout; mark a dead server for a few minutes | Logins stay fast during a server failure |
| Key storage | Strongest available local encryption for the stored key | CISA recommends this over reversible encodings |
| TLS (where supported) | Port 300, trust anchor, client certificate and key, server name for SNI and identity checks, TLS required with no fallback | RFC 9887 mutual authentication |
Step 5: build a lab PKI for TLS
For a lab, a small private CA is enough. In production use your existing internal PKI and its revocation service.
mkdir -p ~/tac-ca && cd ~/tac-ca
# Lab CA
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
-keyout ca.key -out ca.crt -days 825 -subj "/CN=Lab TACACS CA"
# Server certificate for a dedicated subdomain
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
-keyout server.key -out server.csr -subj "/CN=tacacs1.aaa.example.net"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 397 \
-extfile <(printf "subjectAltName=DNS:tacacs1.aaa.example.net\nextendedKeyUsage=serverAuth")
# Client certificate for one device, identified by its management IP
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
-keyout edge1.key -out edge1.csr -subj "/CN=edge1.mgmt.example.net"
openssl x509 -req -in edge1.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out edge1.crt -days 397 \
-extfile <(printf "subjectAltName=DNS:edge1.mgmt.example.net,IP:10.20.0.11\nextendedKeyUsage=clientAuth")
The server name lives under a subdomain used only for TACACS+ servers, which keeps you inside RFC 9887's wildcard rule if you later choose a wildcard. The client certificate carries both a dNSName and an iPAddress, the two subjectAltName types RFC 9887 says servers must be able to match.
Step 6: add the TLS listener
The tac_plus-ng manual shows a listener on port 300 with tls = yes and certificate settings in the configuration block that listener maps to. The manual's option list spells the CA setting tls cafile while its example uses tls ca-file, so confirm the spelling your build accepts with -P. Put TLS on its own listener, and, following RFC 9887, ideally on a different host from any remaining legacy server.
id = spawnd {
listen { port = 300 realm = tls tls = yes }
spawn { instances min = 1 instances max = 8 }
}
id = tac_plus-ng {
realm tls {
tls cert-file = /usr/local/etc/tac-ca/server.crt
tls key-file = /usr/local/etc/tac-ca/server.key
tls ca-file = /usr/local/etc/tac-ca/ca.crt
tls verify-depth = 2
tls accept expired = no
tls.peer.cert.validation = cert
# devices, profiles and rulesets as in Step 2, without legacy keys
}
}
tls.peer.cert.validation = cert asks for full chain validation; the manual's default is any, which also accepts a pinned fingerprint. Fingerprint pinning (tls.peer.cert.sha256) is useful for small sites without a CA but gives up revocation, which RFC 9887 requires for certificate based authentication. The manual notes that PSK and certificate authentication can share a port for TLS 1.3 because the daemon inspects the ClientHello, and that it logs TLS details through log variables such as tls.conn.version and tls.peer.cert.subject, which are worth adding to your access log format.
Check the handshake from the lab host with the device certificate:
openssl s_client -connect tacacs1.aaa.example.net:300 -tls1_3 \
-servername tacacs1.aaa.example.net \
-cert ~/tac-ca/edge1.crt -key ~/tac-ca/edge1.key -CAfile ~/tac-ca/ca.crt \
-verify_return_error </dev/null
# Expect: Protocol TLSv1.3, Verify return code: 0 (ok)
# A TLS 1.2 attempt must fail
openssl s_client -connect tacacs1.aaa.example.net:300 -tls1_2 </dev/null
Step 7: migrate devices and close port 49
- Inventory which device models and software versions support RFC 9887 TACACS+ over TLS. Those that do not stay on legacy servers, on separate hosts, as RFC 9887 section 6.2 describes.
- Issue a client certificate to each capable device and install the CA chain locally so a CA outage does not block logins.
- Move capable devices to a server group that contains only TLS servers. Do not configure a device with both TLS and legacy servers for longer than the cutover itself; RFC 9887 says the migration phase "should be considered insecure until it is fully completed".
- Confirm in the server logs that each device connects with TLS 1.3 and the expected certificate subject.
- Remove legacy keys for migrated devices from the legacy server, and block TCP 49 from those devices at the management firewall.
- Rotate remaining legacy secrets, and track the legacy population down to zero.
Comparison: TACACS+, RADIUS, RADIUS over TLS, SSH certificates and local accounts
| Approach | Transport protection | Central identity | Per command authorization | Per command audit | Works when the AAA server is down | Main risk |
|---|---|---|---|---|---|---|
| TACACS+ legacy (RFC 8907) | MD5 based obfuscation; no integrity | Yes | Yes | Yes | Only via fallback | Secret recovery and tampering on an untrusted path |
| TACACS+ over TLS 1.3 (RFC 9887) | TLS 1.3, mutual authentication | Yes | Yes | Yes | Only via fallback | PKI and revocation operations; mixed migration states |
| RADIUS over UDP (RFC 2865) | Password hiding and packet authenticators built on MD5 and the shared secret | Yes | Not by design | Session level | Only via fallback | MD5 based integrity weaknesses; most attributes in cleartext |
| RADIUS over TLS (RFC 6614; RADIUS/1.1 in RFC 9765) | TLS; RADIUS/1.1 removes MD5 entirely | Yes | Not by design | Session level | Only via fallback | Experimental status; device support varies |
| SSH user certificates | SSH transport; short lived certificates signed by a CA | Yes, at issuance | No; role via principals or forced commands | Device logs only | Yes, until the certificate expires | CA key protection; no central per command decision |
| Per device local accounts | Whatever the login protocol provides | No | Local privilege only | Device logs only | Yes | Shared, stale passwords; no offboarding |
The pattern most operators settle on: TACACS+ over TLS for interactive device administration with per command authorization and accounting, RADIUS for network access, SSH certificates or API tokens for automation that talks to device APIs, and a handful of vaulted local break glass accounts. Automation through NETCONF or RESTCONF often still authenticates against the same AAA server, so the same audit expectations apply to service accounts.
How to monitor and harden an existing TACACS+ deployment today
Most networks will run legacy TACACS+ for a while. These controls come from RFC 8907 section 10.5 and the CISA guidance:
- Put TACACS+ on the management network only. RFC 8907 says it "MUST be deployed over networks that ensure privacy and integrity" and "separated from other traffic". Source it from a management interface or VRF, and filter TCP 49 everywhere else.
- Accept only known clients. The server must define individual clients and accept connections only from them.
- Use a unique secret per device, at least 16 characters (the RFC says servers and clients must support 32), random, rotated, never logged, and never reused as a TLS PSK.
- Reject the unencrypted flag. Search configurations for empty keys left from debugging.
- Prefer challenge response authentication types where your identity system supports them, and do not let the same credential be used for both challenge based and plain types, as RFC 8907 section 10.5.3 recommends.
- Disable FOLLOW redirection, SENDAUTH and SENDPASS if your server still offers them.
- Keep the AAA server separate from the main corporate directory, as CISA recommends, and require multi factor authentication for administrators.
- Ship accounting and authorization logs off the TACACS+ server to storage the network team cannot edit, mask sensitive arguments, and alert on denied commands, logins outside change windows and any use of a local fallback account.
- Watch for traffic on TCP 49 from unexpected sources, and for TLS handshake failures on port 300, which can indicate expired certificates before they cause an outage.
Common mistakes
- Treating the obfuscation as encryption. RFC 8907 says plainly that it is not. Any path you do not control end to end needs TLS or an encrypted tunnel.
- One secret for every device. A single recovered secret then decrypts and forges traffic for the whole estate. RFC 8907 requires servers to support per client secrets and to warn on reuse.
- Short or human secrets. Offline MD5 search makes them cheap to recover. Generate them.
- Leaving an empty key after debugging. Bodies then cross the network in cleartext.
- Shell authorization without command authorization. A privilege level of 15 with no per command checks gives the server no say over what happens next and leaves a thin audit trail.
- Accounting only for configuration commands. Show commands that dump configurations or keys matter during an investigation too.
- Fallback to a shared local password. The emergency path becomes the easiest path.
- Granting everything to "console" sessions. The login method is a field the device asserts; over legacy transport it can be changed in flight.
- Running TLS and legacy on the same host and port. RFC 9887 requires separate ports and recommends separate hosts, and forbids client fallback to non TLS.
- Pinning fingerprints and forgetting revocation. Fingerprints are convenient but RFC 9887 expects revocation checking for certificate authentication.
- No plan for an unreachable CA. Install chains locally and test logins with the CA offline.
- Linking the AAA server straight to the corporate directory. CISA recommends keeping it separate so a directory compromise does not hand over the network.
FAQ
What is TACACS+ used for?
Administrator access to network devices. Routers, switches, firewalls and some servers send login, authorization and accounting requests to a central TACACS+ server, so access is controlled and recorded in one place instead of on every device.
What port does TACACS+ use?
Legacy TACACS+ uses TCP port 49. TACACS+ over TLS 1.3, defined in RFC 9887, uses TCP port 300, registered with IANA as "tacacss" on 15 July 2025.
Is TACACS+ encrypted?
Not in any modern sense in its legacy form. RFC 8907 obfuscates the packet body with an MD5 based pad and calls it obfuscation, not encryption, with no meaningful integrity, privacy or replay protection. RFC 9887 adds real encryption and integrity with TLS 1.3.
What is the difference between TACACS+ and RADIUS?
TACACS+ runs over TCP, obfuscates the whole body, and separates authentication, authorization and accounting so devices can authorize and log each command. RADIUS runs mainly over UDP, hides only the password and a few attributes, and combines authentication with authorization. TACACS+ suits device administration; RADIUS suits network access.
Is RFC 8907 a standard?
No. RFC 8907 is Informational. It documents the common subset of a 1997 draft that implementations already followed. RFC 9887, which adds TLS 1.3 and updates RFC 8907, is on the Standards Track.
Can I run TLS and legacy TACACS+ on the same server?
RFC 9887 says TLS servers must not accept non TLS connections and must listen on a separate port, and it recommends against running TLS and non TLS servers on the same host. Run legacy servers separately for devices that cannot do TLS, and keep that group shrinking.
How long should a TACACS+ shared key be?
RFC 8907 says servers and clients must support keys of at least 32 characters, clients should not accept keys shorter than 16, and administrators should configure at least 16. Generate random keys, one per device.
Does TACACS+ support multi factor authentication?
The protocol supports multi step prompts through its GETDATA, GETUSER and GETPASS replies, which servers can use to ask for a one time code or trigger a push. Whether MFA works depends on your server and identity backend. CISA recommends phishing resistant MFA for administrative access to routers.
What happens if the TACACS+ server is down?
The device tries the next configured server, then whatever fallback method you configured, usually local accounts. RFC 8907 tells clients to treat an ERROR reply as if the server were unreachable. Design that fallback deliberately with vaulted, per device accounts and alerts.
Do I need TACACS+ if I use SSH keys or certificates?
SSH certificates authenticate administrators without a live server, but they do not give a central per command allow or deny decision or a central command log. Many teams use both: certificates or a vault for the login, and TACACS+ for authorization and accounting.
Where Safeguard fits
Safeguard does not run a TACACS+ or RADIUS server, configure network devices, manage device certificates or audit router configurations, and nothing in the steps above depends on it. The honest connection is the software around your AAA service. A TACACS+ server is software you build or package: tac_plus-ng is C code linked against OpenSSL, its test tooling pulls Perl modules from CPAN, and many teams ship it, a log forwarder and their own network automation in container images built from public base images with Python or Go dependencies.
For that software, Safeguard's software composition analysis inventories the dependencies in your repositories, container scanning shows which images carry which package versions, and SBOM generation and analysis records the result in SPDX or CycloneDX. The platform shows which projects contain a given component and version, vulnerability matching and reachability analysis help decide what to fix first, and policies and gates can stop a build that pulls a known vulnerable version. When an OpenSSL advisory lands, "which of our AAA and automation images still ship the old library" becomes a quick question. See using SBOMs to find affected products fast. Firmware on the routers and switches themselves is different: there, fixes come from the device vendor's software releases.
A TACACS+ server, its TLS library and the automation around it are software built from open source components, and every rebuilt server image or automation container pulls those dependencies again. The fit here is indirect, since device firmware fixes still come from the device vendor, but the AAA and automation software your team builds is squarely in scope for the steps below.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
These demos show dependency, SBOM and remediation workflows, not TACACS+ servers or network device management. You can download Safeguard and follow the CLI docs to try them on your own projects.
This demo sets up the Safeguard runner on your own machine, approves it with its device code and scans from the terminal. Pointed at the container image your team builds for its TACACS+ server or log forwarder, the same scan lists the packages and versions inside it, including the TLS library, and their known vulnerabilities.
Click through it at your own pace, or open it full screen.
This demo is a real CLI session: you ask the assistant to fix a lodash CVE, it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, and pushes nothing. The same approval flow applies when a dependency in your network automation repository needs an upgrade.
Click through it at your own pace, or open it full screen.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. It is a useful pattern for network teams who want to ask about the dependency risk in their automation and AAA tooling without granting broad access.
Click through it at your own pace, or open it full screen.
Quick check
Your legacy TACACS+ uses a strong, unique secret per device. Can an attacker on the management path still change an authorization request without being detected?
Yes, if they can predict the plaintext of the byte they want to change. The obfuscation is an XOR with an MD5 based pad and has no integrity check, so known plaintext reveals the pad byte at that offset and any change goes undetected. RFC 8907 uses the authen_method field as its example. Only a transport with integrity, such as TLS 1.3 under RFC 9887, closes this.
During migration, a device is configured with a TLS server on port 300 and a legacy server on port 49 as backup. What is wrong with that?
An attacker who blocks port 300 forces the device onto the legacy server, which is a downgrade. RFC 9887 says clients must not fall back to non TLS when TLS fails, including during migration, and that the period where a client has both kinds of server configured should be minimized. Move each capable device to TLS only servers.
Sources
- RFC 8907: The Terminal Access Controller Access-Control System Plus (TACACS+) Protocol (September 2020)
- RFC 9887: TACACS+ over TLS 1.3 (December 2025)
- IETF Datatracker: draft-ietf-opsawg-tacacs-tls13
- RFC 1492: An Access Control Protocol, Sometimes Called TACACS (July 1993)
- RFC 9105: A YANG Data Model for TACACS+ (August 2021)
- RFC 2865: Remote Authentication Dial In User Service (RADIUS) (June 2000)
- RFC 6614: Transport Layer Security (TLS) Encryption for RADIUS (May 2012)
- RFC 9765: RADIUS/1.1, Leveraging ALPN to Remove MD5 (April 2025)
- RFC 6151: Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms (March 2011)
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- RFC 9325: Recommendations for Secure Use of TLS and DTLS (BCP 195)
- IANA: Service Name and Transport Protocol Port Number Registry
- CISA and partners: Enhanced Visibility and Hardening Guidance for Communications Infrastructure (December 2024)
- NIST SP 800-53 Rev. 5: Security and Privacy Controls for Information Systems and Organizations
- NIST OSCAL content: SP 800-53 Rev. 5 control catalog (JSON)
- event-driven-servers project page (tac_plus-ng, tac_plus, MAVIS)
- event-driven-servers on GitHub (README and build instructions)
- tac_plus-ng manual (text version in the repository)
- tac_plus-ng sample configuration: tac_plus-ng.cfg-shadow
- Wireshark: TACACS+ (tacplus) display filter reference
Last reviewed: 23 October 2026. Device support for RFC 9887 varies by platform and software release, and the TACACS+ YANG and authentication work in the IETF is still moving; check your vendor documentation and the linked RFCs before planning a migration.