Quantcast
Channel: The Data Plumber
Viewing all 77 articles
Browse latest View live

Networking Heresy?

$
0
0

Software Defined Networking, and it’s latest incarnation SD-WAN seem to be all the rage at the moment.  Having seen presentations from vendors large and small on the subject recently at Networking Field Day 10 I am still given to thinking there are a few things that get glossed-over by the vendors quite often.  Foremost in my mind, is this (potentially heretical thought):

It is all very well creating virtual or ‘overlay’ networks which run over other networks to suit your purposes, but as someone famous once said, you can’t change the laws of physics.   Packets must ultimately flow across a medium – wires, fibres or waves.  The media doesn’t give a flying fart whether the packet is naked, or clothed in layers MPLS or GRE headers – if that medium is congested and doesn’t support any form of packet prioritisation, your data is down the dunny.

There’s a trade-off here that perhaps not many people understand when they are shown smooth presentations by manufacturers.  It seems to me that:

  1. Efficient use of network connectivity requires deep understanding from end to end.
  2. Efficient deployment of network connectivity requires abstraction and overlays (which equals loss of understanding of lower layer protocols).
  3. Efficient operation of network connectivity…  well… let’s hope it’ll be fine so long as nothing goes wrong. 

The WAN as we know it today is a stitched together mass of string, brown paper and tape. Lots of protocols, access methods and people somehow working together to satisfy the diverse needs of billions of organisations and people.  Because of this, operating a WAN can be a complicated matter. But as Matt says in his blog, although infrastructure is important, it

… should be invisible. I believe the real-world, practical point behind saying “infrastructure doesn’t matter anymore” is that we are finally getting around to practicing the absolute truth that for the vast majority of organizations, the infrastructure is not a revenue generator.

That’s the business driver, but bullet points 1 and 2 above are diametrically opposed to each other.

Cisco’s IWAN product was demonstrated to us at NFD10. It brings together their rich feature-set under a slick graphical UI quite nicely.  But ultimately it uses DMVPN to abstract the underlay from the overlay (see 1:10 in this video), uses VRFs to abstract transport from service, and uses a GUI to abstract policy creation from enforcement.  In the software-defined datacenter, companies such as Juniper are belatedly trying to correlate the overlay with the underlay (see this video). This is an important step forward I think, but it is only possible because the datacenter WAN is under the end-user’s control.  Since the WAN will almost always be someone else’s network you’ll never get anything better than ‘multi-path best-effort’ packet forwarding. Crude – but effective for most?

Maybe we can take a long view on this. I, and many like me are from the dinosaur school of thought that likes to have everything nicely worked-out, predictable and efficient. Presumably such tugs-of-war happened when the first programming languages arrived on the computing scene.  Yes, they enable great strides to be made where many hours of coding in assembler might have been required before – but the abstraction from low-level functions must surely introduce huge inefficiency?  And how do we troubleshoot now everything’s obscured?

The reality of that scenario is that such technological advances enable great progress, and although they will still need troubleshooting, the advances they enable outweigh the downsides.  Although SD-WAN is a difficult thing to sum up given its current nascent state (as John Herbert says in this article), we are on the road to simplicity.  Your average IT manager would surely rejoice if networking were as simple as Nuage’s very nice video shows it is capable of being.



Managing Junos Commit Time

$
0
0

I’ve been working with an ISP that is going to be using a large amount of configuration in the ‘groups’ section.  The statements there will be inherited into the main configuration using the ‘apply-groups’ statement.

This is a clever way of writing commands once and having them apply to multiple parts of the configuration.  At a basic level you could match on interfaces beginning with ‘ge-‘ or ‘xe-‘ and set an MTU on them all using one group statement. This MTU setting would not appear in the main configuration unless the configuration was displayed using “show | display inheritance”. There’s a nice explanation of how groups work over at this Packetpushers blog.

The downside is that if large amounts of configuration work is done in groups, applying the config can become slow during the ‘commit’ process.  

What happens under the hood when the user issues a commit in Junos?  You can see what happens if you issue a ‘commit | display detail’.  There is an example in this KB article.   As you can see there is a lot of parsing for commit-scripts, interface ranges and apply-groups at the start.  The config in these needs to be expanded and incorporated into the configuration at commit time.  A new config database is then created, and the various daemons are notified that they need to read in their config.  Finally the rollback configs are rotated, and of course if you have two REs in your router, this all has to happen again on the backup RE!

So when the groups section becomes large, this results in a lot of extra work for the mgd daemon to perform at commit time.

The ISP I’m working with has several config elements that I had not come across until now in their system stanza that aims to improve commit time:

system {
    commit {
        fast-synchronize;
        synchronize;
        persist-groups-inheritance;
    }
    configuration-database {
        extend-size;
    }
  }
}
fast-synchronize: causes the commits to happen on both REs in parallel, rather than doing the master first, then the backup. This may help a bit.  Arrived with Junos 12.2 it seems.
 
synchronize: this is a standard command to make sure both REs get the changes.  It isn’t relevant to improving commit time, but is necessary here.
persist-groups-inheritance:  According to this, the command increases performance during commits for groups that use wildcards.  For example matching on ge-* on a device that has a lot of gigabit ports.
configuration-database extend-size:  Valid since Junos 13.2, this command allows the config database to use more memory on an as-needed basis.  It might help in situations where processes (such as mgd which does the commit) temporarily have high memory usage requirements, e.g, parsing of a config with a lot of group inheritance during commit time. More info on this is available  here and here.  If you want to you can get clever and specify which process and how much memory as well if you want.
Caveat – I’ve not tested these myself yet, but thought it worth recording some little-known configuration knobs for future reference.   If I get a chance I will try enabling each in turn and and then record the time it takes for each commit.

Searching for routes with non-IP address next-hops

$
0
0

I am searching in a series of large Redback config files for certain things, and I’m beginning to find Regex and Atom really powerful for this.  The files are sometimes 20,000 lines long, and there are over 100 of them.

Of course I should script this, and someone more script savvy than me would do that in a trice, but I’ve come up with a part manual solution.  Perhaps I will build it into a script later.

What I need to do is search each file for any ‘ip route’ commands that have a named interface as a next-hop rather than an IP address.   So to do this, I am doing inverse-matching on four sets of numbers separated by dots.

I also need to exclude the keyword ‘context’ and the interface ‘null0’. This took me a while to figure out.

Here’s my pattern match:

