2015年12月13日星期日

Python atexit模块使用

atexit提供了一个程序退出时候的回调函数注册接口,比如你需要关掉文件,
保存当前数据等,当程序exit()时候自动调用回调函数,可以注册多个接口,
他们的调用顺序和注册顺序相反:

import atexit
import sys
import time

def goodbye(name, word):
  print 'Goodbye, %s, %s...' % (name, word)
  print 'pretend clean up resource...'


def first_register():
  print 'I am first register, but last called...'


atexit.register(first_register)
atexit.register(goodbye, 'python', 'see you again')


if __name__ == '__main__':
  time.sleep(3)
  if 1 == 1:
    exit(1)
  else:
    print 'exit(0)'
    exit(0)

2015年10月21日星期三

Python 使用 sock5 代理进行requests请求实例

找了很多的版本都有问题,总算有个可用的了:

需要安装依赖 python-socksipy==1.0



import socket
import socks
import requests

socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "182.92.178.227", 1080)
socket.socket = socks.socksocket
url = u'http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=inurl%E8%A2%8B'
print(requests.get(url).text)

2015年9月26日星期六

Python参数说明

-B     Don't write .py[co] files on import. 不产生pyc或者pyo文件
-c     执行字符串参数 如 python -c "print 1"
-d     产生调试信息
-E     Ignore environment variables like PYTHONPATH and PYTHONHOME that modify the behavior of the interpreter. 忽略环境变量
-i     执行完脚本以后 会打开解释器 在调试时候使用比较好
-m     比如 python -m SimpleHTTPServer 8088 从sys.path找到一个模块然后执行模块代码
-O     基本优化 会丢掉docstring
-R     hash() 返回伪随机数
-Q     控制两个整数相除得到的类型 如 python -Q new -c "print 10/100"
-v     显示加载模块 如 python -v -c "print 1"
-s     Don't add user site directory to sys.path.
-S     Disable the import of the module site and the site-dependent manipulations of sys.path that it entails.
-t     检测tab和空格混用 给出警告
-u     Force  stdin,  stdout  and stderr to be totally unbuffered.  On systems where it matters, also put stdin, stdout and stderr in binary mode.  Note that there is internal buffering in xreadlines(), readlines()  and  file-object iterators  ("for line in sys.stdin") which is not influenced by this option.  To work around this, you will want
to use "sys.stdin.readline()" inside a "while 1:" loop.

强制 标准输入 标准输出 标准错误 无缓冲 在nohup python test.py中用比较好 如
nohup python -u script.py > log.log 2>&1 & 会把日志实时写入log.log 而不是等待缓冲区
满了再写入
-W    警告相关的参数

2015年5月31日星期日

一次成功又失败的面试

       昨天去一个公司面试,做的事情侣移动应用。面试官太能说了,他说起话来可以持续很久的时间,听得我好累,对我这样反应比较慢的人来说好痛苦。
       他先问了我:"xxxxx学院是本科吧?",我说是的(高考考不好害死人啊...),接着说对我简历上的项目很有兴趣(其实那个东西很水,做得很烂,我参与的程度很低,简历实在没得写,哎),和他扯了几句,估计他也没听懂究竟是什么。
       接着他说要的是主程序,我就心虚了,我这种水货,怎么当主程序啊?! 然后他就开始balabala扯公司的前景和产品啥的,听得我一愣一愣的,然后就问我期待工资多少。其实我不太会谈工资,招聘网站上写的xx-xx,我直接说了个y,当然是比xx要少的,他就问我:"你觉得自己值这个价吗?"。我心里咯噔一下,这又是要鄙视我的啊(之前被鄙视太多了,还有直接给个3K的,应届生也不能只给3K啊。)。我竟无言以对,也没说出来个123,他竟然也没说什么,吓我一跳。接着说产品什么什么的,我跟着有一搭没一搭的扯着,最好搞了半天,他表示很看好我,问了我两次有没有其他面试我晕死啊,我几乎什么都没说,他一个技术问题也没问,如果我是面试官的话,根本看不出来自己的价值,肯定直接让我get out office了。看不出来是我在出卖劳动力还是他在销售产品。这公司肯定急缺人手,但是也不能这样玩吧,只看简历能看出来什么东西,难道是我的屌丝气质吸引了他?!这对公司和个人都是很不负责的事情。因为程序这种工作,还是要看看过去的代码,只看简历是没有用的,仅仅凭一个小时,看简历嘴上说说,怎么看出来一个人能不能做事情,这也太草率了。
       这次面试对我来说是成功的,因为我的求职目的达到了,同时也是失败的。因为我可能根本无力升任这个工作,真是纠结,不知道到底去不去,哈哈,可能我就是个矛盾体吧,很少自信,不过做事情的能力还算可以,真是撑死胆大的,饿死胆小的。

