Setting up a TACACS+ server for user authentication

When you have a bigger number of network devices and User-Groups with different permissions, it’s easier to use a central instance for authentication than to configure every user on each device manually.

TACACS+ (Terminal Access Controller Access Control System extended) provides such a functionality and is available for free.

I will explain the steps for setting up TACACS+ on Debian Etch from source.
The apt-repository already provides tac_plus version F4.0.4.alpha, but there seems to be some bugs, when using PAM authentication.
TACACS+ offers several authentication methods like . I use PAM method, because it offers you a simple way to manage user passwords.
Every user can change his own password and it resides protected at the place where it should be.
There are different branches of the original daemon available in World Wide Web. I decided for the source code provided by

Shrubbery is also maintainer of the awesome tool RANCID (Really Awesome New Cisco config Differ). I will post about that later…


  • a running Debian Etch installation (PAM should be included per default)
  • Build utilities (simply execute apt-get install build-essential to install the necessary tools/libs)
  • PAM libraries (apt-get install libpam0g-dev)
  • TCP-Wrapper libraries (apt-get install libwrap0-dev)


Getting and installing tac_plus

As mentioned above, you first have to get the source code from Shrubbery’s FTP Server. Either via browser or ftp client

debian:/DOWNLOAD# ftp
Connected to
220 ftp FTP server (Version wu-2.6.2(2) Fri Mar 4 22:01:20 UTC 2005) ready.
Name ( anonymous
331 Guest login ok, send your complete e-mail address as password.
230 Guest login ok, access restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 CWD command successful.
ftp> cd tac_plus
250 CWD command successful.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for /bin/ls.
total 3820
-r--r--r--  1 7053  wheel     116 Mar  2 20:13 00README
-r--r--r--  1 7053  wheel    1224 Mar  2 20:13 MD5
dr-xr-x---  2 7053  wheel     512 Dec 13  2007 OLD
-r--r--r--  1 7053  wheel  247588 Jul  5  2006 tacacs+-F4.0.4.10.tar.gz
-r--r--r--  1 7053  wheel  247789 Jul 18  2006 tacacs+-F4.0.4.11.tar.gz
-r--r--r--  1 7053  wheel  248145 Aug 16  2006 tacacs+-F4.0.4.12.tar.gz
-r--r--r--  1 7053  wheel  249108 Sep 15  2006 tacacs+-F4.0.4.13.tar.gz
-r--r--r--  1 7053  wheel  248779 Dec 13  2006 tacacs+-F4.0.4.14.tar.gz
-r--r--r--  1 7053  wheel  252532 Dec 13  2007 tacacs+-F4.0.4.15.tar.gz
-r--r--r--  1 7053  wheel  260479 Mar  2 20:11 tacacs+-F4.0.4.16.tar.gz
226 Transfer complete.
ftp> get tacacs+-F4.0.4.16.tar.gz
local: tacacs+-F4.0.4.16.tar.gz remote: tacacs+-F4.0.4.16.tar.gz
200 PORT command successful.
150 Opening BINARY mode data connection for tacacs+-F4.0.4.16.tar.gz (260479 bytes).
226 Transfer complete.
260479 bytes received in 2.17 secs (117.5 kB/s)
ftp> quit
221-You have transferred 260479 bytes in 1 files.
221-Total traffic for this session was 262371 bytes in 3 transfers.
221-Thank you for using the FTP service on ftp.
221 Goodbye.

After downloading, untar/uncompress the source and change to the resulting directory

debian:/DOWNLOAD# tar xzf tacacs+-F4.0.4.16.tar.gz
debian:/DOWNLOAD# cd tacacs+-F4.0.4.16

I submit some configure-flags to adjust the installation to my desired paths

./configure --prefix /opt/tac-plus

When configure script runs through without errors, you can build and install tac_plus with a simple “make” followed by a “make install

debian:/DOWNLOAD/tacacs+-F4.0.4.16# make
/usr/bin/make  all-am
make[1]: Entering directory `/DOWNLOAD/tacacs+-F4.0.4.16'
.   (truncated)
make[1]: Leaving directory `/DOWNLOAD/tacacs+-F4.0.4.16'
debian:/DOWNLOAD/tacacs+-F4.0.4.16# make install
make[1]: Entering directory `/DOWNLOAD/tacacs+-F4.0.4.16'
test -z "/opt/tac-plus/bin" || /bin/mkdir -p "/opt/tac-plus/bin"
  /usr/bin/install -c 'tac_pwd' '/opt/tac-plus/bin/tac_pwd'
  /usr/bin/install -c 'tac_plus' '/opt/tac-plus/bin/tac_plus'
test -z "/opt/tac-plus/share/man/man3" || /bin/mkdir -p "/opt/tac-plus/share/man/man3"
 /usr/bin/install -c -m 644 './regexp.3' '/opt/tac-plus/share/man/man3/regexp.3'
test -z "/opt/tac-plus/share/man/man5" || /bin/mkdir -p "/opt/tac-plus/share/man/man5"
 /usr/bin/install -c -m 644 './tac_plus.conf.5' '/opt/tac-plus/share/man/man5/tac_plus.conf.5'
test -z "/opt/tac-plus/share/man/man8" || /bin/mkdir -p "/opt/tac-plus/share/man/man8"
 /usr/bin/install -c -m 644 './tac_plus.8' '/opt/tac-plus/share/man/man8/tac_plus.8'
 /usr/bin/install -c -m 644 './tac_pwd.8' '/opt/tac-plus/share/man/man8/tac_pwd.8'
test -z "/opt/tac-plus/share/tacacs+" || /bin/mkdir -p "/opt/tac-plus/share/tacacs+"
 /usr/bin/install -c -m 644 'users_guide' '/opt/tac-plus/share/tacacs+/users_guide'
test -z "/opt/tac-plus/share/tacacs+" || /bin/mkdir -p "/opt/tac-plus/share/tacacs+"
 /usr/bin/install -c 'tac_convert' '/opt/tac-plus/share/tacacs+/tac_convert'
make[1]: Leaving directory `/DOWNLOAD/tacacs+-F4.0.4.16'

The binaries tac_plus and tac_pwd will be installed in /opt/tac-plus/bin.
Manuals and an user-guide resides in /opt/tac-plus/share.

Preparing your Debian to use the new installed tac_plus

To easy start and stop the daemon or adding/removing from/to runlevels, i created a start script which is compatible to Debians rcconf.
The original /etc/init.d/tac-plus served as a template

# Provides:          tac-plus
# Required-Start:    $network
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: Start tac-plus server.
# Description:       Run the tac-plus server listening for
#                    AAA ( access, acounting and autorization request )
#                    from routers or RAS (remote access servers) via
#                    tacacs+ protocol
DESC="Tacacs+ server"
OTHER_OPTS="-d 256"                             # Default, if no /etc/default/tac-plus available
CONFIG_FILE="/etc/tac-plus/tacacs.conf"         # Default, if no /etc/default/tac-plus available
test -f $DAEMON || exit 0
if [ -r /etc/default/tac-plus ] ; then
        . /etc/default/tac-plus
case "$1" in
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --pidfile /var/run/$
                --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --pidfile /var/run/$
                --exec $DAEMON
        echo "$NAME."
        echo "Usage: $N {start|stop}" >&2
        exit 1
exit 0

Create the file /etc/default/tac-plus with start parameters for the rc-script

OTHER_OPTS="-d 16 -L"

The command-line options and the debug values will be explained below, but “16″ seems to be a good value…

When you want to use with inetd instead standalone, don’t forget to examine your /etc/services file for an entry like this one

tacacs          49/tcp                          # Login Host Protocol (TACACS)
tacacs          49/udp

If it’s missing, you have to create it first or your deamon won’t start.

Creating a configuration-file for the tac_plus daemon

The first example /etc/tac-plus/tacacs.conf is very simple and uses the authentication method “cleartext”.
This is not recommended, because the user editing the tacacs configuration file can see all user passwords.

key = "TaCaCsKeY"
accounting file = /var/log/tac_acc.log
user = testuser {
        login = cleartext "test123"
user = $enable$ {
        login = cleartext "cc"

The second example uses “PAM” authentication method and groups for different users:

  • admin group with all permissions
  • show_users group with permission to execute only  ”show ip interface” commands
key = "TaCaCsKeY"

# Daemon-Log --> /var/log/tac_plus.log
# Logging of priv-15 commands
accounting file = /var/log/tac_acc.log

# create user net_admin with useradd -m net_admin and assign him a password
user = net_admin {
  member = admins
  name = "Netadmin"

# user show needn't exist in the system
user = show {
  member = show_users
  name = "show_user"

# Create the des password with the tac_pwd command
user = $enable$ {
  login = des "ROwd6b1jo/OZg"

## Usergroups
# Users with "show ip/interface" permission (no password required)
group = show_users {
  default service = deny
  login = nopassword
  cmd = quit {
   permit .*
  cmd = show
   permit ip
   permit interface
   deny .*

# Admin users
group = admins {
  default service = permit
  login = PAM

Starting the daemon

With the prepared rc-script and the configuration files /etc/default/tac-plus and /etc/tac-plus/tacacs.conf, you could start the deamon with /etc/init.d/tac-plus start.

When /var/log/syslog or /var/log/tac_plus.log didn’t show error messages, the deamon has successfully started and is listening for requests at tcp/49

debian:~# /etc/init.d/tac-plus start
Starting Tacacs+ server: tac_plus.
debian:~# tail -f /var/log/syslog 

Mar  5 22:30:26 debian tac_plus[11863]: Reading config
Mar  5 22:30:26 debian tac_plus[11863]: Version F4.0.4.16 Initialized 1
Mar  5 22:30:26 debian tac_plus[11863]: tac_plus server F4.0.4.16 starting
Mar  5 22:30:26 debian tac_plus[11864]: Backgrounded
Mar  5 22:30:26 debian tac_plus[11865]: uid=0 euid=0 gid=0 egid=0 s=0
debian:~# netstat -tunlp | grep :49
tcp        0      0    *               LISTEN     11816/tac_plus     

Configuring the network device to use TACACS+ for authentication

There are several devices supporting TACACS+, but i am only experienced in Cisco and Juniper.

Here’s an example for Cisco, that enables authentication and accounting over TACACS+.
When TACACS+ authentication fails, the local user fallback_user (only IOS) and the configured enable-secret can be used to gain access.

Template for IOS
aaa new-model
aaa authentication login default group tacacs+ local
aaa authentication enable default group tacacs+ enable

aaa authorization exec default group tacacs+ if-authenticated
aaa authorization commands 0 default group tacacs+ none
aaa authorization commands 1 default group tacacs+ none
aaa authorization commands 15 default group tacacs+ none
aaa authorization config-commands

aaa accounting send stop-record authentication failure
aaa accounting exec default start-stop group tacacs+
aaa accounting commands 0 default start-stop group tacacs+
aaa accounting commands 1 default start-stop group tacacs+
aaa accounting commands 15 default start-stop group tacacs+
aaa accounting connection default start-stop group tacacs+
aaa accounting system default start-stop group tacacs+

username fallback_user password 0 *password*
enable secret 0 *enable secret*

tacacs-server host *TACACS server IP*
tacacs-server timeout 2
tacacs-server directed-request

! Note:  Some IOS need a leading 0 or 7 (cleartext/encrypted)
tacacs-server key *TACACS server key*

! to make sure, that tacacs-requests always come from the same IP (good for firewalls/ACLs)
ip tacacs source-interface *desired source interface*
Template for CatOS
set authentication login tacacs enable console primary
set authentication login tacacs enable telnet primary
set authentication login tacacs disable http
set authentication enable tacacs enable console primary
set authentication enable tacacs enable telnet primary
set authentication enable tacacs disable http
set tacacs server *TACACS server IP* primary
set tacacs attempts 2
set tacacs directedrequest enable
set tacacs key *TACACS server key*
set tacacs timeout 5

And here’s an example for JunOS.
Note: as a difference to Cisco, you can always login with the fallback_user even if TACACS+ server is available

Juniper set statements:
set system authentication-order [ tacplus password ]
set system tacplus-server <server ip> secret "<tacacs-key>"
set system tacplus-server <server ip> source-address <tacacs source ip>
set system accounting events [ login change-log interactive-commands]
set system accounting destination tacplus
# local user, when TACACS+ fails
set system login user fallback_user uid 2000
set system login user fallback_user class superuser
set system login user fallback_user authentication encrypted-password "<md5 password>"
# user remote must exist. Otherwise tacacs auth won't work.
set system login user remote full-name tacacs_user
set system login user remote uid 9999
set system login user remote class super-user
system {
    authentication-order [ tacplus password ];
    tacplus-server {
        <tacacs-server ip> {
            secret "<tacacs key>";
            source-address <tacacs source ip>;
    accounting {
        events [ login change-log interactive-commands ];
        destination {
    login {    
        user fallback_user {
            uid 2000;
            class superuser;
            authentication {
                encrypted-password "<md5 password>";
        user remote {
            full-name tacacs_user;
            uid 9999;
            class super-user;

Try, if it works…

After inserting the configuration snippet, you should be able to login with user “net_admin” and the assigned password.
For the user “net_admin”, there are no restrictions. All priv-15 commands will be logged to /var/log/tac_acc.log

Furthermore, you can login with user “show” . Here you are restricted to the specified show commands.

All successful and unsuccessful logins are logged to /var/log/tac_plus.log and /var/log/syslog.

Here’s an output from /var/log/tac_plus.log

Thu Mar  5 23:27:35 2009 [11865]: session.peerip is
Thu Mar  5 23:27:35 2009 [11912]: connect from gate []
Thu Mar  5 23:27:40 2009 [11912]: login query for 'net_adm' tty0 from gate rejected
Thu Mar  5 23:27:40 2009 [11912]: login failure: net_adm gate ( tty0
Thu Mar  5 23:27:42 2009 [11865]: session.peerip is
Thu Mar  5 23:27:42 2009 [11913]: connect from gate []
Thu Mar  5 23:27:49 2009 [11913]: login query for 'net_admin' tty0 from gate accepted
Thu Mar  5 23:27:49 2009 [11865]: session.peerip is
Thu Mar  5 23:27:49 2009 [11914]: connect from gate []
Thu Mar  5 23:27:52 2009 [11865]: session.peerip is
Thu Mar  5 23:27:52 2009 [11915]: connect from gate []
Thu Mar  5 23:27:53 2009 [11915]: enable query for 'net_admin' tty0 from gate accepted

You can see the following:

  • User net_adm tries to log in (→ wrong username) to router gate (red)
  • User net_admin loggs in successfully login router router gate (blue)
  • User net_admin successfully enter enable mode on router gate (green)

And here’s an example for the accounting log /var/log/tac_acc.log

Thu Mar 5 23:36:18 2009 gate net_admin tty0 async start task_id=24 timezone=UTC service=shell
Thu Mar 5 23:36:41 2009 gate net_admin tty0 async stop  task_id=24 timezone=UTC service=shell priv-lvl=15 cmd=configure terminal <cr>
Thu Mar 5 23:36:54 2009 gate net_admin tty0 async stop  task_id=25 timezone=UTC service=shell priv-lvl=15 cmd=logging buffered <cr>
Thu Mar 5 23:37:07 2009 gate net_admin tty0 async stop  task_id=24 timezone=UTC service=shell disc-cause=1    disc-cause-ext=9     
pre-session-time=19     elapsed_time=49 stop_time=1014975481


  • User net_admin has successfully logged in
  • net_admin entered configuration mode
  • net_admin executed the command “logging buffered
  • and disconnected
  • Sessions lasts 49 sec
  • All happened on router gate


Command line parameters

debian:/opt/tac-plus/bin# /opt/tac-plus/bin/tac_plus
Usage: tac_plus -C <config_file> [-GghiLPstv] [-B <bind address>] [-d <debug level>] [-l <logfile>] [-p <port>] [-u <wtmpfile>]
        -G      stay in foreground; do not detach from the tty
        -g      single thread mode
        -h      display this message
        -i      inetd mode
        -L      lookup peer addresses for logs
        -P      parse the configuration file and exit
        -s      refuse SENDPASS
        -t      also log to /dev/console
        -v      display version information

Debug values

8       authorisation debugging
16      authentication debugging
32      password file processing debugging
64      accounting debugging
128     config file parsing & lookup
256     packet transmission/reception
512     encryption/decryption
1024    MD5 hash algorithm debugging
2048    very low level encryption/decryption
--> 248 = 128 + 64 + 32 + 16 + 8

Download templates…

Title: etc_default_tac-plus
File: etc_default_tac-plus
Size: 124 B
Title: etc_init
File: etc_init.d_tac-plus
Size: 1 kB
Title: tacacs
File: tacacs.conf
Size: 795 B
Title: tacacs_cisco
File: tacacs_cisco
Size: 2 kB
Title: tacacs_junos
File: tacacs_junos
Size: 1 kB
Title: tacacs_simple
File: tacacs_simple.conf
Size: 176 B

8 comments to Setting up a TACACS+ server for user authentication

  • david

    Hey I came across an issue.. I can telnet into the cisco switch using TACACS but I tried to telnet using default username and password and I couldn’t. Is it because TACACS server is already available ??? or it might be some other reason

    Thanks i advance

  • Allen

    Don’t know if you still need an answer, david, but yes, that is why. Cisco devices will not let you log in with a local username or password if the TACACS server is available.

  • bugsy

    hai..your blog its so helping me for create tacacs..but i have a problem.

    like this :
    tail -f /var/log/tac_plus.log
    Sat Oct 1 19:30:17 2011 [13650]: Reading config
    Sat Oct 1 19:30:17 2011 [13650]: Version F4.0.4.19 Initialized 1
    Sat Oct 1 19:30:17 2011 [13650]: tac_plus server F4.0.4.19 starting
    Sat Oct 1 19:30:17 2011 [13651]: Backgrounded
    Sat Oct 1 19:30:17 2011 [13652]: Error get_socket: bind 49 Address already in use

    but from /etc/service port 49 just tacacs.

    i need your help, thanks

  • admin

    it seems that there is already a service running on Port tcp/49.
    What’s the output of netstat -tunlp ?

  • Don

    Hi all,
    start-time is logged in UTC in the Tacacs accounting log. Anyone knows, if this is configurable?
    Thanks in advance

  • Nacho

    Don, i have the same problem. Could you solve it?

  • Imms

    Dear All,
    I have an issue where the tacacs_plus process is not able to write the logs into the log files. Do I need to do anything with regard to the log files viz. changing the permission of the log files, for instance tacacs.log

    Thanks in advance.

  • Nic

    I just wanted to say that this was the only tutorial that actually worked when following it. You have all of the right information. I got my tacacs server running and my lab cisco switches / routers authentication.

    Thanks a lot for this. You taught me a lot.


Leave a Reply




You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>