ip route [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+ (?![0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|context|null0)

This matches the string:

 ip route 172.21.0.0/16 MADEUPINTERFACE

But not:

 ip route 172.16.4.0/24 10.0.0.1

The expression is not very accurate, since it could match IP addresses like 999.999.999.999, but that does not matter in this case.  Since the config came from a router, the router’s CLI has already vetted for illegal IP addresses anyway.

When you do this in Atom’s Regex find box it becomes even more useful.  As you can see below, I’ve got the regex in the search box.  Atom colours things for you to tell you when you’ve done something wrong in the expression.

Once you’ve got your expression right, you simply have to click down the other files in the same directory (shown in the sidebar) to easily apply the same regex to those.  A massive timesaver.

regex-in-atom


Microsoft on Macs – ARGH!

$
0
0

I moved my Mum onto a Mac a few years ago, and the calls for support dropped off dramatically.  She’s a very non-technical user, but tries hard to get to grips with the modern technology.

She’s recently decided she’d like to put some photos in a Word document, and write a message underneath – to send round to people at Christmas, you know?  How hard can that be?

Over the phone, I told her to go to Photos, select the photo and do Edit | Copy from the menu.  Then go to Word and do Edit | Paste to put it in the document.

Nope.

Tried it on my Mac, and sure enough, Word doesn’t know there’s anything in the clipboard to paste!   But if you open anything else (e.g. Textedit) it works fine.

Not really sure whose problem this is, since Word is able to paste in an image that is not in Photos (i.e. an image on the hard disk).  Instructions for that are here:  https://support.office.com/en-in/article/Add-or-replace-a-picture-in-Office-for-Mac-2011-c0a7f0d4-ed59-4183-8fe1-ed615b94cf80?ui=en-US&rs=en-IN&ad=IN

For a novice user like mum, finding that simple things like cutting and pasting are broken is extremely confusing. Of course she thinks it is her fault, when in fact it is the technology’s fault.


Python script to generate RADIUS users

$
0
0

Just for future reference, I wrote this quick script using python to generate RADIUS users in the Freeradius /etc/raddb/users file.  Makes light work of what I used to do rather painfully in Excel:

 

__author__ = 'amulheirn'

# Create lots of radius users for /etc/raddb/users file

interface = 'ge-0/2/0'        # Local source interface
ipaddr = '89.20.80.'          # First three octets of IP addr
startuser = 1                 # Start of the user range
enduser   = 20                # End of the user

for i in range (startuser, enduser):
    print 'user%d@customer.com     Cleartext-Password := \"password\"' % (i)
    print '                        Service-Type := \"Framed-User\",'
    print '                        Framed-Protocol := \"PPP\",'
    print '                        Framed-IP-Address := \"%s%d\",' % (ipaddr, i)
    print '                        Context-Name := \"tuk_llu\",'


print "======[END]====="

Freeradius setup on Ubuntu 14.04

$
0
0

Frustrated with a dilapidated installation of Freeradius 1.x in our lab, and conscious that it is unsupported any more, I decided to install a new Freeradius server.

Ubuntu 14.04.3 LTS is the platform I am installing it on, and this is a relatively fresh installation of Ubuntu server.   It needs to serve access-requests from a Redback and a Juniper router in our lab for both PPP and DHCP clients.

Install freeradius using ‘apt-get install freeradius’.  This pulls down Freeradius 2.1 as can be seen below:

Setting up freeradius (2.1.12+dfsg-1.2ubuntu8.1)

Edit the /etc/freeradius/clients.conf file to permit all hosts on the lab network (192.168.3.0/24) to be ‘clients’ of my new Freeradius server – as long as they use  a shared secret when authenticating.  To do this, include the following section:

client 192.168.3.0/24 {
      secret = testing123
      shortname = labnet-3
}

Copy /etc/freeradius/users to /etc/freeradius/users.originalfile so that we have a backup in case everything goes wrong.

Edit the /etc/freeradius/users file and  create a new user:

andrew Cleartext-Password := "password"
 Reply-Message = "Hello %{User-Name}"

Save the users file.

Test this locally using the ‘radtest’ command.  The format of this is:

root@labhost:/etc/freeradius# radtest
Usage: radtest [OPTIONS] user passwd radius-server[:port] nas-port-number secret [ppphint] [nasname]
 -d RADIUS_DIR Set radius directory
 -t <type> Set authentication method
 type can be pap, chap, mschap, or eap-md5
 -x Enable debug output
 -4 Use IPv4 for the NAS address (default)
 -6 Use IPv6 for the NAS address

So the command works like this – I just made up any number for the nas-port-number parameter:

root@labhost:/etc/freeradius# radtest andrew password localhost 123 testing123
Sending Access-Request of id 171 to 127.0.0.1 port 1812
 User-Name = "andrew"
 User-Password = "password"
 NAS-IP-Address = 192.168.3.237
 NAS-Port = 123
 Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=171, length=34
 Reply-Message = "Hello andrew"
root@labhost:/etc/freeradius#

 

All seems to be working.

Now to test it from the Juniper router, there is a useful test facility at the CLI, but first you need tell Junos about the RADIUS server by configuring something like this:

andy@juniper> show configuration access
radius-server {
 192.168.3.237 {
 port 1812;
 secret "$9$iHfz9Cu1Eyp0yKWxwsZUjHP5z36AuO"; ## SECRET-DATA
 source-address 192.168.3.79;
 }
}

profile labhost {
 authentication-order radius;
 radius {
 authentication-server 192.168.3.237;
 }
}
domain {
 map dvsr.dia {
 target-routing-instance ttb_internet;
 }
 map rpm.com {
 target-routing-instance ttb_internet;
 }
}
radius-options {
 revert-interval 60;
 request-rate 4000;
}

After committing this config, we can test if it works:

andy@nge001.gui> test aaa ppp user andrew password password profile labhost
 Authentication Deny
 Reply message : Hello andrew
 Reason : address-allocation-fail
 Received Attributes :
 User Name - andrew
 Virtual Router Name - default
 Agent Remote Id - NULL
 Client IP Address - 0.0.0.0
 Client IP Netmask - 0.0.0.0
 Primary DNS IP Address - 0.0.0.0
 Secondary DNS IP Address - 0.0.0.0
 Primary WINS IP Address - 0.0.0.0
 Secondary WINS IP Address - 0.0.0.0
 Primary DNS IPv6 Address - ::
 Secondary DNS IPv6 Address - ::
 Reply Message - Hello andrew
 Class Attribute - not set
 Service Type - 0
 Framed Pool - not set
 Client IPv6 Address - ::
 Client IPv6 Mask - null
 Framed IPv6 Prefix - ::/0
 Framed IPv6 Pool - not-set
 NDRA IPv6 Prefix - not-set
 Login IPv6 Host - ::
 Framed Interface Id - 0:0:0:0
[...OUTPUT OMITTED...]
 NAS Port Id - -0/0/0.0
 NAS Port - 4095
 NAS Port Type - 15
 Framed Protocol - 1
 Test complete. Exiting

 

As you can see, it did not – we got denied because of an IP address allocation failure.  But at least the two are talking!

If you do a ‘service freeradius stop’ and then start it again in debug mode, you can see the freeradius side of things quite nicely:

Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on authentication address 127.0.0.1 port 18120 as server inner-tunnel
Listening on proxy address * port 1814
Ready to process requests.

rad_recv: Access-Request packet from host 192.168.3.79 port 52305, id=102, length=161
 User-Name = "andrew"
 User-Password = "password"
 Service-Type = Framed-User
 Framed-Protocol = PPP
 Chargeable-User-Identity = ""
 Acct-Session-Id = "21481"
 ERX-Dhcp-Mac-Addr = "abcd.0000.0001"
 NAS-Identifier = "nge001.gui"
 NAS-Port = 4095
 NAS-Port-Id = "-0/0/0.0"
 NAS-Port-Type = Ethernet
 ERX-Pppoe-Description = "pppoe ab:cd:00:00:00:01"
 NAS-IP-Address = 192.168.3.79
# Executing section authorize from file /etc/freeradius/sites-enabled/default
+- entering group authorize {...}
++[preprocess] returns ok
++[chap] returns noop
++[mschap] returns noop
++[digest] returns noop
[suffix] No '@' in User-Name = "andrew", looking up realm NULL
[suffix] No such realm "NULL"
++[suffix] returns noop
[eap] No EAP-Message, not doing EAP
++[eap] returns noop
[files] users: Matched entry andrew at line 93
[files] expand: Hello %{User-Name} -> Hello andrew
++[files] returns ok
++[expiration] returns noop
++[logintime] returns noop
++[pap] returns updated
Found Auth-Type = PAP
# Executing group from file /etc/freeradius/sites-enabled/default
+- entering group PAP {...}
[pap] login attempt with password "password"
[pap] Using clear text password "password"
[pap] User authenticated successfully
++[pap] returns ok
# Executing section post-auth from file /etc/freeradius/sites-enabled/default
+- entering group post-auth {...}
++[exec] returns noop
Sending Access-Accept of id 102 to 192.168.3.79 port 52305
 Reply-Message = "Hello andrew"
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 0 ID 102 with timestamp +9
Ready to process requests.

 

The PPP user isn’t going to get logged in with so little configuration though.  I need to be able to assign him an IP address and put him in a routing-instance somehow.  I’ll do a followup post on how to achieve that.


PHPBB and website integration

$
0
0

I needed to integrate a website login with a phpBB3 forum recently, and this blog post came in really useful:  http://www.3cc.org/blog/2010/03/integrating-your-existing-site-into-phpbb3/

The only issue with it was the logout section – it uses $_GET, but when I implement this I get a message saying that this is an ‘illegal use of $_GET’.

Instead, the logout code that worked for me was this – it uses request_var() instead:

<?php
$cp = request_var('cp', '');
if ($cp == "logout") {
$user->session_kill();
$user->session_begin();
echo "Logged out";
}
?>

Junos Space – checking processes are running

$
0
0

After two miserable nights trying to upgrade Space 13.1R1.6 to 14.1R1.9,  I finally called up JTAC for some assistance.  For some reason the upgrade started, but never finished – the GUI remaining in ‘maintenance mode’ for several hours.

What they did:

Checked the services – all were showing as down:

service jmp-watchdog status
service jboss status
service jboss-dc status

Tried to start jboss-dc, but it complained that it couldn’t write or create /var/log/jboss.

Did the following to change ownership from root:root on the /var/log directory:

chown jboss:root /var/log

Did this:

service jboss-dc start
service jboss start

At this point the GUI started showing ‘Junos space is preparing to start  up’, and after 20 minutes it changed to say the applications were deploying.



Location of images on Junos Space after upload

$
0
0

Just a note for my own reference really –

The images you upload via the GUI to upgrade Space end up on the filesystem in /var/cache/jboss/jmp/<imageversion> directory.  In that directory is the actual image, plus a file called appVersionListFile.txt – this file seems to tell the system what other Space apps it is compatible with.

It seems to upload the image into this directory, and then extracts all the various .rpm files from it into /var/cache/jboss/jmp/payloads/<imageversion> directory.

 

I confirmed this by performing an ‘rm -rf <imageversion>’ on both the above directories, then uploading another image via the GUI again.  Both directories re-appeared.  I doubt this is recommended by TAC though, so do this at your own peril.

 


Forgotten ‘maintenance’ password for Junos Space

$
0
0

The maintenance users password can be reset in Junos Space if you still have access via the CLI:

  • SSH to the Space host
  • Log in as the admin user
  • Choose the debug option on the menu (6 or 7, depending on whether this is a VM or an appliance).  Just press the number, not the number followed by return!
  • Put in the admin user’s password again.  You’re now in the Centos shell.
  • Issue the command ‘htpasswd -sb /var/www/maintenance/maintPW maintenance <newpassword>

 

Simple as that…   I was never sure why an additional maintenance password was required as well as the admin user and the GUI super user password.  Makes it a pain to keep a record of, but there you go – presumably there’s a good reason.


EVPN – the basics

$
0
0

A great EVPN overview and detailed walkthrough from a colleague of mine… Nice and clear.

PACKETS AND STUFF

So I decided to take a deep dive into eVPN, I’ll mostly be looking into VLAN-aware bundling, as per RFC 7432 – and mostly because I think this will fit more closely, with the types of deployments most of the customers are used to – good old IRB interfaces and bridge-tables!

As everyone knows, VPLS has been available for many years now and it’s pretty widely deployed, most of the customers I see have some flavour of VPLS configured on their networks and use it to good effect – so why eVPN? what’s the point in introducing a new technology if the current one appears to work fine.

The reality is that multipoint layer-2 VPNs (VPLS) were never quite as polished as layer-3 VPNs, when layer-3 VPNs were first invented they became, and still are the in many cases the “go to” technology for layer-3 connectivity across MPLS networks, and…

View original post 4,444 more words


Junos Space Log Collector – Utilities

$
0
0

The Juniper documentation on log collector is a bit sparse to be honest, and once it is installed, SSHing to it doesn’t seem to produce a configuration menu any more.  In order to change its config, there are some scripts, but I had to dig around for them:

[root@LOG-COLLECTOR bin]# ls
adhoc.py disableExport.sh logcollectorWatchdog.py selfhealingES.py
agentScript.sh elasticDiskAllocation.py logcollectorWatchdog.pyc selfhealingES.pyc
agentUtilityScript.sh elasticDiskRollover.sh logcolmon.py startService.sh
bashUtils.sh enableExport.sh logcolmon.pyc stopService.sh
cleanZipLogs.sh generateReponse.pl lsStatisticsupdate.sh subsequentBootupdate.sh
collectSystemLogs.sh getMountLocation.sh monitorPacketDrop.sh support-diagnostics.sh
configureMailSetup.sh getRebootDetails.pl mountNfs.sh syslogForwardToggle.sh
configureNameServer.sh getSystemInfo networkScript.sh updateEtcHosts.sh
configureNode.sh getZipLogs.pl resizeFS.sh updateIndexerip.sh
configureNtp.sh initConf.pl resourceMonitoring validateIpAddress.sh
configureTimeZone.sh loadFirewal.sh rootWrapper whiteList.sh

[root@LOG-COLLECTOR bin]#

They are in this directory:

[root@LOG-COLLECTOR bin]# pwd
/opt/jnpr/bin
[root@LOG-COLLECTOR bin]#

 

An important thing to be sure of is that log collector does not have two interfaces – it should have only eth0.   If it gets an IP address on eth1, you might find that logging does not work.  This is probably because it received a DHCP address on eth1, and also has a default gateway on eth1 instead of eth0.

To get around the accidental configuration of eth-1, go into /etc/sysconfig/network-scripts and edit the file ifcfg-eth1.  This will probably look as follows:

[root@LOG-COLLECTOR network-scripts]# more ifcfg-eth1
DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet

Use Vi to edit the file and change ONBOOT to equal no.  Then issue the reboot command and once it has rebooted, you should find that there is only eth0.

I then realised that there was no static route, so I used one of the network scripts mentioned above to re-apply the IP address in the hope that it would create me a default route.

To reconfigure the network interfaces, run /opt/jnpr/bin/networkScript.sh.  Doing so looks like this:

[root@LOG-COLLECTOR bin]# ./networkScript.sh
1) Configure IP Address for eth0
2) Configure IP Address for eth1

