This article explains how to install tac_plus-ng, which features significant enhancements to authentication backends, including support for LDAP, Microsoft Active Directory, RADIUS, PAM, and custom scripts (e.g., Perl or C).
Notes:
Please check KB99363 [juniper.net] if you want to know how to configure TACACS Plus server to authenticate Juniper devices using an OpenLDAP backend and authorize permissions based on group membership retrieved from the OpenLDAP server.
1) You can follow the installation instructions provided on the following webpage to install tac_plus-ng:
https://github.com/MarcJHuber/event-driven-servers
2) Alternatively, you can follow the steps below to install tac_plus-ng, here using Ubuntu (24.04.2 LTS 64-bit) as example:
<- Installation:
sudo apt update
sudo apt install -y build-essential git libpcre2-dev libssl-dev libldap2-dev
cd ~/
git clone https://github.com/MarcJHuber/event-driven-servers.git
cd event-driven-servers; ./configure; make
sudo make install
<- Then check path of newly install tac_plus-ng:
lab@vm$ whereis tac_plus-ng
tac_plus-ng: /usr/local/sbin/tac_plus-ng
<- Create directories used for storing authentication, authorization and accounting info:
sudo mkdir -p /var/log/tac_plus-ng/{authentication,accounting,access}
<- Check usage of tac_plus-ng:
lab@vm$ tac_plus-ng
Usage: tac_plus-ng [ <Options> ] <configuration file> [ <id> ]
Options:
-P parse configuration file, then quit
-1 enable single-process ("degraded") mode
-v show version, then quit
-b force going to background
-f force staying in foreground
-i <child-id> select child configuration id
-I <spawnd-id> select spawnd configuration id
-p <pid-file> write master process ID to the file specified
-d <debug-level> set debugging level
Version: abd35fcecb4c9a4edccaf6a0c3067ef2c699f999/PCRE2/CRYPTO/SSL
3) Example config used by tac_plus-ng, it includes two test users: jtac1 and jtac2
Because a user template must be configured on the Juniper device to enable remote authentication methods such as TACACS+ or RADIUS,
for example below, if you want to use jtac1 and jtac2 for testing, please configure below user template on Juniper devices:
configure private
set system login user net_admin_users class super-user
set system login user operator_user class operator
set system tacplus-server <server_ip> secret lab123 port 49
delete system authentication-order
set system authentication-order [tacplus password]
commit
Then start tac_plus-ng:
lab@vm$ tac_plus-ng <conf_file_name>
### Start of example config of tac_plus-ng ###
#!/usr/local/sbin/tac_plus-ng
id = spawnd {
listen = { address = 0.0.0.0 port = 49 }
# Optional: IPv6 support
# listen = { address = :: port = 49 }
spawn = { instances min = 1 instances max = 10 }
background = yes
}
id = tac_plus-ng {
log accesslog { destination = /var/log/tac_plus/access/%Y/%m/access-%m-%d-%Y.txt }
log accountinglog { destination = /var/log/tac_plus/accounting/%Y/%m/accounting-%m-%d-%Y.txt }
log authenticationlog { destination = /var/log/tac_plus/authentication/%Y/%m/authentication-%m-%d-%Y.txt }
access log = accesslog
accounting log = accountinglog
authentication log = authenticationlog
mavis module = external {
# Set environment variables for LDAP connection
setenv LDAP_SERVER_TYPE = "openldap"
setenv LDAP_HOSTS = "ldap://10.85.186.242:389"
setenv LDAP_BASE = "dc=jtac,dc=net"
setenv LDAP_BINDDN = "cn=admin,dc=jtac,dc=net"
setenv LDAP_BINDPW = "lab123"
setenv REQUIRE_TACACS_GROUP_PREFIX = 0
setenv LDAP_FILTER = "(uid=%s)"
setenv LDAP_GROUP_FILTER = "(|(&(objectClass=groupOfNames)(member=%s))(&(objectClass=posixGroup)(memberUid=%u)))"
# Optional: setenv REQUIRE_TACACS_GROUP_PREFIX = 0
# Do NOT set USE_TLS unless you are sure; see notes below
exec = /usr/local/lib/mavis/mavis_tacplus-ng_ldap.pl
# Use mavis for all authentication backends
login backend = mavis
user backend = mavis
pap backend = mavis
# Define access policies
host = Juniper {
address = 0.0.0.0/0
key = "lab123"
group net_admin_users
group net_operator
group net_Read_Only
group net_ts
user jtac1 {
password login = clear lab123
member = net_admin_users
user jtac2 {
member = net_operator
profile net_admin_users_profile {
script {
if (service == junos-exec) {
set local-user-name = admin_user
permit
deny
profile net_operator_users_profile {
set local-user-name = operator_user
profile net_RO_users_profile {
set local-user-name = RO_user
set deny-commands = "(^configure .*)|(^scp .*)|(^op .*)|(^telnet .*)|(^request .*)"
profile net_ts_users_profile {
set local-user-name = ts_user
set allow-commands = "(^ping .*)|(^traceroute .*)"
ruleset {
rule Juniper_rule {
enabled = yes
if (group == net_admin_users) {
profile = net_admin_users_profile
if (group == net_operator) {
profile = net_operator_users_profile
if (group == net_Read_Only) {
profile = net_RO_users_profile
if (group == net_ts) {
profile = net_ts_users_profile
### End of example config of tac_plus-ng ###