Netmiko introduction for network Engineers for start scripting

seen from China

seen from United States
seen from United States
seen from United States
seen from Kazakhstan
seen from United States

seen from United States

seen from United States
seen from United States

seen from India
seen from United States

seen from United States

seen from United Kingdom
seen from Brazil
seen from Syria
seen from United States
seen from United Kingdom
seen from Brazil

seen from United States
seen from Brazil
Netmiko introduction for network Engineers for start scripting
useless day
I honestly tried to concentrate and test sftpclient.get (or put) vs sftpclient.open (using stringIO) in pararamiko. The idea is to boost paramiko in threading mode because both .get and .put seems to be so slow in what they should do. But this attempt was useless due to headache though all i was suppose to do is 20-30 lines of code.
[서버][python][aws] 개발환경 세팅 - 삽질기
오늘 오후는 땅굴을 어디까지 뚫어볼 수 있는가에 대해 알아본 시간..-_-
다음엔 이런 삽질 시간을 조금이라도 줄이고자 기록으로 남기려고 함.
1. python + Django 세팅을 위해 Mac 에 python/Django 설치 - 5분
http://python.org/download/
https://www.djangoproject.com/download/
ubuntu의 경우
$ sudo apt-get install python-django
$ sudo apt-get install mysql-server
$ sudo apt-get install python-mysqldb
2. DB도 붙이려는데, 예전에 테스트삼아 aws 에 ubuntu image 얹어서 APM세팅한게 있으니 거기에 연결하려고 AMI snapshot 만들어서 instance 복제, 이후 Network 설정으로 mysql port 오픈 - 10분
http://aws.amazone.com/
3. 인스턴스가 2개 이상 되니, 접속을 편하게 하기 위해 간단한 shell script/python script 생성 - 1시간?
- 아래 my_key.pem은 aws에서 발급받은 private key.
connect.sh
#!/bin/sh
echo "=========== usage =============="
echo " 1 : instance connect ([email protected]) "
echo " 2 : instance connect ([email protected]) "
read -p "please insert type: " num
case $num in
[1] )
echo "ssh -i my_key.pem [email protected]";
ssh -i my_key.pem [email protected];
break;;
[2])
echo "ssh -i my_key.pem [email protected]";
ssh -i my_key.pem [email protected];
break;;
esac
exit 0
connect.py
#!/usr/env/python
import os
print("=========== usage ==============")
print(" 1 : noir_game instance connect ([email protected]) ")
print(" 2 : only_for_test instance connect ([email protected]) ")
num = input("please insert type: ")
server=""
username="ubuntu"
pem="my_key.pem"
if (num == 1 or num == 2):
if (num == 1):
print("ssh -i my_key.pem [email protected]")
os.system("ssh -i my_key.pem [email protected]")
else:
print("ssh -i my_key.pem [email protected]")
server="[email protected]"
os.system("ssh -i my_key.pem [email protected]")
* python 에서 ssh 접속하기 위한 라이브러리중 paramiko 가 있어서 다운로드 후 설치하였으나, 내 목적은 쉘 접속 - 명령어 실행 - 종료가 아니라 remote shell 연결 상태를 유지하는 것이므로 os.system 으로 변경.
2번에서 원래 하려고 했던 DB 세팅으로 돌아와서, mysql 서버 세팅이 끝났으니 pythonn package installer인 pip 설치 및 python-mysql 설치..
sudo easy_install pip
sudo pip install python_mysql
하다보니, Django의 Database 설정을 aws에 ssh 접속 후에 mysql을 붙어야 하는데, 그 설정이 상당히 애매한 관계로...
그리고, 굳이 로컬에 설정할 이유가 없는데...ec2 instance에 그냥 할걸....
설상가상으로 ssh 접속도 자꾸 튀어서, AWS EC2 인스턴스의 zone을 옮기는 작업을 다음에 넣을 예정임.
F5 SSH vulnerability and how to check if you are affected
Following recent [F5 SSH vulnerability disclosure](http://support.f5.com/kb/en-us/solutions/public/13000/600/sol13600.html), I was forced to quickly identify which of my devices are actually vulnerable and need patching. I started looking at my options and it turned out that easiest way to find out which boxes need some loving was to try exploiting them. It took me just a moment to locate dodgy private SSH key on BigIP's filesystem. Once I had that I was able to login to hundreds of boxes as root without providing any password. Huh, F5 - what a fail... This is probably one of the biggest and easiest to exploit vulnerability I have ever seen. Anyway, this is an example command that I have used to "exploit" the box: $ ssh -i PATH_TO_PRIVATE_KEY root@HOST If you try it against loadbalancer with IP of 7.7.7.7, you will get output similar to this: $ ssh -i ~/.ssh/f5_idsa [email protected] Warning: Permanently added '7.7.7.7' (RSA) to the list of known hosts. Last login: Wed Jun 20 10:41:53 2012 from 5.5.5.5 [root@lb1:Active] config # O.K. so now next logic step was to automate the checks to some extent. Quickest way I could have thought of was to execute "exit" command with some random, non-common exit code like 50. Once executed, I could check the return value and if it was indeed 50 it meant that SSH process succesfully logged in or the "exploitation" failed if return code was different. [skrobul@atol ~]$ ssh -qi ~/.ssh/f5_idsa [email protected] "exit 50" [skrobul@atol ~]$ echo $? 50 [skrobul@atol ~]$ # Connecting to SSH through HTTP proxy in Python It is good and quick way to test, but how do you know what actually happened when error code is different than 50? The OpenSSH client will return 255 in case anything goes wrong, be it connection timeout, connection refused or anything else. I need better level of granularity so I started looking at more sophisticated options. My [programming language](http://python.org) of choice has pretty good [SSH library](http://www.lag.net/paramiko/) that is widely used and documented well. Despite having written all previous scripts with [pexpect](http://www.noah.org/wiki/pexpect) I've decided to give it a shot. I came up with following script that is able to scan individual IPs or
#!/usr/bin/python2 import paramiko import sys import os import argparse #paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) def scan(ip, privatekey=os.path.expanduser("~/.ssh/f5_idsa")): ssh = paramiko.SSHClient() mykey = paramiko.RSAKey.from_private_key_file(privatekey, password="") ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect(ip, username='root', pkey=mykey, timeout=3) stdin, stdout, stderr = ssh.exec_command("ls /shared/") ret = True except paramiko.PasswordRequiredException: ret = False finally: ssh.close() del ssh return ret if __name__ == '__main__': parser = argparse.ArgumentParser() grp = parser.add_mutually_exclusive_group(required=True) grp.add_argument("-f", dest="filename") grp.add_argument("-i", dest="ip") args = parser.parse_args() if args.ip: print scan(args.ip) if args.filename: for ip in open(args.filename).readlines(): ip = ip.rstrip() try: if scan(ip) == True: print "%s is vulnerable" % ip else: print "%s is patched" % ip except Exception, e: print "%s failed with following exception: %s" % (ip, e) continue
Above script is relatively simple and does the job most of the time. Unfortunately as soon as I tried to use it out of my lab I hit huge roadblock. I completely forgot that all of my production devices are accessible only from dedicated management network and in order to access them I have to go through specific proxy server / jump host. Obviously, this is much more secure than having door wide open but is pain in the ass for executing scripts like above. Now to solve this problem I had few options: * Find a server that is connected directly to the management network and upload scripts there. This is most difficult option (if possible at all) for me so I decided against it. Also, it would be really uncomfortable to transfer scripts back and forth every time I wanted to make a tiny change. * Open SSH session to the jump server and enable dynamic forwarding. If you do that, your localhost becoms full-blown SOCKS proxy. Now if you combine this with little tool called "tsocks", you can transparently execute any command as if you were logged into the jump server. In theory all connections get transparently proxied through your SSH tunnel and jump server will make connection on behalf of the client. Except, it doesn't always work. I learned this hard way - I was able to reach about 800 boxes and then tsocks would just hang for hours and the only solution was to manually kill the process. I played a bit with strace to try to identify the problem but got nowhere. * I remembered that mentioned jump host has a HTTP proxy feature enabled. I believe it's just standard configuration of [Squid Proxy](http://squid-cache.org) with CONNECT method enabled. In fact this is how I normally login to the loadbalancers. There is a little tool called [connect-proxy](http://aur.archlinux.org/packages.php?ID=45592) that allows to use HTTP proxy with OpenSSH through ProxyCommand configuration. It's awesome, works perfectly and requires almost no configuration. All you need to do is add relevant ProxyCommand to your ~/.ssh_config file:
[skrobul@atol ~]$ cat ~/.ssh/config ForwardAgent yes TCPKeepalive yes ServerAliveInterval 5 Host 192.168.* ProxyCommand none Host * ProxyCommand /usr/bin/connect -H jump.host.company.com:3128 %h %p [skrobul@atol ~]$
This configuration allows me to execute my "simple" scans as described above, but it still leaves me with incomplete information - all I know is that device is definitely vulnerable or in unknown status. In fact, that information is not very useful because I want to know that particular devices is definitely NOT vulnerable before I can sleep well. In other words - I need to find a way to modify my miniscanner to go through HTTP proxy because TSOCS option is very unreliable. I jumped on google and found out that paramiko does not support proxies, however there is an extension named [paraproxy](http://pypi.python.org/pypi/paraproxy) that enables proxy functionality. While documentation is not very extensive I was able to successfully add it to my project. All I needed to do was to add "import paraproxy" to the top of my file and it should work:
#!/usr/bin/python2 import paramiko import paraproxy import sys import os import argparse [...]
Unfortunately, it didn't work. The module is loaded and used but for some reason, even though debugging says that ProxyCommand is being used, the packets still leave my computer directly without going through proxy. I have reported the problem to paraproxy author, René Köcher and we are trying to identify what the exact problem is. So far, I've been able to get it working by forcing the module into "command chaining" mode but it's not good long-term solution. Debugging paraproxy sounds like fun, but given the severity of this vulnerability I had to come up with something else quickly. Finally, I decided to use good old pexpect to do the job. Given the fact that my configuration of OpenSSH works well with HTTP proxy already, all I needed was just to improve my "simple" scanner. I came up with following code:
#!/usr/bin/python2 import sys import os import argparse import pexpect #paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) def scan(ip, privatekey=os.path.expanduser("~/.ssh/f5_idsa")): "Returns true if vulnerable" p = pexpect.spawn("ssh -q -i %s -l root %s \"exit 50\"" % (privatekey, ip) ) # p.logfile_read = sys.stdout i = p.expect(["assword: ", "refused", pexpect.TIMEOUT, pexpect.EOF], timeout=6) p.close() if p.exitstatus == 50: return True else: if i == 0: return False elif i == 1: raise Exception, "Connection refused" elif i == 2: raise Exception, "Timed out" if __name__ == '__main__': parser = argparse.ArgumentParser() grp = parser.add_mutually_exclusive_group(required=True) grp.add_argument("-f", dest="filename") grp.add_argument("-i", dest="ip") args = parser.parse_args() if args.ip: print scan(args.ip) if args.filename: for ip in open(args.filename).readlines(): ip = ip.rstrip() try: if scan(ip) == True: print "%s is vulnerable" % ip else: print "%s is patched" % ip except Exception, e: print "%s failed with following exception: %s" % (ip, e) continue
While it's not most elegant solution, it works and gives me some breathing space to play around with paramiko and paraproxy.
A fork of the Fabric tool with some nice enhancements like:
parallel execution of tasks
decorators
tasks' contexts
a remote shell
configuration file and better environment variables
...
I'm looking at how to launch jobs in remote hosts from Django. As I don't want to block until the job is completed, the best thing to do is to create an asynchronous task with Celery and then start the remote job with Paramiko or Fabric. I have found this link where the author explains how to do it with Fabric:
from fabric.api import * @task def update(): Random.atfork() env.host_string = '[email protected]' env.disable_known_hosts = True run('ls')
Also check cloudpool or cloudcontrol: it seems they do something very similar...