Please enter your choice: 1

Setup eth0 interface

1) Configure IPV4 Address for eth0
2) Configure Mixed mode(IPV4 and IPV6) for eth0
3) Exit

Please enter your choice : 1

Setup IPV4 address for eth0 interface

Checking for IPV4 Address of the machine

Current IPV4 address is : 192.168.1.1

IPV4 Address for eth0 is already Configured.

Configure eth0 IP Address? [Y/N]
y

Enter the IP address:
192.168.1.1

Enter the Subnet Mask:
255.255.255.0

Enter the gateway IP
192.168.1.254


IP Entered is 192.168.1.1, netmask 255.255.255.0, gateway IP 192.168.1.254

Setting up the IP addresses


Indexer(127.0.0.1) cluster status is green.
logstash started.

Network Configuration Done !!!
You have new mail in /var/spool/mail/root
[root@LOG-COLLECTOR bin]#

Following this, I used the ‘route’ command to make sure the default gateway was set via eth0 now:

[root@LOG-COLLECTOR bin]# route
Kernel IP routing table
Destination     Gateway         Genmask      Flags Metric Ref Use Iface
192.168.1.0     *               255.255.255.0 U      0    0     0  eth0
link-local      *               255.255.0.0   U    1002   0     0  eth0
default         192.168.1.1     0.0.0.0       UG     0    0     0  eth0
[root@LOG-COLLECTOR bin]# ls

 