2015年5月25日星期一

为什么要有同源策略

   同源策略,是一个在Web应用安全中的一个重要的模型,它定义了两个站点之间是否可以执行彼此的脚本,比如A站不能通过脚本访问B站的cookie,不然会用户的信息毫无安全性可言了。
我们学会了如何解析URL,就好理解同源策略了,它的定义是:如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin)。那么两个在URL中:
scheme://[login[:password]@](host_name|host_address)[:port][/hierarchical/path/to/resource[?search_string][#fragment_id]]
scheme,host_name,port就决定了是否同源。具体实例可以参考MDN
那么为什么要有同源策略,没有的话怎么样,这篇文章里说,如果没有同源策略的话,你的个人信息容易被获取到,但是没说如何获取,在不同的浏览器Tab中,总无法读取另一个页面的DOM吧,简单的方法是使用iframe,我们看一个简单的例子,使用本地文本one.html作为一个含有敏感信息的网站:

one.html:
<input type="text" value="myuser" id="user" /> <br> <input type="password" value="123456" id="pwd" />
通过iframe.html读取它的信息,并把iframe隐藏掉:
<!DOCTYPE html> <html lang="en"> <head> <title>fream</title> <style> iframe { display: none; width: 1000px; height: 500px; } </style> <meta charset="UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <script> window.onload = function () { var iframe_one = document.getElementById('one-iframe'); var iframe_one_document = iframe_one.contentWindow.document; alert(iframe_one_document.getElementById('user').value + ' with password: ' + iframe_one_document.getElementById('pwd').value); } </script> <iframe id="one-iframe" src="./one.html" /> </body> </html>
这样就很容易得到有用的信息了,如果不同的域之间可以随意获取DOM对象数据的话,那么随便造很多网站就能得到其他网站的信息了,那样就无所谓安全了。 出于这样的考虑,有了同源策略,在同一个域下的脚本才能进行DOM操作,想要进行跨域操作的话,常见的是使用CORS或者JSONP,那将是另一个主题了。 如何绕过同源策略,更是一个有意思的安全问题,以后再深入学习吧。 参考: 1.同源策略——浏览器的安全卫士 2.JavaScript 的同源策略

2015年5月24日星期日

解析URL

  URL,就是我们天天使用的网址,英文全称叫做uniform resource locator,你可以把它理解成互联网上每个页面独一无二的名字。其实也不全是页面了,比如一些FTP下载资源,或者网页上的mailto链接,都是使用URL表示的。其实URL就相当于互联网字典上的索引,这些资源本来是一个个的孤岛,被一些工具(比如搜索引擎)整合后,使得互联网得以连接,所有的links加起来,就是我们看到的互联网了
URL的语法如下:
scheme://[login[:password]@](host_name|host_address)[:port][/hierarchical/path/to/resource[?search_string][#fragment_id]]
一个一个看:
  scheme,不是那个满屏幕小括号的编程语言,而是方案的意思,其实我认为可以理解成打开一个互联网资源的方式,比如http和ftp就是不同的方式,常用的scheme包括http,https,ftp,mailto,javascript,file(一般是打开本地浏览器可以打开的资源时使用的),chrome(Chrome浏览器特有的,一般用于插件)。scheme名称后加一个冒号,标准写法是在':'前只能出现[a-z][A-Z][0-1]+-.这些字符的,但是很多浏览器对于额外的字符也能够解释,比如下面这样的HTML代码,对于Chrome也是可以解析的:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>scheme</title>
</head>
<body>
    <a href="http:

