Automation & Programmability
, Super Contributor
Automation & Programmability
Junos NETCONF and SSH tunneling (Part 2)



Now that we've established SSH tunneling through the network, we can verify a NETCONF session directly.  When I use the ssh command I specify the sub-command netconf using the -s parameter as illustrated.  Note that the netconf sub-command is after the hostname:


[]$ ssh -s srx3600.jumpy netconf
Warning: Permanently added '[localhost]:8001' (RSA) to the list of known hosts. <!-- No zombies were killed during the creation of this user interface --> <!-- user jeremy, class j-super-user --> <hello> <capabilities> <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file</capability> <capability></capability> <capability></capability> </capabilities> <session-id>22595</session-id> </hello> ]]>]]>


What you see here is the actual NETCONF "hello" message in response to the connection.  If you do not see this, then one of two things is not setup correctly:


  1. Your Junos device is not configured with NETCONF enabled.  You can verify this by checking the [edit system services] stanza.  If you are using an SRX, then you also need to enable NETCONF on the security-zone/interface.


  2. Your network/firewall is blocking TCP/830, which is the default port for NETCONF

You can close the NETCONF session using <Ctrl-C>.




I am going to demonstrate a Python script using a module called jnpr.eznc.  This is an active open-source project that is relatively new.  I will write more detailed blog on this module in the near term, but for now, if you'd like to get started using it, please see the github repo and README files located here.


Let's first take a look at a script that is *NOT* in an ssh-tunnelled environment.  Let's say I simply want to connect to the Junos device, display the serial-number and version, and then close the connection.  It would look like the following:


from jnpr.junos import Device

dev = Device(host='', user='jeremy', password='logmein')

print dev.facts['serialnumber']
print dev.facts['version']


The above example illustrates making a connection providing the user name and password.  If you are using ssh-keys, then you simply do not provide the password.


Now to do the tunneling use-case, we know that we are connecting through a local port forward.  We could do something like the following:


from jnpr.junos import Device

# srx3600-1.jumpy uses port 8001 dev = Device(host='localhost', port=8001, user='jeremy') print dev.facts['serialnumber'] print dev.facts['version'] dev.close()


But now we've duplicated information between our script and the ssh config file.  What we really want to do is use the ssh config file to extract the port associated with srx3600-1.jumpy so we can connect by the host name directly.


I am using the Python paramiko module to illustrate the technique to load the ssh config file and extract the information based on the host name defined in the config file, e.g. "srx3600-1.jumpy":


import paramiko
import os
from jnpr.junos import Device # load the $HOME/.ssh/config file and do a lookup on the
# host name "srx3600-1.jumpy"
config_file = os.path.join(os.getenv('HOME'),'.ssh/config') ssh_config = paramiko.SSHConfig() ssh_config.parse(open(config_file,'r')) got_lkup = ssh_config.lookup( "srx3600-1.jumpy" )
# now open the NETCONF connection using the information
# we retreived from the ssh config file
dev = Device(user='jeremy', host=got_lkup['hostname'], port=got_lkup['port'])
print dev.facts['serialnumber'] print dev.facts['version'] dev.close()


(UPDATED NOTE: 2014-Apr-15:  The above paramiko code is *not* required as of later version of the py-junos-eznc module.  This functionality was directly incorporated into the "Device" class.  So long as you have an SSH config file defined correctly and an active SSH tunnel, you will be able to connect through a jumphost when you invoke the method).




Writing Python scripts for Junos automation tasks can be easy (and fun!).  With a little bit of practice and the right set of modules (like jnpr.junos), you can quickly create very powerful automation tools with a high degree of confidence.








I'm getting hello message, but then I get stuck when trying directly ssh in on error below


Traceback (most recent call last):
  File "", line 7, in <module>
  File "/usr/local/lib/python2.7/site-packages/jnpr/junos/", line 236, in open
    hostkey_verify=False )
  File "/usr/local/lib/python2.7/site-packages/ncclient/", line 76, in connect_ssh
    session.connect(*args, **kwds)
  File "/usr/local/lib/python2.7/site-packages/ncclient/transport/", line 181, in connect
    raise SSHError("Could not open socket to %s:%s" % (host, port))
ncclient.transport.errors.SSHError: Could not open socket to
[root@Linux-helper SRX]# 



Sorry,  forgot to mention that it netconf appers to be configured correctly


root@fw201> show version               
Hostname: fw201
Model: srx240h
JUNOS Software Release [11.1R4.4]

root@fw201> show configuration | match netconf | display set
set system services netconf ssh




For SRX devices, you will also need to enable the protocol on the zone/interface.  So if you are using ge-0/0/0 for your connectivity for NETCONF, find the zone that has ge-0/0/0.  Then on that interface check the host-inbound-services configuration to make sure that ssh/netconf is enabled.


Hope that helps!





I'm trying to run the sample test script on a T1600 box with netconf configured:


jac@re1-willem> show version
Hostname: re1-willem
Model: t1600
JUNOS Base OS boot [12.3R4.6]


$ ssh -s netconf's password: 
<!-- No zombies were killed during the creation of this user interface -->
<!-- user noc, class j-super-user-local -->


Running the first sample script returns an error:


$ python
No handlers could be found for logger "paramiko.hostkeys"
Traceback (most recent call last):
  File "", line 6, in <module>
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/", line 239, in open
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/", line 403, in facts_refresh
    gather(self, self._facts)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/facts/", line 29, in personality
    raise RuntimeError("Unknown device persona: %s" % examine)
RuntimeError: Unknown device persona: T1600

Is T-series not supported?




I Think I found the answer


No T-series defined in there, bummer Smiley Sad any change on getting this in there?

Top Kudoed Authors