Finally, there’s some useful information on this forum posting about a few more things to check, including a healthcheck script that seems to check the various internal processes within Log Collector.  http://forums.juniper.net/t5/Network-Management/FAQ-Log-Collector-Deployment/ta-p/292769

 

 

 

 

 

 


Setting up vSRX and Space in VMware Fusion

$
0
0

I’m going to be travelling a bit in the near future and wanted an easy, laptop-based Juniper device and Junos Space instance to mess with. I’ve recently made some headway with CLI configlets and wanted to build on what I’ve got working.

I already run VMware Fusion on the Mac in order to run Ubuntu and Windows, so I figured that was the best thing to use. What I wanted was two VMs that could see each other and be accessed from the host machine, but without them being dependent on the host’s interfaces being up. Wifi access would be chargeable, and wired impossible – without making an ethernet loopback plug to bring the Mac’s interface up artifically, that is. So that ruled out both bridged and NAT type connections. What I needed was some kind of internal network within the host – Fusion seems to call this a ‘Private to my Mac’ connection.

My version of Fusion is 7.1.2 – it doesn’t seem to be the ‘Pro’ version, but I can’t confirm this. For some reason, the help isn’t vey helpful. You do some Googling and VMware Workstation information comes up, or help pages about what appear to be very old versions of Fusion. Anyway, a bit of experimentation and I figured it out.

If you go into the shell in OSX, and type ‘ifconfig’ you will see a variety of interfaces – two of which are ‘vmnet’ ones. In my case, these are vmnet1 and vmnet8. These interfaces have IP addresses assigned to them. In my case, vmnet1 has 192.168.32.1/24 and vmnet8 has 192.168.126.1/24.  See below – your addresses and interface numbers may vary:

ifconfig

vmnet1 is the host interface for an internal network, not accessible from outside the host. vmnet8 is the network that guest VMs are put on if they are going to use NAT to access the outside world using the host’s IP address. Obviously with a bridged VM, neither of these would be used.

So after installing the OVA file for the Juniper vSRX, click into the properties:

fusion
Click on the first network adapter – there will probably be three:

vm-settings

Make sure the ‘Connect network adapter’ checkbox is selected, and choose the ‘Private to my Mac’ option:

privatenet

Start up the vSRX, and configure an IP address on ge-0/0/0 that is in the subnet 192.168.32.0/24.

Once you’ve committed this, you should be able to ping the host machine at 192.168.32.1. Don’t forget that for the host to be able to ping the vSRX, you’ll need to put it in routing mode or create firewall policy that permits the pings…

vSRX

After doing this, I set up Space 15.2, put it on the ‘Private to my Mac’ network with an appropriate address, and browse to it from the host. Finally, I got Space to discover the vSRX as a managed device.


JBAS011469 Error in Junos Space

$
0
0

Just went onto a customer’s Junos Space/Security Director installation to discover that their SRX5800 was showing as ‘out of sync’.    I tried to do a ‘Resynchronize with Network’ from the Device Operations menu, but this failed with the following error:

Error while reading config from device: <devicename> javax.persistence. TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction of extended persistence context)
jbas011469

JBAS011469 error in Space 15.2

Unfortunately (like most Space-related errors) there’s nothing about this in Juniper’s knowledgebase – the only hit I found on a Google search was a similar error, but with a different cause that had been fixed.   So I thought I’d put this here in case it helps anyone.  

The solution in the end was to update the DMI schema for the device. The SRX5800 had been upgraded from 12.1R3.5 to 12.3X48-D30.7 but the schema within Space had not.  I downloaded the appropriate schema, and now the device re-syncs just fine.


Ansible and Junos Notes

$
0
0

I’m working on a project to push out configs to Juniper devices and upgrade them if necessary. Ultimately it will be vendor-independent.  In the first instance I thought about writing it all in Python, but there’s really no need because quite a lot of legwork has already been done for you in the form of ‘PyEz’ and the Junos Ansible core modules.

Juniper give you a few examples to get you started, but don’t really explain what each of the lines in the YAML file does, but I guess they expect you to figure that out.  Below are a few notes on things I discovered – perhaps obvious to some, but they might help someone else.

Ansible’s agentless nature

Ansible has the upper hand over Chef and Puppet in that it is agentless.  All you need is SSH.  Or so they tell you.

Ansible actually needs the system it is making changes on to be running Python.  So really, *that’s* the agent that Ansible talks to.   Since most network devices don’t have Python (it is roadmapped for Junos soon), that means you’ve got a problem – you can’t use most of the commands module of Ansible to execute remote commands.

With Junos you have two choices:

  1. Use the ‘raw’ module to send SSH commands to Junos:  This opens up a channel, sends the command and closes it again.  No error-checking, no frills.
  2. Use the Juniper Ansible modules: Used with a playbook you need ‘connection: local’ so that the Python part is done on the controlling node.  Then the module uses Netconf to connect to the Junos device to issue commands.

There is no other way – since there’s no Python on Junos and no way to get into a shell over SSH, these are your only options.

‘No module named jnpr.junos’ When Running Ansible

