Transition Plain TACACS+ Clients to TACACS+ over TLS
This guide is for hosts that already use local TACACS+ clients such as
pam_tacplus or
audisp-tacplus, but need to
move the network path to TACACS+ over TLS.
Those clients speak classic TACACS+ over TCP. tacacsrs-agentd can run on the
same host as a local TACACS+ proxy, accept the existing client traffic on
loopback, and open protected upstream connections to TACACS+ servers.
pam_tacplus / audisp-tacplus
|
| TACACS+ over loopback TCP
v
tacacsrs-agentd --service-mode tacacs-proxy
|
| TACACS+ over TLS 1.3
v
upstream TACACS+ servers
When to Use This
Use this transition path when:
- Existing consumers are hard-wired to
pam_tacplus,audisp-tacplus, or another client that already emits TACACS+ packets. - You want to avoid changing PAM or auditd integration code during the TLS cutover.
- You can install and run
tacacsrs-agentdon the same host as the legacy client. - The local host boundary is acceptable for the temporary plain TACACS+ hop.
Do not use this as proof that the legacy client itself supports TLS. The legacy
client still speaks plain TACACS+ to localhost. The TLS security boundary starts
at tacacsrs-agentd and covers the upstream network path.
What Changes
Move these responsibilities from each legacy client into tacacsrs-agentd:
| Concern | Before | After |
|---|---|---|
| Upstream server list | Repeated server= entries in PAM or audisp config | --server-addr flags or --config in tacacsrs-agentd |
| Upstream transport security | None, because the client only speaks classic TACACS+ | --use-tls, mTLS, TLS PSK-DHE, or TLS PSK-only in tacacsrs-agentd |
| Failover | Client-specific server-list behavior | Ordered upstream failover in tacacsrs-agentd |
| Local client target | Remote TACACS+ server | Loopback TACACS+ proxy endpoint |
Keep these in the legacy client configuration:
- PAM stack placement and control flags.
- TACACS+
service,protocol,login, timeout, and accounting options that describe the local request. - The downstream TACACS+ shared secret, unless the client and server are configured to use the TACACS+ unencrypted flag.
Shared Secret Compatibility
Proxy mode currently uses the selected upstream server's TACACS+ shared secret for the downstream client connection too. That means:
- Keep the legacy client
secret=value and thetacacsrs-agentd --shared-secretvalue aligned. - Use the same TACACS+ shared secret across the upstream servers used by one proxy deployment.
- Avoid a cutover where the local client secret differs from the upstream server secret unless the proxy gains a separate downstream-secret setting.
- If the upstream TLS server disables TACACS+ packet obfuscation entirely, verify whether the legacy client can send unencrypted TACACS+ packets before relying on proxy mode.
TLS protects the upstream connection, but it does not replace the downstream
TACACS+ packet format expected by pam_tacplus or audisp-tacplus.
Start the Local Proxy
Use a loopback TCP endpoint for pam_tacplus and audisp-tacplus because these
clients are normal TACACS+ TCP clients. Port 9049 is useful for testing because
it does not require privileged bind rights. Use 127.0.0.1:49 only when the
legacy client cannot be pointed at a non-standard port and the daemon has the
required permissions.
TLS Server Authentication
# Load this value from the host's secret manager.
TACACS_SHARED_SECRET='replace-with-secret-from-secret-store'
sudo tacacsrs-agentd \
--server-addr tacacs1.example.com:449 \
--server-addr tacacs2.example.com:449 \
--service-mode tacacs-proxy \
--proxy-endpoint 127.0.0.1:9049 \
--shared-secret "$TACACS_SHARED_SECRET" \
--use-tls \
-vv
TLS mTLS
# Load this value from the host's secret manager.
TACACS_SHARED_SECRET='replace-with-secret-from-secret-store'
sudo tacacsrs-agentd \
--server-addr tacacs1.example.com:449 \
--server-addr tacacs2.example.com:449 \
--service-mode tacacs-proxy \
--proxy-endpoint 127.0.0.1:9049 \
--shared-secret "$TACACS_SHARED_SECRET" \
--use-tls \
--client-certificate /etc/tacacs/client.crt.pem \
--client-key /etc/tacacs/client.key.pem \
-vv
TLS PSK-DHE
TLS PSK support requires a build with the psk feature. PSK-DHE is the preferred
PSK mode because it adds ephemeral key exchange. If no PSK key-exchange mode is
specified, tacacsrs-agentd defaults to PSK-DHE with the preferred group order
secp384r1,secp256r1.
# Load these values from the host's secret manager.
TACACS_SHARED_SECRET='replace-with-secret-from-secret-store'
TACACS_TLS_PSK='replace-with-tls-psk-from-secret-store'
sudo tacacsrs-agentd \
--server-addr tacacs1.example.com:449 \
--server-addr tacacs2.example.com:449 \
--service-mode tacacs-proxy \
--proxy-endpoint 127.0.0.1:9049 \
--shared-secret "$TACACS_SHARED_SECRET" \
--use-tls \
--psk-identity host01@example.com \
--psk-key "$TACACS_TLS_PSK" \
--psk-key-exchange-groups secp384r1,secp256r1 \
-vv
TLS PSK-only
Use PSK-only only for interoperability with a peer that cannot negotiate
PSK-DHE. PSK-only cannot be combined with --psk-key-exchange-groups.
# Load these values from the host's secret manager.
TACACS_SHARED_SECRET='replace-with-secret-from-secret-store'
TACACS_TLS_PSK='replace-with-tls-psk-from-secret-store'
sudo tacacsrs-agentd \
--server-addr legacy-tacacs.example.com:449 \
--service-mode tacacs-proxy \
--proxy-endpoint 127.0.0.1:9049 \
--shared-secret "$TACACS_SHARED_SECRET" \
--use-tls \
--psk-identity host01@example.com \
--psk-key "$TACACS_TLS_PSK" \
--psk-key-exchange psk-only \
-vv
Repoint pam_tacplus
Change only the TACACS+ server target first. Keep the PAM control flow and the request-shaping options that already work in the environment.
Before:
auth required pam_tacplus.so server=tacacs1.example.com:49 secret=<existing-shared-secret> login=pap
account required pam_tacplus.so server=tacacs1.example.com:49 secret=<existing-shared-secret> service=shell protocol=ssh
session required pam_tacplus.so server=tacacs1.example.com:49 secret=<existing-shared-secret> service=shell protocol=ssh
After:
auth required pam_tacplus.so server=127.0.0.1:9049 secret=<existing-shared-secret> login=pap
account required pam_tacplus.so server=127.0.0.1:9049 secret=<existing-shared-secret> service=shell protocol=ssh
session required pam_tacplus.so server=127.0.0.1:9049 secret=<existing-shared-secret> service=shell protocol=ssh
If the existing PAM configuration repeats several server= values for failover,
replace them with the one local proxy endpoint. Put the ordered upstream list in
tacacsrs-agentd instead.
For validation, use the same PAM test tool and PAM service file already used for
local changes. pamtester is useful for proving authenticate, account, open
session, and close session behavior before editing production PAM services.
Repoint audisp-tacplus
audisp-tacplus uses a TACACS+ accounting configuration with options derived
from pam_tacplus. Keep the auditd plugin wiring and audit rules unchanged, and
move only the TACACS+ server target to the local proxy.
Before:
server=tacacs1.example.com:49
secret=<existing-shared-secret>
service=shell
protocol=ssh
After:
server=127.0.0.1:9049
secret=<existing-shared-secret>
service=shell
protocol=ssh
Then restart or reload auditd/audisp using the operating-system procedure for the
host. Validate by producing a known audited command event and confirming that the
upstream TACACS+ server receives the accounting record through tacacsrs-agentd.
Rollout Plan
- Inventory every
pam_tacplusandaudisp-tacplusconfiguration file on the host. Recordserver=,secret=,service,protocol,login, timeout, and anyacct_alluse. - Deploy
tacacsrs-agentdin proxy-only mode on a loopback test port such as127.0.0.1:9049. - Configure the upstream TLS mode that matches the TACACS+ server: server-auth TLS, mTLS, PSK-DHE, or PSK-only.
- Test with a non-production PAM service or a controlled auditd event.
- Repoint one production consumer at a time to the local proxy endpoint.
- After confidence is established, remove direct outbound access from the host to the old plain TACACS+ server path so only
tacacsrs-agentdcan reach upstream TACACS+ servers.
Behavioral Differences to Check
acct_allfan-out is not the same as agent failover. Proxy mode sends each downstream connection to one selected upstream server. If accounting must be written to multiple collectors, plan a separate fan-out path.pam_tacplusrecords the successful authentication server for later account/session phases. After the cutover, that server is always the local proxy; upstream server choice is owned bytacacsrs-agentd.- Debug logging in these legacy clients may include passwords or secrets. Use debug briefly, collect logs carefully, and disable it after validation.
- Local loopback TACACS+ is still plain TACACS+. Bind the proxy to loopback, avoid exposing the proxy endpoint on non-loopback interfaces, and restrict host access to the process and config files that need it.
Rollback
Keep a copy of the previous PAM and audisp configuration. Roll back by restoring
the previous remote server= entries, or by leaving the clients pointed at the
local proxy while starting tacacsrs-agentd against the old plain upstream
server without --use-tls. The second option keeps the local configuration
stable while isolating the rollback to the daemon command line or service unit.