This guide will walk you through the setup of a Linux based TACACS+ Authentication Server, using Ubuntu 18.04 (tested on Ubuntu 16.04 as well) that authenticates against a Windows Active Directory LDAP(S).
This guide assumes that you are familiar with installing and configuring a Ubuntu Server and can deploy or have already deployed a Windows Active Directory infrastructure.
Prerequisites
- Windows Server 2016 with Active Directory Services (Domain Controller or Read-Only Domain Controller)
- Ubuntu Server (tested on 16.04 LTS or 18.04 LTS)
Basic Network Topology
Below is an example network topology commonly found in a small to medium sized network.
Windows Active Directory Requirements
First, we will setup the required items in our Active Directory system.
- Create a service account that TACACS will use to bind and authenticate to our AD infrastructure. Be sure to use a secure password (16 characters or longer).
This is needed because Active Directory does not allow anonymous bindings by default and will not allow you to search the AD tree if you are not authenticated.
The user does not need any special permissions or group memberships.
- Create two security groups that TACACS will match against to identify what users and permission levels to assign authenticated users. In this example, we will create two security roles. The first being “ADMIN” level permissions, and the second being “TECHNICIAN” level permissions.
- Now create two user accounts, one for each type of user security level and add them to the security group associated with their account.
Username “test.admin” is a member of security group “R_ADMINS” and Username “test.tech” is a member of security group “R_TECHS” in our example
TACACS+ Server Installation
We have written an automated installation using Ansible for this TACACS+ Server to help users with deployment.
Lets move on to the TACACS Server installation on our Ubuntu Server. First, SSH into your Ubuntu Server and install the required packages.
packages="build-essential libnet-ldap-perl libpcre3-dev ntp ntpdate" sudo apt-get install -y ${packages}
Next, we are going to download the TACACS+ Server packages that includes the MAVIS (LDAP) authentication packages. This is provided by Marc Huber at pro-bono-publico.de.
wget http://www.pro-bono-publico.de/projects/src/DEVEL.201712190728.tar.bz2 -O tacacs_plus.tar.bz2 bzip2 -dc tacacs_plus.tar.bz2 | tar xvfp - mv PROJECTS tac_plus
Now, we will configure and build the tac_plus packages on our server.
cd tac_plus sudo ./configure --etcdir=/etc/tac_plus sudo make sudo make install
We now need to create the logging directories on our server because the package build process does not build these out for us. We will also make sure to set the permission on these directories so that our TACACS Server software can write to them.
sudo mkdir -p /var/log/tac_plus /var/log/tac_plus/access /var/log/tac_plus/accounting /var/log/tac_plus/authentication sudo chmod -R 755 /var/log/tac_plus
You can verify that the permissions were set correctly by running the following command:
stat --format '%a' /var/log/tac_plus >> OUTPUT << 755
We now need to verify that our MAVIS packages are working correctly. To do this execute the below command. You should see output as exampled.
/usr/local/lib/mavis/mavis_tacplus_ldap.pl < /dev/null >> OUTPUT << Default server type is 'tacacs_schema'. You *may* need to change that to 'generic' or 'microsoft'. LDAP_HOSTS not defined at /usr/local/lib/mavis/mavis_tacplus_ldap.pl line 277, <DATA> line 755.
If there are error messages saying “Can’t locate Net/LDAP.pm in @INC”, you need to double-check the configure
and make
commands at the beginning of the guide. Make sure they all completed successfully without any errors.
If your output above matches, then we can continue with adding the configuration for the TACACS server. Create a file tac_plus.cfg
in the /etc/tac_plus
folder.
Once created, we will open that file to add our configuration template.
sudo touch /etc/tac_plus/tac_plus.cfg sudo chmod 755 /etc/tac_plus/tac_plus.cfg sudo nano /etc/tac_plus/tac_plus.cfg
Next, we will copy and paste in the below template configuration into the tac_plus.cfg
file. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
#!/usr/local/sbin/tac_plus id = spawnd { listen = { address = 0.0.0.0 port = 49 } #Uncomment the line below for IPv6 support #listen = { address = :: port = 49 } spawn = { instances min = 1 instances max = 10 } background = yes } id = tac_plus { access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt mavis module = external { setenv LDAP_SERVER_TYPE = "microsoft" #If you are using Microsoft Global Catalog with secure LDAP (SSL) #setenv LDAP_HOSTS = "ldaps://{{AD-SERVER-IP}}:3269" #If you are using Microsoft Global Catalog with regular LDAP (non-SSL) setenv LDAP_HOSTS = "ldap://{{AD-SERVER-IP}}:3268" setenv LDAP_BASE = "{{LDAP-BASE-DN}}" setenv LDAP_SCOPE = sub ## Username ONLY Authentication setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))" ## Username + UPN Authentication [example: user@mydomain.lan] # setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))" setenv LDAP_USER = "{{LDAP-SERVICE-ACCOUNT-USERNAME}}" setenv LDAP_PASSWD = "{{LDAP-SERVICE-ACCOUNT-PASSWORD}}" #Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1 #I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does setenv EXPAND_AD_GROUP_MEMBERSHIP = 0 #Clear default setting of tacplus for AD_GROUP_PREFIX setenv AD_GROUP_PREFIX = "" #Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix setenv REQUIRE_TACACS_GROUP_PREFIX = 1 #DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE #TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED #FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED #setenv USE_TLS = 0 exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl } login backend = mavis user backend = mavis pap backend = mavis skip missing groups = yes host = world { #Allow any IPv4 device address = 0.0.0.0/0 #Uncomment the line below for IPv6 support #address = ::/0 #Uncomment the line below to inject a login prompt #prompt = "Put your custom welcome message here.\n" #Change this to your own secure TACACS+ key key = "{{TACACS-ENCRYPTION-KEY}}" } group = {{AD-ADMIN-GROUP}} { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands default command = permit #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = {{AD-ADMIN-GROUP}} } } group = {{AD-TECH-GROUP}} { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands default command = permit #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = {{AD-TECH-GROUP}} } } ### BEGIN USER ACCOUNT MAPS ### # user = user@example.net { # password = mavis # member = {{AD-ADMIN-GROUP}} # } # user = DEFAULT { # password = mavis # member = {{AD-TECH-GROUP}} # } ### END USER ACCOUNT MAPS ### }
Here is an example of our working tac_plus.cfg
file on our lab servers.
#!/usr/local/sbin/tac_plus id = spawnd { listen = { address = 0.0.0.0 port = 49 } #Uncomment the line below for IPv6 support #listen = { address = :: port = 49 } spawn = { instances min = 1 instances max = 10 } background = yes } id = tac_plus { access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt mavis module = external { setenv LDAP_SERVER_TYPE = "microsoft" #If you are using Microsoft Global Catalog with secure LDAP (SSL) #setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269" #If you are using Microsoft Global Catalog with regular LDAP (non-SSL) setenv LDAP_HOSTS = "ldap://172.16.10.10:3268" setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net" setenv LDAP_SCOPE = sub ## Username ONLY Authentication setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))" ## Username + UPN Authentication [example: user@mydomain.lan] # setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))" setenv LDAP_USER = "tacacs@tacacs-lab.datai.net" setenv LDAP_PASSWD = "My3ncryptedP@55w0rd" #Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1 #I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does setenv EXPAND_AD_GROUP_MEMBERSHIP = 0 #Clear default setting of tacplus for AD_GROUP_PREFIX setenv AD_GROUP_PREFIX = "" #Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix setenv REQUIRE_TACACS_GROUP_PREFIX = 1 #DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE #TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED #FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED #setenv USE_TLS = 0 exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl } login backend = mavis user backend = mavis pap backend = mavis skip missing groups = yes host = mgmtnet { #Allow any IPv4 device address = 172.16.10.0/24 #Uncomment the line below for IPv6 support #address = ::/0 #Uncomment the line below to inject a login prompt #prompt = "Put your custom welcome message here.\n" #Change this to your own secure TACACS+ key key = "dXVHBUYX36nqd3hA" } group = R_ADMINS { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands default command = permit #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = R_ADMINS } } group = R_TECHS { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands default command = permit #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = R_TECHS } } ### BEGIN USER ACCOUNT MAPS ### # user = user@example.net { # password = mavis # member = R_ADMINS # } # user = DEFAULT { # password = mavis # member = R_TECHS # } ### END USER ACCOUNT MAPS ### }
Now we need to validate the configuration file. After you have saved and exited the tac_plus.cfg
file, run the following command to verify everything was setup correctly.
/usr/local/sbin/tac_plus -P /etc/tac_plus/tac_plus.cfg
If tac_plus reports any errors, you will need to edit the tac_plus.cfg
file again and correct the errors. Do not proceed further until you have corrected all the reported errors. See http://www.pro-bono-publico.de/projects/tac_plus.html for a complete configuration reference. You may also want to view the file /usr/local/lib/mavis/mavis_tacplus_ldap.pl
for a detailed explanation of the available LDAP variables.
Now we need to create a SystemD service startup script for our TACACS server. Copy/Paste the below command into your SSH session. It will automatically create the required service startup script.
sudo cat << EOF > /etc/systemd/system/tac_plus.service # systemd configuration unit for tac_plus. # $Id: tac_plus.service,v 1.1 2011/07/22 17:04:03 marc Exp $ # # To enable the service: # sudo cp tac_plus.service /etc/systemd/system/ # sudo systemctl enable tac_plus.service # sudo systemctl start tac_plus.service # [Unit] Description=TACACS+ Service After=syslog.target [Service] ExecStart=/usr/local/sbin/tac_plus -f /etc/tac_plus/tac_plus.cfg KillMode=process Restart=always ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target EOF
Now you can enable the service for auto-startup and manually start the service.
sudo systemctl enable tac_plus.service sudo systemctl start tac_plus.service
To verify that the service started, you can run the following two commands.
# sudo systemctl status tac_plus.service >> OUTPUT << ● tac_plus.service - TACACS+ Service Loaded: loaded (/etc/systemd/system/tac_plus.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2019-01-01 16:13:57 UTC; 1h 8min ago Main PID: 21795 (tac_plus) Tasks: 3 (limit: 4662) CGroup: /system.slice/tac_plus.service ├─21795 tac_plus: 0 connections, accepting up to 600 more ├─21796 tac_plus: 0 connections └─21797 perl /usr/local/lib/mavis/mavis_tacplus_ldap.pl Jan 01 16:13:57 tacacs01 tac_plus[21795]: startup (version 201811291931) Jan 01 16:13:57 tacacs01 systemd[1]: Started TACACS+ Service. Jan 01 16:13:57 tacacs01 tac_plus[21795]: epoll event notification mechanism is being used Jan 01 16:13:57 tacacs01 tac_plus[21795]: bind to [0.0.0.0]:49 succeeded Jan 01 16:13:57 tacacs01 tac_plus[21796]: - Version 201811291931 initialized Jan 01 16:13:57 tacacs01 tac_plus[21796]: epoll event notification mechanism is being used # netstat -antp | grep ":49" >> OUTPUT << tcp 0 0 0.0.0.0:49 0.0.0.0:* LISTEN 21673/tac_plus: 0 c
We are now ready to verify that the TACACS services are authentication against our Active Directory server. Run the below commands on your Ubuntu server. You should get output similar to our example.
### Test Admin Account Authentication /usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.admin password123$ >> OUTPUT << {{ bunch of debug output ...}} Input attribute-value-pairs: TYPE TACPLUS TIMESTAMP mavistest-21804-1546360707-0 USER test.admin PASSWORD password123$ TACTYPE AUTH Output attribute-value-pairs: TYPE TACPLUS TIMESTAMP mavistest-21804-1546360707-0 USER test.admin RESULT ACK PASSWORD password123$ SERIAL OwS74pPKAjcEH89PojinNQ= DBPASSWORD password123$ TACMEMBER "R_ADMINS" TACTYPE AUTH ### Test Technician Account Authentication /usr/local/bin/mavistest -d -1 /etc/tac_plus/tac_plus.cfg tac_plus TACPLUS test.tech password123$ >> OUTPUT << {{ bunch of debug output ...}} Input attribute-value-pairs: TYPE TACPLUS TIMESTAMP mavistest-21806-1546360743-0 USER test.tech PASSWORD password123$ TACTYPE AUTH Output attribute-value-pairs: TYPE TACPLUS TIMESTAMP mavistest-21806-1546360743-0 USER test.tech RESULT ACK PASSWORD password123$ SERIAL gydnsgXHXyjeQaR2JaBlhw= DBPASSWORD password123$ TACMEMBER "R_TECHS" TACTYPE AUTH
From the output above, look specifically at the RESULT output and the TACMEMBER output. These should be “ACK” in the RESULT field, which means Active Directory responded and was successful, and the TACMEMBER value should match the security group associated with the user account. If you got NACK, BFD, or ERR in the RESULT field, that means something went wrong. You’ll want to double-check your Active Directory environment variables in the tac_plus.cfg
file.
For those that want to see what the traffic looks like, below is a PCAP (packet capture) of the LDAP communication between our TACACS Server and our Windows Active Directory Controller. The communication in this capture was done using none SSL based connections, which means everything is transmitted in CLEAR TEXT.
A handy Windows tool that may help you correctly configure the environment variables in LDAP is the Softerra LDAP Browser.
Do not continue further until you can run the above tests and get a valid response from the user authentication.
Juniper (JunOS) Device Configuration
We are now ready to configure one of our Juniper devices for TACACS authentication. For a full en-depth understanding on setting up Juniper TACACS Authentication, we would recommend that you read the Juniper documentation for your specific device and version of software. To learn more about the different permissions flags and users classes, we would recommend reading the Junos OS Login Classes documentation. ~ In this example, we will be using a Juniper vMX Router running JunOS v14.1
First, we will configure our Juniper device to utilize the TACACS authentication server as the primary source for account authorizations, with the standard “password” (local user accounts) as a fall-back in the event the TACACS server is offline or networking is unavailable. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
## Set the system authentication order ## set system authentication-order tacplus set system authentication-order password ## Set the TACACS server and encryption key ## set system tacplus-server {{TACACS-SERVER-IP}} secret "{{TACACS-ENCRYPTION-KEY}}" set system tacplus-server {{TACACS-SERVER-IP}} single-connection set system tacplus-server {{TACACS-SERVER-IP}} source-address {{ROUTER-SOURCE-IP}} ## Set the accounting logging services ## set system accounting events login set system accounting events change-log set system accounting events interactive-commands set system accounting destination tacplus
Here is an example configuration from our lab equipment.
set system authentication-order tacplus set system authentication-order password set system tacplus-server 172.16.10.11 secret "dXVHBUYX36nqd3hA" set system tacplus-server 172.16.10.11 single-connection set system tacplus-server 172.16.10.11 source-address 172.16.10.15 set system accounting events login set system accounting events change-log set system accounting events interactive-commands set system accounting destination tacplus ## SHOW SYSTEM >> OUTPUT << ## authentication-order [ tacplus password ]; tacplus-server { 172.16.10.11 { secret "$9$q.PQApOcrKNdw24aji1IEhKWxNdgaZLxUHk.zFSrleMX7NV"; ## SECRET-DATA single-connection; source-address 172.16.10.15; } } accounting { events [ login change-log interactive-commands ]; destination { tacplus; } }
Next, we need to add the configuration to the Juniper device that map the user account to the user class. This portion is very important and miss-understood very easily. The “user class” attributes can be built out however works best for your organization. However, you need to pay special attention to the “login user” accounts that are created.
The “login user” accounts that are created are NOT the “usernames” for every user that will be logging into the devices. These “names” are the direct mapping names that match what was created in the tac_plus.cfg
GROUP attributes. This is where the “magic” happens on the username > group mappings.
service = junos-exec { set local-user-name = R_TECHS }
Add the following configuration to your Juniper device. If you named your security groups differently, then you will have to adjust the configuration to match your changes.
set system login class administrators permissions all set system login class technicians permissions network set system login class technicians permissions view set system login class technicians permissions view-configuration set system login user R_ADMINS full-name "TACACS Administrators" set system login user R_ADMINS class administrators set system login user R_TECHS full-name "TACACS Technicians" set system login user R_TECHS class technicians
Once you have your configuration changes added to your device, commit them.
commit check commit
You are now ready to test your TACACS authentication with the different user accounts. SSH into your Juniper device on the management address and enter the username / password that you setup. For this example, we will be using “test.admin” and “test.tech”.
Upon a successful login, your TACACS server should be recording the accounting packets sent from the Juniper device. These accounting logs are located in /var/log/tac_plus/*
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
>> OUTPUT << 2019-01-01 14:55:25 -0500 172.16.10.15 test.admin ttyp1 172.16.10.10 start task_id=1 service=shell process*mgd[5143] cmd=login 2019-01-01 14:55:48 -0500 172.16.10.15 test.tech ttyp2 172.16.10.10 start task_id=1 service=shell process*mgd[5152] cmd=login
I have also provided a PCAP of the TACACS authentication request between the Juniper device and the TACACS server. This PCAP also includes the SSH traffic from the client to the Juniper device.
tacacs_ssh_juniper-authentication.zip
Cisco Device Configuration
We are now ready to configure one of our Cisco devices for TACACS authentication. For a full en-depth understanding on setting up Cisco AAA / TACACS Authentication, we would recommend that you read the Cisco Documentation for your specific device and version of software. Unfortunately, Cisco has done a very poor job on standardizing the configuration of the AAA settings per version and again per device type. ~ In this example, we will be using a Cisco IOS Router running version 15.4(1)T
First, we will configure our Cisco device to utilize the TACACS authentication server as the primary source for account authorizations, with the “local” user account as a fall-back in the event the TACACS server is offline or networking is unavailable. You will need to replace the variables that are specific to your configuration. These are identified by {{VARIABLE-NAME}}
in the template configuration.
! !-- !-- SET THE TACACS AUTHENTICATION SERVER !-- tacacs-server host {{TACACS-SERVER-IP}} tacacs-server directed-request tacacs-server key 0 {{TACACS-ENCRYPTION-KEY}} ! ! !-- !-- ESTABLISH A SECRET PASSWORD FOR CONSOLE !-- service password-encryption enable secret 0 {{SECURE-SECRET-PASSWORD}} ! !-- !-- SET THE AAA SECURITY ROLES !-- ! aaa new-model ! aaa authentication login default group tacacs+ local aaa authentication login console local ! aaa authorization config-commands aaa authorization exec default group tacacs+ local if-authenticated aaa authorization exec console if-authenticated aaa authorization commands 1 default group tacacs+ local if-authenticated aaa authorization commands 15 default group tacacs+ local if-authenticated ! aaa accounting exec default start-stop group tacacs+ aaa accounting commands 1 default start-stop group tacacs+ aaa accounting commands 15 default start-stop group tacacs+ ! ! aaa session-id common ! ! !-- !-- CONFIGURE CONSOLE FOR LOCAL AUTHENTICATION ONLY !-- line con 0 logging synchronous login authentication console ! !-- !-- CONFIGURE VTY FOR AAA AUTHENTICATION VIA SSH ONLY !-- line vty 0 4 logging synchronous transport input ssh ! !
Upon a successful login, your TACACS server should be recording the accounting packets sent from the Cisco device. These accounting logs are located in /var/log/tac_plus/*
cat /var/log/tac_plus/accounting/2019/01/accounting-01-01-2019.txt
2019-01-01 17:37:26 -0500 172.16.10.16 test.admin tty2 172.16.10.10 start task_id=35 timezone=EST service=shell 2019-01-01 17:37:29 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell priv-lvl=15 cmd=configure terminal <cr> 2019-01-01 17:37:32 -0500 172.16.10.16 test.admin tty2 172.16.10.10 stop task_id=35 timezone=EST service=shell disc-cause=1 disc-cause-ext=9 pre-session-time=3 elapsed_time=6 stop_time=1546382252
Cisco Command Access Control
Below is a tac_plus.cfg
configuration file that includes settings to allow restrictive ( permit | deny ) commands for the R_TECHS access group. This was put together to show how to restrict or permit access to specific commands to users.
#!/usr/local/sbin/tac_plus id = spawnd { listen = { address = 0.0.0.0 port = 49 } #Uncomment the line below for IPv6 support #listen = { address = :: port = 49 } spawn = { instances min = 1 instances max = 10 } background = yes } id = tac_plus { access log = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt accounting log = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt authentication log = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt mavis module = external { setenv LDAP_SERVER_TYPE = "microsoft" #If you are using Microsoft Global Catalog with secure LDAP (SSL) #setenv LDAP_HOSTS = "ldaps://172.16.10.10:3269" #If you are using Microsoft Global Catalog with regular LDAP (non-SSL) setenv LDAP_HOSTS = "ldap://172.16.10.10:3268" setenv LDAP_BASE = "DC=tacacs-lab,DC=datai,DC=net" setenv LDAP_SCOPE = sub ## Username ONLY Authentication setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(sAMAccountName=%s))" ## Username + UPN Authentication [example: user@mydomain.lan] # setenv LDAP_FILTER = "(&(objectClass=user)(objectClass=person)(userPrincipalName=%s))" setenv LDAP_USER = "tacacs@tacacs-lab.datai.net" setenv LDAP_PASSWD = "My3ncryptedP@55w0rd" #Setting UNLIMIT_AD_GROUP_MEMBERSHIP to 0 will cause a NACK response if the AD account is a member of more than one security group setenv UNLIMIT_AD_GROUP_MEMBERSHIP = 1 #I'm not 100% sure what EXPAND_AD_GROUP_MEMBERSHIP does setenv EXPAND_AD_GROUP_MEMBERSHIP = 0 #Clear default setting of tacplus for AD_GROUP_PREFIX setenv AD_GROUP_PREFIX = "" #Setting REQUIRE_TACACS_GROUP_PREFIX to 1 will cause a NACK response if the AD account is not a member of a security group with the required prefix setenv REQUIRE_TACACS_GROUP_PREFIX = 1 #DO NOT SET THE USE_TLS ENVIRONMENT VARIABLE #TLS WILL AUTOMATICALLY BE ENABLED IF NEEDED #FORCING THIS VARIABLE TO 1 WILL BREAK MAVIS IF TLS IS NEEDED #setenv USE_TLS = 0 exec = /usr/local/lib/mavis/mavis_tacplus_ldap.pl } login backend = mavis user backend = mavis pap backend = mavis skip missing groups = yes host = world { #Allow any IPv4 device address = 0.0.0.0/0 #Uncomment the line below for IPv6 support #address = ::/0 #Uncomment the line below to inject a login prompt #prompt = "Put your custom welcome message here.\n" #Change this to your own secure TACACS+ key key = "dXVHBUYX36nqd3hA" } group = R_ADMINS { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands default command = permit #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = R_ADMINS } } group = R_TECHS { #Permit all services by default default service = permit #Users will need to re-enter their AD password for the enable password (feel free to customize this however you want) enable = login ### ### Cisco IOS Authentication ### service = shell { #Permit all commands # default command = permit default command = deny #Permit all command attributes default attribute = permit #Set privilege level to 15 on IOS/XE set priv-lvl = 15 ##========================================## ## COMMAND ACCESS CONTROL RULES ## ##========================================## # Enter enable mode cmd = enable { permit .* } # Enter global configuration of terminal cmd = configure { permit terminal.* } # Exit disable mode cmd = disable { permit .* } # Exit any configuration mode cmd = exit { permit .* } # Jump back to enable mode cmd = end { permit \r } # Ping cmd = ping { permit .* } # Traceroute cmd = traceroute { permit .* } # Show any configuration parameter cmd = show { permit .* } # Save running-configuration cmd = copy { permit "running-config startup-config <cr>" } # Write running-configuration to memory cmd = write { permit "memory <cr>" } # Clear commands cmd = clear { permit "counters FastEthernet.*" permit "counters GigabitEthernet.*" permit "counters Vlan.*" permit "counters Port-channel.*" } # "Do" commands run from configuration mode. Since "do" commands # don't autoexpand, the shortest forms possible have to be allowed. cmd = do { # Allow shortened form of "ping" permit pi.* # Allow shortened form of "traceroute" permit tr.* # Allow shortened form of "show" permit sh.* } # Enter interface configuration mode cmd = interface { permit FastEthernet.* permit GigabitEthernet.* } # Set interfaces to default cmd = default { permit FastEthernet.* permit GigabitEthernet.* } # IP commands cmd = ip { permit route.* permit address.* permit "verify unicast.*" } # IPv6 commands cmd = ipv6 { permit route.* permit address.* permit "verify unicast.*" } # Removing configuration parameters cmd = no { permit "ip route.*" permit "ipv6 route.*" permit description.* permit "ip address.*" permit "ipv6 address.*" permit "ip verify unicast.*" permit "ipv6 verify unicast.*" permit "cdp enable <cr>" permit "shutdown <cr>" permit "switchport <cr>" permit "switchport mode <cr>" permit "switchport access vlan .*" permit nonegotiate.* permit "switchport private-vlan host-association.*" permit "spanning-tree portfast edge <cr>" permit service-policy.* } # Allow adding descriptions cmd = description { permit .* } # Allow IP commands cmd = ip { permit address.* permit "verify unicast.*" } # Allow IPv6 commands cmd = ipv6 { permit address.* permit "verify unicast.*" } # Allow switchport commands cmd = switchport { # Allow the 'switchport' command without allowing all # other switchport commands. permit ^<cr> permit "mode access" permit "access vlan.*" permit "mode private-vlan host" permit nonegotiate permit "private-vlan host-association.*" permit host } # Allow spanning-tree commands cmd = spanning-tree { permit "portfast edge" permit "portfast disable" } # Allow CDP enable cmd = cdp { permit enable } # Allow mls qos for VLANs cmd = mls { permit "qos vlan-based <cr>" } # Allow service policy commands cmd = service-policy { permit .* } # Allow shutdown command cmd = shutdown { permit ^<cr> } #Uncomment the line below for NX-OS support #set shell:roles="\"network-admin vdc-admin\"" #Uncomment the line below for IOS XR support #set task = "#root-system" } ### ### Juniper JunOS Authentication ### service = junos-exec { set local-user-name = R_TECHS } } ### BEGIN USER ACCOUNT MAPS ### # user = user@example.net { # password = mavis # member = R_ADMINS # } # user = DEFAULT { # password = mavis # member = R_ADMINS # } ### END USER ACCOUNT MAPS ### }