In the examples Juniper give, they don’t tell you that the Ansible module ‘Juniper.junos’ relies on a Python module called ‘jnpr.junos’.  (It is mentioned elsewhere if you look for it.)

So if you’ve done an ‘ansible-galaxy install Juniper.junos’ you could be forgiven for thinking that you’ve downloaded the modules you need.  You then gaily go on to have a crack at the example given above, but get this error:

$ ansible-playbook juniper-test.yml

PLAY [Get info] *********************************************************

TASK [Checking Netconf connection] **************************************
ok: [192.168.30.12]

TASK [Get info from Junos device] ***************************************
fatal: [192.168.30.12]: FAILED! => {"changed": false, "failed": true, "msg": "ImportError: No module named jnpr.junos"}

NO MORE HOSTS LEFT ******************************************************
 to retry, use: --limit @/Users/amulheirn/Documents/scripts/softpush/juniper-test.retry

PLAY RECAP **************************************************************
192.168.30.12 : ok=1 changed=0 unreachable=0 failed=1
$

To resolve this, you need to download the PyEz module for Python.  On my Mac, I did this using ‘sudo pip install junos-eznc’

 

Authenticating

I thought I’d be able to issue a command like ‘ansible-playbook junipertest.yml -u UserName -k’.   Ansible would then use the specified username and ask for the password interactively before it began – which it does.  However I was persistently getting the following authentication error:

TASK [Get info from Junos device] ***************************************
fatal: [192.168.30.12]: FAILED! => {"changed": false, "failed": true, "msg": "unable to connect to 192.168.30.12: ConnectAuthError(192.168.30.12)"}

This was a bit confusing for a while.  It seems you can’t use command-line switches to pass username and password to a playbook.  Instead, the Juniper.junos module wants you to make a  variables section in the YAML file, and then pass the variable contents to the tasks that are specified later in the file.   The result is that you still  interactively asked for a username and password, and can successfully authenticate.

 

My YAML file

My YAML file looks like this – it successfully retrieves the version running on the device. I have commented down the right-hand side of this to add explanations, so you will need to remove these:

---
- name: Get info      # The name of the 'play'
  hosts: all          # Run on all hosts in inventory file
  roles:
  - Juniper.junos     # Invokes the Junos Ansible module
  connection: local   # Tells it to run locally
  gather_facts: no

 vars_prompt:           # Variable section
 - name: USERNAME       # Name of the variable
   prompt: User name    # Text presented to user
   private: no          # Obscure input with stars = no
 - name: DEVICE_PASSWORD
   prompt: Device password
   private: yes         # Obscure input with stars = yes

 tasks:                 # A series of tasks
   # Check a netconf connection can be made on port 830
 - name: Checking Netconf connection
   wait_for: host={{ inventory_hostname }} port=830 timeout=5

 # Retrieve the facts from the device using user/pass specified earlier
 - name: Get info from Junos device
   junos_get_facts:
   host={{ inventory_hostname }}
   user={{ USERNAME }}
   passwd={{ DEVICE_PASSWORD }}
   savedir=./
 register: junos

 # Three tasks to print results to screen
 - name: Print model
   debug: msg="{{ junos.facts.model }}"
 - name: Print version
   debug: msg="{{ junos.facts.version }}"
 - name: Print serial
   debug: msg="{{ junos.facts.serialnumber }}"
~


The above seems to work ok.  If you want to see all the facts that can be retrieved, change one of the last lines to just:

debug: msg="{{ junos.facts }}"

In doing this, you will get back all possible sub-facts that can be inspected – here’s the output I receive from an EX2200 in our lab:

 "msg": {
 "HOME": "/var/home/axians-prestage",
 "RE0": {
 "last_reboot_reason": "Router rebooted after a normal shutdown.",
 "mastership_state": "master",
 "model": "EX2200-24T-4G",
 "status": "OK",
 "up_time": "3 days, 23 hours, 38 seconds"
 },
 "domain": null,
 "fqdn": "",
 "has_2RE": false,
 "hostname": "",
 "ifd_style": "SWITCH",
 "master": "RE0",
 "model": "EX2200-24T-4G",
 "personality": "SWITCH",
 "serialnumber": "CW02122xxx91",
 "switch_style": "VLAN",
 "vc_capable": true,
 "vc_mode": "Enabled",
 "version": "12.2R9.3",
 "version_RE0": "12.2R9.3",
 "version_info": {
     "build": 3,
     "major": [
         12,
         2
     ],
     "minor": "9",
     "type": "R"
    }
  }
}

As you can see from the previous YAML file, you can retrieve junos.facts.version in order to get just that one ‘sub-fact’.  Replace ‘version’ with any of the above facts and see what you get – e.g. junos.facts.hostname

 

Ansible files

I wanted my work to be portable to a colleague’s computer with minimal fuss.  Ansible looks for a config file in /etc/ansible/ansible.cfg I believe, but it looks for a config file in the current directory first.  That is nice – it means you can override the system’s settings on a per playbook basis.

So here is my ansible.cfg file:

$ more ansible.cfg
# Ansible config file for softpush
[defaults]
inventory = ./hosts
log_path = ./ansible.log

 

My hosts file is pretty basic – it only contains a single IP address at the moment.  According to docs.ansible.com you should be able to alias a host using this:

jumper ansible_port=5555 ansible_host=192.0.2.50

‘jumper’ in this example is a host alias – apparently it doesn’t even have to be a real hostname.   However I found that this did not work for me – it tried to use the alias to connect to the host, rather than the IP address specified by ansible_host.  The error was:

$ ansible-playbook juniper-test.yml
User name: prestage
Device password:

PLAY [Get info] *********************************************************

TASK [Checking Netconf connection] **************************************
fatal: [test]: FAILED! => {"changed": false, "elapsed": 5, "failed": true, "msg": "Timeout when waiting for test:830"}

NO MORE HOSTS LEFT ******************************************************
 to retry, use: --limit @/Users/username/Documents/scripts/softpush/juniper-test.retry

PLAY RECAP **************************************************************
test : ok=0 changed=0 unreachable=0 failed=1

I edited the /etc/hosts file on my machine to include the same alias, and that now works fine.    Not sure this is intended behaviour – why specify an ansible_host value in the ansible hosts file if your /etc/hosts file contains the IP address as well?

Update on 27th Oct:  I’ve discovered the above does actually work – not entirely sure what I was doing wrong last time, but with this in the inventory it works fine:

[Devices]
line2001 ansible_host=192.168.30.20

 

Authentication

SSH Public Key Authentication

There are a few ways that authentication can be achieved.  The most preferred way is to use an SSH public key, so no password is required.  This means generating a public/private key for the user and then transferring the public key to the Junos host’s config.  Since my script is for pre-staging lots of devices, I felt that was overkill – if I was going to use Ansible for daily management of these devices, then it would be worthwhile, but that won’t be the case here.

Interactive Authentication

An alternative is the method described above, where the credentials are requested interactively. The ‘vars_prompt:’ section of the YAML file is what makes this happen.