www.baidu.com">baidu</a>
<a href="javascript	:alert(1);">javascript alert()</a>
</body>
</html>
& # 0 9 ;(合起来)在HTML中是TAB的转移字符,可以在free-formatter中转义回来。
不过对于Firefox第二个弹窗代码就没法使用了,它解释成了file:///Users/zookeep/Desktop/web/javascript:alert%281%29;一个本地文件的相对路径地址.

对于Safarier,会把第一个URL解释成http:%0A%0A//www.baidu.com其中的换行符变成了line feed就无法打开百度了。

对于scheme,我们试试file一个本地可执行文件hello.exe,发现它没法执行文件而是把它下载下来了,看来file方法只能打开浏览器可以识别的格式的文件,比如html,PDF等。

scheme后面跟了两个反斜杠//,如果不写的话,又会怎么样:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>without //</title>
</head>
<body>
    <a href="http:baidu.com">baidu</a>
    <a href="./http:baidu.com">baidu</a>
</body>
</html>
第一个没有指定目录,会被解释成和http://baidu.com一样的URL,而加上./(表示当前目录),则会被解释成一个本地的目录.
如果我们省略掉scheme的话,只用//filename的话又会怎样:

Chrome下 //filename 会打开本地文件 
Safair 则没反应
IE 会转到http://hello

下面是[login[:password]@]用户的认证信息,这个其实现在用处不大,几乎没人会让用户这样验证,都是表单验证了。
不过这个认证信息选项会让一些URL看起来很邪恶,我们以后再看。

接下来是主机名或者主机IP地址,比如localhost,或者一个域名google.com或者一个IP:http://74.125.130.99(同样是Google).不过这些常规的写法大家都明白,那么一些猥琐的写法可以是这样的:
http://0x7f.1
http://017700000001
同样都是localhost的表示,第一个是把点分十进制第一个127写成16进制,其他三个组成一个数字,第二个是把127.0.0.1每一个十进制都转为8进制然后加个0表示八进制的IP。 对于Google地址 74.125.130.99我们也可以这样写: >>> a = '74.125.130.99' >>> map(hex, map(int, a.split('.'))) ['0x4a', '0x7d', '0x82', '0x63'] >>> '.'.join(map(hex, map(int, a.split('.')))) '0x4a.0x7d.0x82.0x63' 或者: >>> '.'.join(map(oct, map(int, a.split('.')))) '0112.0175.0202.0143' 对于端口号倒是没什么可以玩的,记住常用的http是80, https是443就行了。 下一个是路径和资源比如/home/user/index.html这样的文件,不过现在很多都不显示文件的后缀了,因为都是动态网站了... 下一个是查询字符串,这个就很有用了,比如使用taobao的时候你输入的查询内容就会被填充到query中, 比如taobao.com/search?q=html就能在taobao找到你要的宝贝了... 下一个是片段ID,这个可是个好东西,不过注意它和服务器可是没有交互的,只是会在当前页面找到一片内容,由浏览器跳到那里去, 更多的内容可以参考 这里。 好了,我们基本上看完了URL的基本解析方式,那么如下的URL到底会把你带到哪里: http://qq.com&location=12306.com@evil.net http://a@b@c.com http://www.sina.com&id=123@0300.0250.01.01 ok,看第一个,这不就是qq嘛,好了,你把它输入Chrome一看,跑到了evil.net什么鸟玩意... 第二个,也许会是a@b@c.com,进去看看再说,不过Chrome把我们带到了c.com 第三个,估计是sina网吧...好吧,它把我带到了我的路由器登录页上.这是什么乱七八糟的?! 其实,URL的解释是没错的,不过我们忽视了登录信息罢了,[login[:password]@]: 第一个URL中,qq.com&location=12306都被当做了你访问evil.net的用户名了 同样的a@b也被当成c.com的认证消息了, 第三个也是一样,只不过把域名换成了一个IP地址,更加难以看出真实的hosts是谁.如果再用HTML转义一下,估计就没人能看清楚了,哈哈... 不过我发现,万能的Chrome还是可以在你的地址栏中高亮出真实的网址:
关于URL的解析我们算是搞明白了。

2015年5月20日星期三

涂鸦一个favicon

今天看这篇文章时候,看到示例代码在终端的结果如下:

GET / HTTP/1.1
Host: localhost:9999
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: csrftoken=sBvCVUzotPqq7jaeE52zOK3caXkMldSD