The Juniper.junos module pays no attention to the ‘-u <USERNAME>’ command-line argument, nor does it observe the -k argument, which prompts for a password. I’m not sure why that is, but it is documented here.  If you put those command-line switches in, they are accepted and ignored – instead, the $USER environment variable from your computer is sent, resulting (probably) in an auth failure.

 

‘Insecure’ Authentication

Instead of using ‘vars_prompt:’, you can write the username and password into a ‘vars:’ section of the YAML file.  Obviously this isn’t secure, but since my script is for lab purposes, security of this information isn’t a concern.   Just replace the ‘vars_prompt:’ section shown above with something like this:

 vars:
 - USERNAME: someusername
 - DEVICE_PASSWORD: yourpassword

 

An alternative to doing  this is to put the usernames/passwords in the hosts file, though again this is not recommended:

$ more hosts
[Devices]
192.168.30.20 ansible_user=MyUsername ansible_ssh_pass=MyPassword

 

 

Vault Authentication

The proper way to store usernames and passwords is in the Ansible vault.  This is a file that is automatically encrypted with AES256 encryption.  You can pull in just the password, or a variety of variables as per the example on this Juniper page.   Quite cool, but too complex for my basic lab setup.

 

Formatting The Output

Instead of calling each fact one after the other, it is possible to do this and create a comma-separated list of facts:

 - name: Print model
   debug: msg="{{ junos.facts.serialnumber }},{{ junos.facts.model }},{{ junos.facts.version }}"

The result is:

TASK [Print model] *************************************************************
ok: [test] => {
 "msg": "CW0212xxx591,EX2200-24T-4G,12.2R9.3"
}

 

That’s all very well, but maybe you want to write this to a text file in that format?  Simply create another task that uses the copy module to write the output to a file.  Here’s the ‘Print model’ task again, followed by a new task called ‘Write details’:

 # Print results to screen, then write a CSV file
 - name: Print model
 debug: msg="{{ junos.facts.serialnumber }},{{ junos.facts.model }},{{ junos.facts.version }}"
 - name: Write details
 copy: content="{{ junos.facts.serialnumber }},{{ junos.facts.model }},{{ junos.facts.version }}" dest=./{{ inventory_hostname }}.txt

This results in a file in the current directory in the format <hostname>.txt:

$ more 192.168.30.12.txt
CW0212286591,EX2200-24T-4G,12.2R9.3

$

Issues

When running this playbook, the Juniper.junos module is supposed to write output to a file in the location specified by ‘savedir=’ in the YAML file.  It does do this, but fails to pre-pend the hostname on the file, so you get a file called ‘-facts.json’.   This is a problem because the filename begins with a ‘-‘ and it is therefore interpreted as a command-line switch by vi, cat and more.

Opening this file in the GUI reveals it to be a JSON formatted file containing all of the ‘facts’, just missing the hostname:

{"domain": null, "hostname": "", "ifd_style": "SWITCH", "version_info": {"major": [12, 2], "type": "R", "build": 3, "minor": "9"}, "version_RE0": "12.2R9.3", "serialnumber": "CW0212xxx591", "fqdn": "", "RE0": {"status": "OK", "last_reboot_reason": "Router rebooted after a normal shutdown.", "model": "EX2200-24T-4G", "up_time": "4 days, 18 minutes, 55 seconds", "mastership_state": "master"}, "has_2RE": false, "switch_style": "VLAN", "version": "12.2R9.3", "master": "RE0", "HOME": "/var/home/axians-prestage", "vc_mode": "Enabled", "model": "EX2200-24T-4G", "vc_capable": true, "personality": "SWITCH"}

It occurred to me that it isn’t the hostname on my Ansible control machine that should be in the filename – it should be the hostname of the device I am configuring.  As you can see above, the hostname is an empty string.  That’s because my device is new – all it has on it is an IP address and username/password.

I used the ‘set system host-name <name>’ command to give the device a name.  Re-ran the playbook and this time got the hostname on the file as expected:

$ more line1-facts.json
{"domain": null, "hostname": "line1", "ifd_style": "SWITCH", "version_info": {"major": [12, 2], "type": "R", "build": 3, "minor": "9"}, "version_RE0": "12.2R9.3", "serialnumber": "CW0212xxx591", "fqdn": "line1", "RE0": {"status": "OK", "last_reboot_reason": "Router rebooted after a normal shutdown.", "model": "EX2200-24T-4G", "up_time": "4 days, 29 minutes, 33 seconds", "mastership_state": "master"}, "has_2RE": false, "switch_style": "VLAN", "version": "12.2R9.3", "master": "RE0", "HOME": "/var/home/axians-prestage", "vc_mode": "Enabled", "model": "EX2200-24T-4G", "vc_capable": true, "personality": "SWITCH"}
$

 

 



Issuing Junos Commands Using Ansible raw Module

$
0
0

If you want to issue something quick on a lot of devices, you don’t need to write a whole Ansible playbook to do that.  In fact you don’t really need the Junos module installed.

Ansible expects there to be Python on the managed device.  As you can read in this PacketPushers blog, it pushes the module out to the device and tries to execute it there.  Junos is going to get on-box Python at some point, but right now that’s roadmap (or SOPD if you must).

Suppose you want to find out what version of software you have on a your lab device, here’s a quick way to do that.

$ ansible 192.168.30.20 -m raw -a "show version" -u username -k
SSH password:
192.168.30.20 | SUCCESS | rc=0 >>
fpc0:
--------------------------------------------------------------------
Model: ex2200-24t-4g
JUNOS Base OS boot [12.3R12.4]
JUNOS Base OS Software Suite [12.3R12.4]
JUNOS Kernel Software Suite [12.3R12.4]
JUNOS Crypto Software Suite [12.3R12.4]
JUNOS Online Documentation [12.3R12.4]
JUNOS Enterprise Software Suite [12.3R12.4]
JUNOS Packet Forwarding Engine Enterprise Software Suite [12.3R12.4]
JUNOS Routing Software Suite [12.3R12.4]
JUNOS Web Management [12.3R12.4]
JUNOS FIPS mode utilities [12.3R12.4]

$

Perhaps you want to issue the same command across multiple devices?   Simply add them into the inventory file (by default, this is /etc/ansible/hosts) like so:

[Devices]
192.168.30.20
192.168.30.21
192.168.30.22
#192.168.30.23

As you can see above, individual hosts can be ‘remmed-out’ with a # at the start of the line.

Instead of specifying an IP address, you can now specify ‘all’ or just the group-name like this:

ansible all -m raw -a "show version" -u username -k
ansible Devices -m raw -a "show version" -u username -k

 

If you need to run several commands, you can daisy-chain them together using the semi-colon as a separator like so:

$ ansible Devices -m raw -a "show version;show system uptime" -u username -k
SSH password:
192.168.30.20 | SUCCESS | rc=0 >>
fpc0:
--------------------------------------------------------------------
Model: ex2200-24t-4g
JUNOS Base OS boot [12.3R12.4]
JUNOS Base OS Software Suite [12.3R12.4]
JUNOS Kernel Software Suite [12.3R12.4]
JUNOS Crypto Software Suite [12.3R12.4]
JUNOS Online Documentation [12.3R12.4]
JUNOS Enterprise Software Suite [12.3R12.4]
JUNOS Packet Forwarding Engine Enterprise Software Suite [12.3R12.4]
JUNOS Routing Software Suite [12.3R12.4]
JUNOS Web Management [12.3R12.4]
JUNOS FIPS mode utilities [12.3R12.4]
fpc0:
--------------------------------------------------------------------
Current time: 2016-01-26 01:33:51 UTC
System booted: 2016-01-25 21:48:18 UTC (03:45:33 ago)
Protocols started: 2016-01-25 21:51:32 UTC (03:42:19 ago)
Last configured: 2016-01-25 20:59:55 UTC (04:33:56 ago) by username
 1:33AM up 3:46, 1 user, load averages: 0.11, 0.11, 0.08

$

It is even possible to go into edit mode, apply some config and commit it:

$ ansible Devices -m raw -a "edit;set system host-name test;commit and-quit" -u username -k
SSH password:
192.168.30.20 | SUCCESS | rc=0 >>
Entering configuration mode
configuration check succeeds
commit complete
Exiting configuration mode

$

 

 

 

 

 


Segment Routing on JUNOS – The basics

$
0
0

Anybody who’s been to any seminar, associated with any major networking systems manufacturer or bought any recent study material, will almost certainly have come across something new called segment routing &…

Source: Segment Routing on JUNOS – The basics


Restoring Space 15.2 data to 16.1

$
0
0

The upgrade from Space platform 15.2 to 16.1 is one of the worst procedures I’ve seen in quite a while.   It is complicated because the underlying CentOS is being upgraded at the same time, so I guess that’s part of the reason, but still, it could be a lot slicker and better tested.

In summary, you have to apply a couple of patches, the second of which backs your 15.2 data up somewhere else – ideally over SCP to a remote server.  You then shut down your 15.2 VM, install a fresh 16.1 VM with the same IP addresses, and restore the data to it.

Sounds easy, but the 16.1 installation part can generally only be done by the customer’s VMware admin because it needs console access.  So you’ve got to rely on them following lots of instructions quite well.

Recently a customer experienced some kind of failure in the restoration part, leaving me with a fresh installed 16.1, but no data.  I SSHed on to the VM and could see the standard menu, but wasn’t offered any option to attempt another restore.   After digging around for a while, I found you can kick it off again by running:

/usr/bin/jmp_restore

The restoration process looks like this:

 

[root@space-00505688180e bin]# pwd
/usr/bin
[root@space-00505688180e bin]# ./jmp_restore
Please enter valid response.
The Restore process might take several hours if the overall backup content including database size is in few Giga-Bytes...

Restore Junos Space Backup

1> Remote Server
2> USB
3> Local

Select option :
1
You have selected [ Remote Server ]. Do you want to Continue? [Y/N]


Please enter Remote Server IP:
XXX.XXX.XXX.XXX


Please enter port number for Remote Server [ XXX.XXX.XXX.XXX ] :
22
Ping Remote Server [ XXX.XXX.XXX.XXX ] on Port number [ 22 ]...
 Remote Server [ XXX.XXX.XXX.XXX ] is available on Port number [ 22 ] ...
Please enter Remote Server [ XXX.XXX.XXX.XXX ] user:
root
Please enter Remote Server user [ root ] password:
Enter the path of the directory containing backup files:
/mnt/space-15.2R2.4.tgz

Verifying Remote server credentials....!
Valid Credentials for [ XXX.XXX.XXX.XXX ] Remote Server...!

Checking [ XXX.XXX.XXX.XXX:/mnt/space-15.2R2.4.tgz ] directory...!

[ XXX.XXX.XXX.XXX:/mnt/space-15.2R2.4.tgz ] is not exist. Please enter valid response.

Enter the path of the directory containing backup files:
/mnt
 [ XXX.XXX.XXX.XXX:/mnt ] exist.
Checking 15.2 R2 Backup Files....


Completed finding backup files...!

File transfer is going to be started, Please wait....
File transfer completed.


Validating MD5 Checksum of Backup file...!

Valid MD5sum of backup file. Continuing Restore...!

Shutting down services...

Stopping WatchDog Services

Stopping OpenNMS Services
Stopped OpenNMS Services


Extracting backup files...

Restoring MySQL...

Starting MySQL service...

Starting MySQL data import....


Restoring pgsql...
Starting postgres service...


Restoring Application related files to /var/cache/jboss/jmp/payloads/backup/

Restoring Space configuration......
Doing /etc/pki/tls/ca_certs
Doing /etc/pki/tls/ca_crls