GET /favicon.ico HTTP/1.1
Host: localhost:9999
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
Accept: */*
Referer: http://localhost:9999/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: csrftoken=sBvCVUzotPqq7jaeE52zOK3caXkMldSD
我明明只是请求了根目录,Chrome却把/favicon.ico也一起请求过来了,不过没有设置favicon,就是空的。于是在tree house里看看如何设计一个favicon,发现一个有意思的web应用--X-Icon, 可以随意画画,画出来一个favicon,我也画一个玩玩:
新建一个HTML,代码如下,并把下载来下的favicon.ico放到一个目录下,打开的时候就有自己的网页图标了:
<link href="favicon.ico" rel="shortcut icon"/ >
这个宝贝还是挺好玩的,不过还是我随便画的图片更好玩一点,哈哈。

听声音判断性格

1.喜欢用质疑语气说话的人,往往比较强势。
2.说话语速快而且皱眉的人,往往耐性较差。
3.说话有气无力,让人觉得总想要休息一下的人,往往不是很自信,或者在思考。
4.说话时总是笑着的人,未必真的高兴。
5.胖的人一般比较好说话。(他们的声音一般比较粗,细声细气的人不好说话)
6.声音娘的男人不好说话。

PS:个人经验,未必靠谱。

2015年5月11日星期一

骇客交锋里的代码(code in blackhat)

       一直以来,对黑阔电影的里的代码比较感兴趣,最新新出了一部叫做<骇客交锋>的电影。 王力宏,汤唯和一个歪果仁(我不很了解)主演的,听电影的名字应该还不错。不过,票房和口碑貌似不怎么样,屏幕里的代码和命令倒是可以看看(据说:谷歌的工程主管,被称为“信息安全公主”的帕里萨·塔布瑞兹评价本片是她所见过的“最为准确的有关信息安全的电影”~),本着无聊加学习的心态,来看看这部电影里的代码:

1.貌似是C语言或者C++,看起来还像那么回事:

2.ssh登录远程主机,嗯:

3.cat命令得到文件内容,不过autorun.inf和mssvc就不太科学了,Unix系统下应该失效的吧:

4.陈小姐拽的两句术语还挺专业的:
  Your network is sitting behind deep packet inspection intrusion protection.

5.ls命令列出目录下文件:

6.WRT和onion router,挺专业:

7.who命令查看登录者:

8.whois查询IP网段和所有人,不过这个IP是个假的,而且显示也不太专业~:

9.write向其他终端写入字符,sdksdk这名字不错:

10.GNG加密

11.社会工程欺骗--下载的PDF原来是个keyboard-logger,不过,貌似是个文档啊,officer看都不看...




12.贴出来一个401未授权认证的静态网页就是IP地址了?401的页面应该是动态加载的吧(我只见过404是写死的)而且明明指的是ACCESS嘛,没看懂怎么回事...


13.mount命令挂载移动硬盘:


14.貌似Python的代码,不过==写成了=,二层if中也没加:另外返回值都是空的:



        总的来看还不错,不过硬伤也有。比起来其他黑客电影里,啪啪啪一通键盘,就关灯了(又可以继续啪啪啪了,嘿嘿),还是算可以的。从硬件到电路的特效做得也不错,不过电影本身不知道为什么这么不给力,哎,真为王力宏难过...

  PS:我们的解放军叔叔的普通话也太不正宗了...

2015年5月5日星期二

数据库基本概念

      一直以来对数据库都不太熟悉,在公司设计到的表也大多是一张或者两张,关联也很少做。 所以一直都不大懂数据库,SQL语句也只会最简单的。现在需要好好把基础概念搞清楚。

 一、数据库表 如果一个Excel文件是一个数据的话,那么一个Sheet就是一张表,一个数据库中可以有多张表,不过数据库中叫做Table。


 二、字段 Excel的一个Sheet中有行和列,数据库表中也有。第一行一般是字段的集合,剩下的每一行表示每一条记录,每一列表示这个字段的所有值。字段就是用于描述一个Table的属性的最小单位,如人口表中的姓名,年龄等等。


 三、键 和一本汉语字典类似,我们总希望快速地找到一个汉字的说明,一般使用拼音去找,这里的拼音就是键。不过拼音不能当成主键,因为有同音字,而主键是不能有重复的。每个表最好都有主键,如果没有的话,最好有一个唯一标识每条记录的字段。如IP定位库中,经常使用的是将每个点分十进制转为32位无符号整数所表示的数字,也能当做主键使用,可以减少一个字段的使用,减少空间占用。

 外键:如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外关键字。由此可见,外关键字表示了两个关系之间的联系。以另一个关系的外关键字作主关键字的表被称为主表,具有此外关键字的表被称为主表的从表。外关键字又称作外键。外键经常用来关联两张表使用。

 四、记录 记录,如果看Excel的话,就是每一行的数据,记录都是按照行(或者条)计数的。

 五、视图 视图也叫做虚表,即不是一个实际存在的表。一般情况下,是将几张表关联起来得到的一个数据集合,交给用户使用。如果更改视图中的数据,那么原始表中的数据也会修改,所以使用最好是只读的,这样不仅可以隐藏真实的表结构,而且根据业务定制视图函数,不用每次都去关联,更加灵活。

六、关系
     两张表的关系,在数据库中的Table,不像Excel中的Sheet,一般情况下,可能表和表之间都有些联系。两两之间的关系有三种:

 1.一对一的关系:
       比如领结婚证登记的时候,两个人都要登记,如果分成两个表,分别表示男女的话。
那么最简单的可以用两个字段就能描述婚姻关系了,自己的身份证+配偶的身份证。如果一方的删除,另一方的一定也要删除。正常情况下,不允许出现其它的情况。

2.一对多的关系:
       最经典的就是学生和班级的例子,班级有班级号码1,2,3等等,学生有学号0000-9999,学生表中还有班级号表示属于哪个班级的字段。这就是一个一对多的关系,一个班级对应多个学生,而一个学生只能对应一个班级。

3.多对多的关系:
        比较好的例子是公交车和公交站,一个公交站上可能有好几路公交车,一个公交车对应了很多个公交站。用公交车的路数找公交站,能找到很多个,同样,使用公交站牌号找公交车也能找到很多个。一般多对多的关系比较复杂,还是尽可能设计成一对多或者一对一的关系。

七、数据库设计的简单原则:

   0)每个表表示单一的主题,比如建立动物的数据库的表,最好不要设计成这样的字段。
   海洋 陆地 哺乳动物 非哺乳动物 因为他们的主题不是单一的,以至于难以给它起个名字。
   1)最好给每个表加一个主键,而且加上约束,比如在0-MAX_INT之间的数字。
   2)主键的值最好是不能修改的值,也最好不要更改主键的值。
   3)字段名字不用缩写,比如xsh,很难想出来他是学生号的意思,即便用拼音也要全拼。
   4)数据库中每个字段有唯一的名字,除非有关联的情况,不然最好在整个数据库中仅出现一次,
     比如每个表中最好不要都起一个ID作为主键名字,加上些描述性单词。
   5)最好给一些字段加上约束,避免出现错误的情况,比如性别,限定为男女,或者01,其他值都是非法的。
   6)每个字段最好只有一个部分,避免多部分字段。比如一个国内电话号码的字段,最好分开设计为两个字段:城市区号和电话号码。这样不仅方便查找,也方便更新。
   7)每个字段只有一个值,避免多值字段。比如学生选修课程这个业务,避免设计成一张表,包含课程号,加上N个选修的学生名字。这样难以查询和维护,这是一个多对多的关系,可以拆成三个表,一个课程表(主要包括课程号,课程描述),一个学生表(主要包括学生号,学生选课号),一个学生选课表(主要包括学生号,课程号)。这样就把多对多的化解掉了,方便查找和更改。
   8)减少关联表中的重复字段,有些字段可以通过两个表关联表得到,那么他们不应当作为表的自段,可以得到一个视图或者临时表,但是没必要设计成基表的字段。这样会使得表的结构臃肿。

2015年4月26日星期日

Python List和Tuple的区别

  面试中老是会问这个,还问使用场景,不过我一般只用list很少使用tuple,
没读过源码,简单的可以从以下几个方面说:
  1.列表里的内容是可以改变的,增删改都可以,tuple则不行:
>>> alist = [1,2,3,4]
>>> atuple = (1,2,3,4)
>>> atuple.append(1)
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'tuple' object has no attribute 'append'
>>> dir(atuple)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
>>> dir(alist)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
可以看出tuple根本没有修改的方法.
2.在Python中,字典的key必须是可哈希的,不可变的,所以tuple可以作为字典的键,而list则不行:

>>> adict = {}
>>> atuple = (1,2,3)
>>> adict[atuple] = 'ok'
>>> adict
{(1, 2, 3): 'ok'}
>>> alist = [1,2,3]
>>> adict[alist] = 'not ok'
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'
3.对于使用场景,tuple适合一些只读数据,如Python连接MySQL得到的结果就是使用tuple,
而list则在列表长度不固定或者需要有变动的数据中使用,另外,tuple的性能要比list好一些,
tuple比list更省内存:


>>> a = list(xrange(100000))
>>> a.__sizeof__()
900088
>>> b = tuple(xrange(100000))
>>> b.__sizeof__()
800024
而且更快,具体测试方法,参考stackoverflow

我和comcast网络


  前一段坐高铁的时候,翻阅上面的杂志,发现一篇吐槽美国网络巨头comcast的文章,说它如何坑,服务如何不好。我这土鳖也没用过comcast,无法评价它的服务到底如何。
  不过,comcast让我想起了在一家小公司打杂的经历,那时候需要对很多IP进行traceroute测量,简直是无尽的traceroute。然后对结果进行分析,得出一些结论,记得他们总说comcast的定位效果好,没想到现在离开了那里,依然可以看到comcast,不过是对comcast的吐槽。
  哈哈,网络真是把世界变得很小,我这个很少出省的人居然还能和大洋彼岸的ISP有点什么关系。
  最后再做一个traceroute玩玩,不知道下一次能玩traceroute是什么时候了:
➜  Desktop  traceroute www.comcast.com
traceroute to www-prd.g.comcast.com (96.114.156.20), 64 hops max, 52 byte packets
 1  10.10.0.1 (10.10.0.1)  87.486 ms  84.712 ms  88.840 ms
 2  106.187.33.3 (106.187.33.3)  94.097 ms  90.211 ms  85.432 ms
 3  124.215.199.125 (124.215.199.125)  83.513 ms  89.550 ms  91.969 ms
 4  * * otejbb206.int-gw.kddi.ne.jp (124.215.194.177)  110.009 ms
 5  pajbb002.int-gw.kddi.ne.jp (203.181.100.202)  222.177 ms
    pajbb002.int-gw.kddi.ne.jp (203.181.100.206)  214.200 ms
    pajbb001.int-gw.kddi.ne.jp (203.181.100.134)  205.113 ms
 6  ix-pa4.int-gw.kddi.ne.jp (111.87.3.42)  221.573 ms
    ix-pa4.int-gw.kddi.ne.jp (111.87.3.70)  225.931 ms  221.207 ms
 7  124.215.192.126 (124.215.192.126)  226.368 ms  216.431 ms  209.909 ms
 8  pos-3-15-0-0-cr01.ashburn.va.ibone.comcast.net (68.86.86.25)  263.942 ms
    pos-3-2-0-0-cr01.56marietta.ga.ibone.comcast.net (68.86.86.165)  227.324 ms
    pos-3-15-0-0-cr01.ashburn.va.ibone.comcast.net (68.86.86.25)  235.313 ms
 9  be-10919-cr01.1601milehigh.co.ibone.comcast.net (68.86.85.154)  265.006 ms  261.971 ms  239.354 ms
10  he-0-13-0-0-ar01.area4.il.chicago.comcast.net (68.86.94.126)  256.685 ms  253.493 ms  247.654 ms
11  te-0-1-0-0-ar02-d.potomac.co.ndcwest.comcast.net (68.86.206.2)  258.036 ms  254.292 ms  269.330 ms
12  162.151.27.218 (162.151.27.218)  241.044 ms  252.085 ms  259.350 ms
13  * * *
14  * * *
15  * * *
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  162.151.27.218 (162.151.27.218)  443.467 ms !X * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
30  * * *
31  * 162.151.27.218 (162.151.27.218)  216.655 ms !X *
32  * * *
33  * * *
从路由器上看出来,从日本走到了美国,(124.215.192.126 搞不好还是在海底的路由器呢) 到了芝加哥(不知道为什么,芝加哥总让我想起一些吃的东西,比如芝士汉堡什么的...), 科罗拉多州 最后就不知道消逝在哪了。
如果使用MaxMind的IP数据库的话,可以看出数据包经过的路由器:
from subprocess import Popen, PIPE
import re
import pygeoip

def get_traceroute_res(hostname, max_hop=10):

  p = Popen(['traceroute', '-m', str(max_hop), hostname], stdin=PIPE, stdout=PIPE, stderr=PIPE)
  output, err = p.communicate()
  rc = p.returncode

  return output


def get_all_ip(result):
  reip = re.compile(r'(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}(?![\.\d])')
  return [i for i in reip.findall(result) if i]

if __name__ == '__main__':

  result = get_traceroute_res('comcast.com')
  ip_list = get_all_ip(result)
  gi = pygeoip.GeoIP("GeoLiteCity.dat")

  for ip in ip_list:
    ip_info = gi.record_by_addr(ip)
    try:
      print ip_info['country_name'], ip_info['latitude'], ip_info['longitude'], ip
    except Exception, error:
      pass
结果如下:
Japan 35.69 139.69 106.187.33.3
Japan 35.69 139.69 106.187.33.3
Japan 35.69 139.69 124.215.199.125
Japan 35.69 139.69 124.215.199.125
Japan 35.69 139.69 124.215.194.178
Japan 35.69 139.69 124.215.194.162
Japan 35.69 139.69 124.215.194.177
Japan 35.69 139.69 203.181.100.66
Japan 35.69 139.69 203.181.100.202
Japan 35.69 139.69 111.87.3.46
Japan 35.69 139.69 111.87.3.54
Japan 35.69 139.69 124.215.192.126
Japan 35.69 139.69 124.215.192.126
United States 38.0 -97.0 68.86.85.154
United States 38.0 -97.0 68.86.94.126

2015年4月10日星期五

netcat 使用笔记

Netcat笔记

netcat是一个用来调试网络数据的工具,对调试网络编程来说十分方便,同时也可以实现很多强大的功能,对于网络安全也有很重要的意义。以下是一些常用用法的说明:

1.作为远程登陆shell工具使用:

在服务端运行以下命令在12345端口listen连接,这里-e /bin/bash为连接上以后可以执行bash命令:

gcc:~ zookeep$ netcat -l -p 12345 -e /bin/bash

在另一个终端连接服务并执行一些命令:

gcc:Desktop zookeep$ netcat 10.223.138.163 12345
ls | grep test
test
perl -e 'print "hello"';
hello
python -c "print 123"
123
uname -a
Darwin gcc.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun  3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64

2. -v选项,打印出得到的消息,-n选项,只接受点分IP地址,不再进行DNS解析:

如对于google.com

gcc:~ zookeep$ ping -c 4 google.com
PING google.com (74.125.200.113): 56 data bytes
64 bytes from 74.125.200.113: icmp_seq=0 ttl=48 time=117.342 ms
64 bytes from 74.125.200.113: icmp_seq=1 ttl=48 time=122.505 ms
64 bytes from 74.125.200.113: icmp_seq=2 ttl=48 time=118.082 ms
64 bytes from 74.125.200.113: icmp_seq=3 ttl=48 time=134.491 ms

--- google.com ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 117.342/123.105/134.491/6.864 ms

gcc:~ zookeep$ netcat -v -n 74.125.200.113 80
74.125.200.113 80 (http) open

如果使用-n时给出域名将无法解析:

gcc:~ zookeep$ netcat -v -n google.com  80
Error: Couldn't resolve host "google.com"

使用-v加域名是可以自动解析的:

gcc:~ zookeep$ netcat -v google.com 443
google.com [74.125.200.113] 443 (https) open

3.使用-lp进行listen并重定向对端输入:

gcc:~ zookeep$ netcat -v localhost 12345
localhost [127.0.0.1] 12345 (italk) open
hello world
test words from client
^CExiting.

在断掉client之后,server的当前目录下就会出现刚才输入的内容, 这个功能可以作为一个局域网下的通信工具。

4.作为轻量级端口扫描使用,更好的工具是nmap,打开12345端口以后,进行连接,可以得到源端口和目的端口的信息,以及是否连接成功:

gcc:~ zookeep$ nc -v localhost 12345
nc: connectx to localhost port 12345 (tcp) failed: Connection refused
found 0 associations
found 1 connections:
     1: flags=82
  outif lo0
  src 127.0.0.1 port 64609
  dst 127.0.0.1 port 12345
  rank info not available
  TCP aux info available

Connection to localhost port 12345 [tcp/italk] succeeded!
lll

5.一个复杂点的扫描实例,-r随机扫描端口列表,-w3超时时间3秒,-z使用0输入输出:

gcc:~ zookeep$ nc -v -n -r -w3 -z 127.0.0.1 10-15
nc: connectx to 127.0.0.1 port 15 (tcp) failed: Connection refused
nc: connectx to 127.0.0.1 port 11 (tcp) failed: Connection refused
nc: connectx to 127.0.0.1 port 10 (tcp) failed: Connection refused
nc: connectx to 127.0.0.1 port 13 (tcp) failed: Connection refused
nc: connectx to 127.0.0.1 port 12 (tcp) failed: Connection refused
nc: connectx to 127.0.0.1 port 14 (tcp) failed: Connection refused

6.从连接中得到一些信息,比如连接MySQL后得到版本(5.6.16):

gcc:Desktop zookeep$ netcat localhost 3306
J
5.6.16`QT3@'C\��'K$q.0DEnx34mysql_native_password

这个功能使用Python的简单实现:

import socket
import re

def get_mysql_version(ip_address):
  sock = socket.socket()
  addr = (ip_address, 3306)
  try:
    sock.connect(addr)
  except Exception, error:
    print error
  data = sock.recv(2046)
  re_obj = r'5.\d+.\d+'
  return re.findall(re_obj, data)[0]

if __name__ == '__main__':
  print 'MySQL version:', get_mysql_version('localhost')

7.进行HTTP请求:

gcc:~ zookeep$ netcat -v google.com 80
google.com [74.125.200.113] 80 (http) open
GET / HTTP/1.1

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.com.sg/?gfe_rd=cr&ei=-J4nVa73EIWCuASZ_4HgAQ
Content-Length: 262
Date: Fri, 10 Apr 2015 09:59:20 GMT
Server: GFE/2.0
Alternate-Protocol: 80:quic,p=0.5


302 Moved

302 Moved

The document has moved here.

8.扫描本机的开放端口:

gcc:Desktop zookeep$ netcat -v -z localhost 1-65535
localhost [127.0.0.1] 21 (ftp) open
localhost [127.0.0.1] 80 (http) open
localhost [127.0.0.1] 443 (https) open
localhost [127.0.0.1] 631 (ipp) open
localhost [127.0.0.1] 3306 (mysql) open
localhost [127.0.0.1] 8021 (intu-ec-client) open
localhost [127.0.0.1] 25035 open
localhost [127.0.0.1] 27017 open

2015年4月2日星期四

You had me at hello.

        不记得第一次在哪里看到这句话(You had me at hello.),一开始不知道什么意思,后来百度,类似中文“一见钟情”的意思。不过,还是觉得原文更有画面感:两个陌生人,也许在他人相互介绍后,笑着说句"hello"(不过惯例应该是Nice to meet you啊,哈哈),然后内心各种澎湃。而一见钟情貌似有很多种方式,我能想到的多半是男生面对漂亮女生,瞬间感觉fucking high,就像You are beautiful中所描述的一样。

        我曾有过一见钟情,不过还好,没有在fucking high后,因再也见不到而投海自尽。为什么是一见钟情而不是You had me at hello,因为我的hello还未说出口就没有然后了。可见,'You had me at hello.'和"一见钟情"还是有区别的,可以想象的画面是这样的:两人互有好感以后,有天谈论起什么时候有的感觉,在耳边小声地说:You had me at hello.而一见钟情根据我的经历可能就没有那种耳鬓厮磨的甜腻了。极端者如James Blunt所演绎的那样。

       也许,有些文字在想象以后才能体会出其中的差别,或者在经历以后才能体验出正确的使用场景。

   
print "You had me at hello"