Upgrading Opennms Configuration Directory (/opt/opennms/etc)
Starting Service Now Restore...
Service Now version 15.1R3.14
Processing AIM-RESTORE.SH - STAGE - 0
Processing AIM-RESTORE.SH - STAGE - 1
Processing AIM-RESTORE.SH - STAGE - 2
Processing AIM-RESTORE.SH - STAGE - 3
Processing AIM-RESTORE.SH - STAGE - 4
Processing AIM-RESTORE-DB.SH - STAGE - 0
Processing AIM-RESTORE-DB.SH - STAGE - 1
Processing AIM-RESTORE-DB.SH - STAGE - 2
Processing AIM-RESTORE-DB.SH - STAGE - 3
Processing AIM-RESTORE-DB.SH - STAGE - 4
ls: cannot access /var/cache/jboss/jmp/payloads/backup/AIM/sn_backup/db-table/logFileData/*.sql: No such file or directory
Processing AIM-RESTORE.SH - STAGE - 5
AIM-RESTORE-DATA.sh - Starting Service Now data restore...
AIM-RESTORE-DATA.sh - Started to copy...
AIM-RESTORE-DATA.sh - Changing permissions...
AIM-RESTORE-DATA.sh - Completed Service Now data restore...
Successfully completed processing AIM-RESTORE.SH

Starting services...

Starting Watch-Dog Service...

Starting OpenNMS Service

Starting Jboss Domain Controller Service

Starting Jboss Service
Space Upgrade has completed successfully
[root@space-00505688180e bin]#
[root@space-00505688180e bin]#

Shrubbery.net TACACS+ daemon and Junos

$
0
0

Axians Professional Services normally recommends using RADIUS authentication to our customers, but one of our customers uses TACACS.  We did some type-approval testing of new Junos release for them recently and had to set up a TACACS+ daemon in the lab to make sure authentication still worked following the upgrade.

Shrubbery.net very helpfully provide a TACACS+ implementation that you can download to a Linux host for this purpose, but the documentation is a bit light on their website, and what you find using Google is naturally somewhat Cisco-specific.  So here are some notes on getting a basic setup going with Shrubbery’s tac_plus daemon and Junos.  Maybe this will help someone else.

 

Create the Junos Config

First, you need to set up the Junos side of things.  You need to do three things:

  1. Create a tacplus-server in the config
  2. Add tacplus to the authentication-order
  3. Create a ‘local user’ account that has no password, but gives anyone belonging to it the appropriate privileges.

 

Create the TACACS server

axians@MX104-1-re0> show configuration system tacplus-server | display set

set system tacplus-server 192.168.3.237 port 49
set system tacplus-server 192.168.3.237 secret testing123
set system tacplus-server 192.168.3.237 source-address 192.168.3.72

In the above, we specify that Junos should find the server at the .237 address on port 47.  The secret is a password that must agree on both the Junos device and the server.  It is also good practice to specify the source of the TACACS request – in this case, it is fxp0, the managment interface.

 

Create the local ‘user’

axians@MX104-1-re0> show configuration system login user | display set

set system login user RO uid 2006
set system login user RO class read-only
set system login user SU uid 2007
set system login user SU class super-user

In the above, we create two ‘users’ which aren’t really users.   They are called RO (read-only) and SU (super-user) and their purpose is to determine the class that should be assigned to anyone matching these two usernames.  (The UID part can be ignored – that is generated by Junos automatically)/

 

Specify the authentication order

axians@MX104-1-re0> show configuration system authentication-order | display set
set system authentication-order tacplus

This tells the router to authenticate using TACACS primarily.  If the server responds with either an accept or a deny, then TACACS will be the only authentication database that is consulted.   If no response is received (i.e. server is down or unreachable) then the local Junos password database will be consulted instead.

We recommend not specifying tacplus and password at the same time. This is a common mistake and means that Junos will try both authentication types every time.  It leaves your router more open to brute-force password attacks on the local Junos password database, which in all likelihood is not changed very often.

 

Create the tac_plus server

 

On your Linux host you need to install the tacacs+ package.  This example is performed on an Ubuntu server.  Here are the commands I issued:

sudo apt-get update
sudo apt-get install tacacs+

 

tac_plus normally runs in daemon mode.  There is a config file at /etc/tacacs+/tac_plus.conf and messages are logged to /var/log/syslog by default.  The messages are not in debug mode,  and I have yet to figure out how to turn that on when the daemon is running.

You can get online help using ‘man tac_plus.conf’

Edit /etc/tacacs+/tac_plus.conf and make it look as follows:

 

# This is the 'secret' we specified in Junos

key = testing123

# This is the actual user who is a member of group 'SU'
user = user1 {
 member = SU
 login = cleartext password123
}

# Here is another user, who belongs in the other group.
user = user2 {
 member = RO
 login = cleartext password456
}

# Here is the SU group definition.  It specifies a
# junos-specific 'local-user-name' to pass back if
# authentication is successful.  This must match the
# local user we configured in Junos
group = SU {
   service = junos-exec {
     local-user-name = SU
   }
}

group = RO {
   service = junos-exec {
     local-user-name = RO
   }
}

Save the file.

Note: in the above file, the passwords are specified in cleartext for each user.  An alternative method is to use the PAM (password authentication module) of this Linux host itself.   In this instance, the username/password used to log on to the Linux host would be the same as the one used to log on to Junos.  It is probably a safer system to use, but the cleartext option was sufficient for our testing.

I got a clue as to the correct  formatting of the configuration file by reading this Juniper document – the bottom of the page shows what appears to be a section of the config file for the tac_plus daemon.  I tried the first line of it and it worked – there are other commands there that I didn’t try but would allow you to specifically permit or deny certain commands.

Check if the tac_plus daemon is running:

andrew@axians:/etc/tacacs+$ sudo service --status-all | grep tacacs_plus
[ + ] tacacs_plus

As you can see above, the plus symbol means it is running.  It would show a minus sign if it were stopped.  Stop and start it again as follows to ensure it reads in the config file:

andrew@axians:/etc/tacacs+$ sudo service tacacs_plus stop
 * Stopping TACACS+ authentication daemon tacacs+ [ OK ]
andrew@axians:/etc/tacacs+$ sudo service tacacs_plus start
 * Starting TACACS+ authentication daemon tacacs+ [ OK ]
andrew@axians:/etc/tacacs+$

 

When you do a ‘sudo tail -f /var/log/syslog’ you will see user authentication failures.  The successes are less usefully-logged, just appearing as a ‘connect from <ip address of Junos router>’ message.   I’m sure the logging level can be improved, but haven’t got time to figure that out right now.

Jun 14 12:06:04 axians tac_plus[19390]: connect from 192.168.3.72 [192.168.3.72]
Jun 14 12:06:05 axians tac_plus[19390]: login failure: user1 192.168.3.72 (192.168.3.72) unknown-port
Jun 14 12:06:06 axians tac_plus[19391]: connect from 192.168.3.72 [192.168.3.72]
Jun 14 12:06:09 axians tac_plus[19392]: connect from 192.168.3.72 [192.168.3.72]

 

In the above, the first two lines are the radius client (i.e. the Juniper router) connecting and a user failing to authenticate.  The second two lines represent a successful authentication by the user.

 

How it works:

  1. The user SSHes to the Junos host and enters credentials
  2. Junos passes those credentials (encrypted using the secret) to the TACACS+ server
  3. TACACS+ permits or denies the user.
  4. If the user is permitted, the ‘local-user-name’ is sent back to Junos
  5. Junos uses that parameter’s value to look up the local user of RO or SU
  6. Depending on which local user it is, the real user gets assigned to the appropriate class and is logged in to Junos.

 

Let me know in the comments if you know a better way of doing this, and thanks for reading.

 


Updating to JDK 1.8 or 1.9 on Ubuntu

$
0
0

Trying to install OpenDaylight Nitrogen needs JDK 1.8 or later.

Needless to say, I’ve not go the right version on my Ubuntu 16.04 server – it reports 1.7.  Also needless to say, installing it isn’t a simple matter of adding the software through apt-get because the repository appears to be broken or empty (at the time of writing).  I was hoping to get away with doing this:

sudo add-apt-repository ppa:webupd8team/java

sudo apt-get update

sudo apt-get install oracle-java9-installer

Anyway, the last part failed with:

Connecting to download.oracle.com (download.oracle.com)|104.86.110.251|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2017-10-20 14:05:08 ERROR 404: Not Found.download failed
Oracle JDK 9 is NOT installed.
dpkg: error processing package oracle-java9-installer (--configure):
 subprocess installed post-installation script returned error exit status 1
E: Sub-process /usr/bin/dpkg returned an error code (1)

So instead I downloaded it from here:  http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html

Unpacked the tarball with this:

cd /opt
tar -xvzf jdk-9.0.1_linux-x64_bin.tar.gz

Finally updated my environment variables to tell it where the JDK is:

 export JAVA_HOME=/opt/jdk-9.0.1/
 export PATH=$JAVA_HOME/bin:$PATH

Still no cigar – Karaf won’t install because I obviously don’t know my JVM from my JDK:

andym@ubuntu-dev:~/karaf-0.7.0/bin$ ./karaf
JVM must be greater than 1.8
andym@ubuntu-dev:~/karaf-0.7.0/bin$ java -veresion
Unrecognized option: -veresion
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
andym@ubuntu-dev:~/karaf-0.7.0/bin$ java -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

 

 

 

 

 


Viewing all 77 articles
Browse latest View live