碳基体

奋斗在产品安全第一线的安全妹子

十二、TCP/IP协议分析-DNS协议

一、DNS报文结构

DNS报文采用大端字节序,由DNS报头与DNS正文组成。

 

DNS报头定长12个字节,由

transaction ID 2个字节 

 + flags 2个字节

+questions 2个字节 查询段中的条目数

+answers RRs 2个字节 应答段中的资源记录数

+authority RRs 2个字节 授权段中的资源记录数

+additional RRs 2个字节  附加段中的资源记录数

组成。


其中flags对应的术语:

QR query/response 1位 0表示query 1表示response

OPCODE 4位   值为0表示标准查询,值为1表示逆向查询,值为2表示查询服务器状态,值为3保留,值为4表示通知,值为5表示更新报文,值6~15的留为新增操作用

AA 是否要求授权,在响应中有效

TC 是否截断

RD 是否期望递归

RA 是否递归可用

Z 保留位

RCODE 响应码4位:值0表示没有错误;1表示格式错误;2表示服务器故障;3表示名字错误,仅对来自权威服务器的响应有意义,表示查询中引用的域名不存在;4表示没有实现;5表示拒绝;6-15保留将来使用

bin(int('8180',base=16))‘0b1000000110000000' 


   



DNS正文包括

Question查询段、Answer应答段、Authority授权段、Additional附加段。

例如:对smtp.aol.com进行域名查询

    

Question查询段包括

qname 变长,以\0x00结尾

+ qtype 2个字节

+ qclass 2个字节 

  

  qtype常见的类型 

0x0010 (16)  表示TXT,e.x. cujo.movie.edu. IN TXT “Location: machine room dog house"

0x000f (15) 表示MX,  e.x. ora.com IN MX 0 ora.ora.com.

                                                        IN MX 10 ruby.ora.com

                                                        IN MX 10 opal.ora.com

0x001d (29)表示LOC location information,

0x000c (12) 表示PTR domain name pointer,e.x. 1.249.249.192.in-addr.arpa. IN PTR wormhole.movie.edu.

0x000d (13)表示 HINFO host information, e.x. grizzly.movie.edu. IN HINFO VAX-11/780 UNIX

0x0001  (1) 表示A (host address) e.x. localhost.movie.edu. IN A 127.0.0.1

0x001c  (28)表示AAAA (IPv6 address)

0x0005 (5) 表示CNAME ,e.x. wh.movie.edu. IN CNAME wormhole.movie.edu.

0x00ff (255) 表示 *(A request for all records the server/cache has available),

0x002 (2) 表示NS(authoritative name server),e.x. movie.edu. IN NS terminator.movie.edu

0x0021 (33)表示SRV(server selection)) 

0x0006 (6) 表示SOA 



Answer应答段、Authority授权段、Additional附加段包括: 

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

+ type  2个字节 

+ class  2个字节 

+ time to live 4个字节 

+ data length 2个字节 ,前2位必须是00,后面6位用于计算长度

+ data 变长

  

  

DNS数据格式

1. 2个字节整型

2. 4个字节整型

3. 域名

  

4.字符串

  


二、示例 

1. txt类型 可任意填写,可为空。一般做一些验证记录时会使用此项,如:做SPF(反垃圾邮件)记录

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x0010 10表示TXT类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x0000010e

+ data length 2个字节  0x0010

+ data 变长 = (txt length 1个字节 0x0f + txt content组成)

  

2. MX类型 建立电子邮箱服务,将指向邮件服务器地址,需要设置MX记录。建立邮箱时,一般会根据邮箱服务商提供的MX记录填写此记录

 

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x000f 15表示MX类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00000228

+ data length 2个字节  0x000a

+ data 变长 = (preference优先级 2个字节 0x0028

 + mail exchange组成 0x 05 73 6d 74 70 34 c0 0c --> smtp4.google.com

      

3. A类型

  

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

以0xc02a  为例:

bin(int('c02a',base=16)) ---> '0b1100000000101010'

int('00000000101010',base=2) --->42   ,头2位都是11,表示域名采用消息压缩,偏移量为42

+ type 2个字节  0x0001 1表示A类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00000258

+ data length 2个字节  0x0004

+ data 变长 = (ip地址 0x d8ef251a

int('d8ef251a',base=16) ----> 3639551258

socket.inet_ntoa(struct.pack('!L',3639551258)) ---> 216.239.37.26

 )

  4. PTR类型 PTR记录是A记录的逆向记录,又称做IP反查记录或指针记录,负责将IP反向解析为域名 

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x000c 12表示PTR类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00015125

+ data length 2个字节  0x0020

+ data 变长 

  5. AAAA类型  将主机名(或域名)指向一个IPv6地址(例如:ff03:0:0:0:0:0:0:c1),需要添加AAAA记录 

name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量 

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x001c 28表示PTR类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00015180

+ data length 2个字节  0x0010

+ data 变长 

 

6. CNAME类型 如果将域名指向一个域名,实现与被指向域名相同的访问效果,需要增加CNAME记录。这个域名一般是主机服务商提供的一个域名

  name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量 

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x0005 5表示CNAME类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00000279

+ data length 2个字节  0x0008

+ data 变长 ( 0x 03 77 77 77 01 6c c0 10 --- www.l.google.com)

  7.NS类型  域名解析服务器记录,如果要将子域名指定某个域名服务器来解析,需要设置NS记录 

  

  name 2个字节 域名重复出现的时候采用消息压缩。头2位都是11,用于与标识区区别,后14位表示偏移量

以0xc00c  为例:

bin(int('c00c',base=16)) ---> '0b1100000000001100'

int('00000000001100',base=2) --->12   ,头2位都是11,表示域名采用消息压缩,偏移量为12

+ type 2个字节  0x0002 2表示NS类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x0000000e

+ data length 2个字节  0x000e

+ data 变长 ( 0x 06 6e 73 2d 65 78 74 04 6e 72 74 31 c0 0c --- ns-ext.nrt1.isc.org)

  

  8.SOA 类型 SOA叫做起始授权机构记录,NS用于标识多台域名解析服务器,SOA记录用于在众多NS记录中那一台是主服务器 

  name 0x00

+ type 2个字节  0x0006 6表示SOA类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00000005

+ data length 2个字节  0x0040

+ data 变长 (Primary Name Server

 + Responsible authority's mailbox

+ serial number 4个字节

+ refresh interval 4个字节

+ retry Interval 4个字节

+ expire limit 4个字节

+ minimum ttl 4个字节)

  9. SRV 类型:添加服务记录服务器服务记录时会添加此项,SRV记录了哪台计算机提供了哪个服务。格式为:服务的名字.协议的类型(例如:_example-server._tcp) 

   name 0xc00c

+ type 2个字节  0x0021 33表示SRV类型

+ class 2个字节  0x0001

+ time to live 4个字节 0x00000258

+ data length 2个字节  0x001a

+ data 变长 (Priority 2个字节

 + weight 2个字节

+ Port 2个字节

+ target)

 

来源:碳基体

bbcp-局域网中大文件的快速传输

需求:

1. 局域网中传输大文件,文件大小大于100G

2. 无加密要求

3. 文件完整性要求低

4. 越快越好


结论:

bbcp


使用实例:

一、安装(传输的双方机器都需要安装同版本的可执行文件)

wget http://www.slac.stanford.edu/~abh/bbcp/bbcp.tgz


tar zxvf bbcp.tgz

cd bbcp/src/

make

cp bbcp/bin/amd64_linux26/bbcp /usr/bin/

二、使用

/usr/bin/bbcp -F -P 2 -V -w 10m -s 16 -T 'ssh -x -a -oFallBackToRsh=no %I -l %U %H /home/xxx/bin/bbcp'

src_file_path user@host:/home/xxx/dest_file_path

选项说明

-F: 不检查目的机器的磁盘空间大小是否还够

-P: 指定每个进程的启动时间,单位s

-w: 磁盘IO buffer大小

-s: 并发streams数 

-T 指定如何远程启动bbcp

-V: 显示传输详细细节


三、优化

可以使用以下选项来加快传输速度

1. 关闭域名查找

-n

2. 磁盘IO buffer大小与并发streams数的合理设置

传输是否快取决于机器的内存和带宽,上面两个数值在内存不会耗尽的情况下理论上是设置越大越好,当然实际情况要找到一个平衡点。


参考http://pcbunn.cithep.caltech.edu/bbcp/using_bbcp.htm 给出的测试数值:

a. 并发streams数的设置

局域网中 -s 设置为16或32比较好


b.磁盘IO buffer大小的设置

可以使用iperf来获得带宽数量

服务端

iperf -s

客户端

iperf -c server_ip -t 60 -i 2 -w 200k -n 10400000 -d

-t 测试时间

-i 以秒为单位显示报告间隔

-w 指定TCP窗口大小,默认8k

-n 指定传输的字节数

-d 进行双向传输测试

[  5]  0.0- 1.1 sec  10.0 MBytes  76.5 Mbits/sec

那么窗口大小设置为

-w 0.5*76.5比较合适


四、问题

再次感叹自己的bug体质

1. bash: bbcp: command not found

找不到目的机器的bbcp路径

首先查看一下默认的bbcp路径

ssh user@host which bbcp

然后copy或建立符号链接到bbcp目标路径

如果没有权限将bbcp移动到指定路径,可以使用 -T 指定bbcp路径

-T 'ssh -x -a -oFallBackToRsh=no %I -l %U %H /home/xxx/bin/bbcp'


2. bbcp: Insufficient space to copy all the files

bbcp在传输的过程中会检查目的机器的磁盘空间大小,当然这个空间大小的探测可能不准确。

可以使用 

-F 选项关闭磁盘大小检测


3.bbcp: No space left on device writing

目的机器真的磁盘空间不够,整理整理吧,以我的经验不少磁盘空间不够是因为被标记删除的文件仍在被进程使用造成。

可以使用以下命令杀死这些进程

lsof | grep deleted|while read abc;do kill -9 $abc;done



参考:

http://pcbunn.cithep.caltech.edu/bbcp/using_bbcp.htm

https://www.olcf.ornl.gov/kb_articles/transferring-data-with-bbcp/

http://www.slac.stanford.edu/~abh/bbcp/

https://www.52os.net/articles/iperf-check-bandwidth.html

来源:碳基体

NFA引擎正则优化TIPS、Perl正则技巧及正则性能评测方法

一、性能优化Tips

1. 优先选择最左端的匹配结果


2.标准量词优先匹配

比如'.*[0-9][0-9]' 来匹配字符串"abcd12efghijklmnopqrstuvw",这时候的匹配方式是‘.*’先匹配了整行,但是不能满足之后的两个数字的匹配,所以‘.*’就退还一个字符‘w’,还是无法匹配,继续退还一个‘v’,循环退还字符到‘2’发现匹配了一个,但是还是无法匹配两个数字,所以继续退还‘1’


3.谨慎使用捕获性括号(),选择使用非捕获性括号(?:expression)

捕获性括号需要消耗一部分内存


4.使用字符组代替分支(替换)条件

例如用[a-d] 代替 a|b|c|d避免不必要的回溯


5.不要滥用字符组(单个字符时不要用字符组)

\. 代替 [.]


6.使用锚点^ $ \b 加速定位


7.从两次中提取必须元素

a{2,4} 写成 aa{0,2}


8.提取多选结构开头的相同字符

the|this 改成th(?:e|is)


9.选择字符串中最常出现的字符串放到分支最前面


10.能懒则懒,不要贪婪

在 * + {m,n}后面加上问好?就会变成非贪婪模式


总结:引用CFC4N大牛的一句话 滥用. 点号  * 星号  +加号  ()括号 是不环保,不负责任的做法 !


11.简单字符串处理应避免使用正则表达式


二、Perl正则技巧

1)仅需分组时,用非捕获括号

圆括号在perl正则表达式中,有分组和捕获的作用

在split中使用非捕获括号,以关闭分隔符保留模式

让处理器花时间去捕获不需要的子字符串是一种浪费


2)能懒则懒,不要贪婪

perl正则表达式默认返回能找到的最左最长匹配

在 * + {m,n}后面加上问好?就会变成非贪婪模式


3)用零宽断言匹配字符串中的特定位置

用\b判断单词与非单词之间的边界

用\A或 \z匹配字符串的绝对起始或绝对末尾

在多行模式(/m)下,用^或$分别匹配每一行文本的行首或行尾


4)避免不必要的回溯

(1)用字符组[abc]代替多选结构

(2)避免量词*引起的不必要回溯

在任意量词后面加一个+号,该量词就变成占有优先量词,占有优先量词包括 *+  ++ ?+ {m,n}+ {m,}+ 目前仅Java和PCRE支持


5)仅编译正则表达式一次

可在正则表达式中用/o标示只需编译一次,但如果正则表达式中使用了内插变量(/$a/) ,需酌情考虑


6)预编译正则表达式

使用qr//操作符预编译正则表达式,用eval检测模式非法的正则表达式,如下所示

my $name = '(';
my $regex = eval { qr/\b$name\b/ } or die "Regex failed : $@";

由于左括号没有配对,所以报错

Regex failed : Unmatched ( in regex; marked by <-- HERE in m/\b( <-- HERE \b/ at ./re_qr.pl line 6.


7)正则表达式的调试及性能评测

使用use re ‘debugcolor’开启调试

benchmark模块比较正则表达式的效率

例子见三、正则调试及评测方法


8)不要滥造正则表达式,使用已封装好的常用正则表达式模块

use Regexp::Common;

例子见四、常用的正则匹配



三、正则调试及评测方法

1. 调试

以调试贪婪与懒惰模式为例

#!/usr/bin/perl
use strict;
use warnings;
use feature qw(say);
use re 'debugcolor';

my $re1 = '<div>.+</div>'; #贪婪匹配
my $re2 = '<div>.+?</div>';# 懒惰匹配

my $str = '<div>testtest</div><div>testtest2</div>';

$str =~ /$re1/;

$str =~ /$re2/;

运行结果

 有上图可以看出来,perl默认开启贪婪匹配模式,.+会一直定位到字符串末尾,然后开始往前回溯。


2.计算正则花费时间

以贪婪与懒惰模式为例

#!/usr/bin/perl
use strict;
use warnings;
use Time::HiRes qw(gettimeofday time);

my $str = "<div>testtest</div><div>testtest2</div>" x 10000;

my $re1 = '<div>.+</div>';

my $re2 = '<div>.+?</div>';


#计算<div>.+</div>花费时间

my $starttime = time();
         
$str =~ /$re1/;
         
my $endtime = time();
my $time_cost = $endtime - $starttime;
printf( "$re1 time costs:  %.6f seconds.\n",$time_cost);

#计算<div>.+?</div>花费时间
my $starttime2 = time();
    
$str =~ /$re2/;

my $endtime2 = time();
    
my $time_cost2 = $endtime2 - $starttime2;
    
printf("$re2 time costs: %.6f seconds . \n",$time_cost2);


运行结果

这里只是简单地进行估算,如果要更准确,需要多次计算花费时间,如下文介绍的。 


3. 正则性能计算

以查找拥有10w条访问日志的lighttpd 服务器为例

#!/usr/bin/perl
use strict;
use warnings;

use Benchmark qw(:all);

my @data = <>;

timethese(
     -5,
    {


        mem => q{
            foreach (@data){
                 /(\w+(\.\w+)+)/;
            }
        },

        memfree => q{
            foreach (@data){
                /(\w+(?:\.\w+)+)/;
            }
        },

    }


);


运行结果如下:

 测试拥有记录

 
 捕获性

四、Regexp::Common常用的正则匹配

以 匹配IP地址为例

#!/usr/local/bin/perl
use strict;
use warnings;
use Regexp::Common qw (net);

while (<>){
    chomp $_;
    print "$_ IPv4 address \n" if /$RE{net}{IPv4}/;
    print "$_ IPv6 address \n" if /$RE{net}{IPv6}/;

}

运行结果如下:

 



参考:

CFC4N 的PPT〈正则表达式〉

《perl高效编程》

《perl最佳实践》

正则cheatsheets 


来源:碳基体

github最基本的使用

记录最简单的github源码托管操作,其实,作为IT人员,现在才提起github,已经过时到不行了。



最早接触github,完全是因为要“借用”大牛们编写的工具。于是最先学会了

git clone 地址 来下载源码

git pull 与更新源码


题外话,由于强迫症似的到处收集工具,除了git以外,还接触了Mercuria (hg),Subversion(svn)这些版本管理工具,但最最流行的还是git,其中github起到了巨大的推广作用(看看git的出书,it杂志上的git专栏)。


好了,回到正题。


首先,我们需要在本地机器上安装git


一、git安装

1. 本地安装git

windows下

下载

http://msysgit.github.io/


Debian/Ubuntu下

apt-get install git


Mac上


brew install git  或者 http://code.google.com/p/git-osx-installer


2. git命令自动补全

git clone https://github.com/git/git.git

cp git/contrib/completion/git-completion.bash ~/.git-completion.bash

vim ~/.bashrc

添加 

source  ~/.git-completion.bash

source .bashrc 

更多学习参考:http://git.oschina.net/progit/index.html



二、github注册帐号及基本的操作(以上传README文件为例)

1. github 注册帐号

https://github.com/


2.git全局配置

git config --global user.name "xxx" #你在github上的帐号 

git config --global user.email "xxx@gmail.com"#你在github上的邮箱地址


3.在github上创建一个repository

https://github.com/

点击create repositories, 为repository取个名字,以perl_tools为例


4.在本地创建源码文件夹

mkdir perl_tools

cd perl_tools/

git init


5.提交文件,以提交README文件为例 



vim README #在工作目录下修改文件,此时文件的状态是已修改状态


随便写点啥


git add README #将修改文件放到暂存目录,此时文件的状态是已暂存状态

git commit -m 'create README file' #将放置在暂存目录中的文件提交到本地仓库此时文件的状态是已提交状态

git remote add origin https://github.com/[github username][github_repository_name].git #添加远程仓库,例子中将远程仓库取名为origin,这个操作只需要一次,后续修改上传文件都不要执行

git push origin master #将本地仓库master的数据推送到远程仓库origin

Username for 'https://github.com': xxx
Password for 'https://xxx@github.com':

就ok了,上传其他文件步骤相同。


三、我的github

https://github.com/tanjiti/perl_tools

尝试上传了几个最近写的小工具(申明我是编程菜鸟),像搭积木,蛮好玩的


isRealSpider.pl 判断指定ip是不是google/baidu/yahoo/bing/msn爬虫

 

getIPinfoOnline.pl 查询指定IP的基本信息,读取了以下在线IP接口

    1  ipinfo.io

    2  ip-api.com

    3  ip-taobao.com 淘宝IP

    4  www.cz88.net 纯真IP

    5  ip.chinaz.com 站长之家IP

 

getIPinfoOffline.pl 从本地离线IP数据库查询指定IP/域名的基本信息,IP数据库来自maxmind.com

 

whichCDNUser.pl 判断指定host是否使用了CDN服务(能识别cloudflare,incapsula,360网站卫士, 加速乐,云加速,安全宝)

 

readTitle.pl 读取指定域名的title,主要加入了中文解码

 

来源:碳基体

使用免费的本地IP地理库来定位IP地理位置-GeoIP lookup

网上有不少IP地理位置查询的API,像ip-api.com,但为了避免造成查询服务超载,都限制了查询数,所以最好的办法还是将IP地理库下载到本地,然后进行查询。


而其中IP地理库会按精确程度(其实就是更新是否及时)进行收费,当然也会好心的开放一下不用收费但没有那么准确的数据库


以下介绍利用maxMind提供的免费的IP地理库来定位IP的地理位置

一、GeoIP的使用

第一步:安装geoiplookup

以debian为例,安装包安装

apt-get install geoip-bin


在其他操作系统上可以采用手动编译安装

wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz

tar zxvf GeoIP.tar.gz

cd GeoIP-1.4.8/

./configure

make

make install

echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf

ldconfig


安装成功后,有以下重要文件

可执行文件:geoiplookup   geoiplookup6  geoipupdate

配置文件/etc/GeoIP.conf.default (数据库更新需要的身份认证配置),对于免费用户,不用管


第二步:下载(更新)IP地理库

maxMind提供按月更新的数据库,可以使用crontab 来定期更新这些数据库

以下编写一个脚本来下载数据库,并检查是否存在更新,脚本运行环境需要安装wget,gunzip,md5sum,当然大多数linux环境都已经安装

vim installGEODB.sh


#!/bin/bash
#下载免费数据库

#GeoLite Country
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
#GetLite Country IPv6
#wget http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz
#GeoLite City
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
#GeoLite City IPv6(Beta)
#wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz
#GeoLite ASN
wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
#GeoLite ASN IPv6
#wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNumv6.dat.gz


#解压缩

#gunzip
gunzip GeoIP.dat.gz
gunzip GeoLiteCity.dat.gz
gunzip GeoIPASNum.dat.gz

#get the md5 of binary file
#generate md5 value of the dat


#根据数据库文件的md5值来判断是否存在更新
if [ ! -f GeoIP_md5 ]
then
   md5sum  -b GeoIP.dat > GeoIP_md5
   cp -f GeoIP.dat /usr/share/GeoIP/
else
   GeoIP_result=$(md5sum -c GeoIP_md5)
fi

if [ ! -f  GeoLiteCity_md5 ]
then
   md5sum  -b GeoLiteCity.dat > GeoLiteCity_md5
   cp -f GeoLiteCity.dat /usr/share/GeoIP/
else
   GeoLiteCity_result=$(md5sum -c GeoLiteCity_md5)
fi


if [ ! -f GeoIPASNum_md5 ]
then
   md5sum  -b GeoIPASNum.dat > GeoIPASNum_md5
   cp -f  GeoIPASNum.dat /usr/share/GeoIP/
else
   GeoIPASNum_result=$(md5sum -c GeoIPASNum_md5)
fi


if [[ $GeoIP_result =~ OK$ ]]
then
   echo "GeoIP.dat not updating"
   rm -f GeoIP.dat
else
   echo "GeoIP.dat updating"
   md5sum  -b GeoIP.dat > GeoIP_md5
   mv -f GeoIP.dat /usr/share/GeoIP/
fi


if [[ $GeoLiteCity_result =~ OK$ ]]
then
   echo "GeoLiteCity.dat not updating"
   rm -f GeoLiteCity.dat
else
   echo "GeoLiteCity.dat updating"
   md5sum  -b GeoLiteCity.dat > GeoLiteCity_md5
   mv -f GeoLiteCity.dat /usr/share/GeoIP/
fi

if [[ $GeoIPASNum_result =~ OK$ ]]
then
   echo "GeoIPASNum.dat not updating"
   rm -f GeoIPASNum.dat
else
   echo "GeoIPASNum.dat updating"
   md5sum  -b GeoIPASNum.dat > GeoIPASNum_md5
   mv -f GeoIPASNum.dat /usr/share/GeoIP/
fi


chmod +x installGEODB.sh 


使用crontab在每月的1号执行更新操作

00 00 1 * * cd /home/getipDB ; /bin/bash /home/getipDB/installGEODB.sh 2>&1 &


第三步:使用geoiplookup获得地理位置

接下来我们就可以使用geoiplookup来查看指定的ip信息了

-bash-4.2# geoiplookup -f /usr/share/GeoIP/GeoIP.dat 61.55.186.15
GeoIP Country Edition: CN, China
-bash-4.2# geoiplookup -f /usr/share/GeoIP/GeoLiteCity.dat 61.55.186.15
GeoIP City Edition, Rev 1: CN, 10, Hebei, N/A, 39.889702, 115.275002, 0, 0
-bash-4.2# geoiplookup -f /usr/share/GeoIP/GeoIPASNum.dat 61.55.186.15
GeoIP ASNum Edition: AS4837 CNCGROUP China169 Backbone


在上面的基础上(安装了getiplookup, 和ip地理库)我们可以编写脚本来一次性获得指定ip或者host的所有ip地理位置,脚本如下所示:脚本使用perl编写,运行前需要安装

cpan -i Getopt::Long

cpan -i Term::ANSIColor

vim geoiplookup.pl

#!/usr/bin/perl -w
use Getopt::Long;
use Term::ANSIColor qw(:constants);

#命令行选项部分
my $help = "";
my $ip = "";
my $host = "";

local $Term::ANSIColor::AUTORESET = 1;

GetOptions(
'help|h'=>\$help,
'ip=s'=>\$ip,
'host=s'=>\$host
);


if($help){
print <<__HELP__;
Usage: $0 -ip 61.55.186.15 -host tanjiti.com

where:
-ip : Specify the ip address to query
-host: Specify the host address to query

__HELP__
exit 0;

}

chomp $ip;

die "You need to specify the ip address or hostname to query!!!! " if  ($ip eq "" and $host eq "");

#查询指定ip的地理信息
#query the specify ip geo information
geoiplookup($ip) if $ip ne "";

#查询指定host的地理信息
#query the specify host geo information
if ($host){
   my $ips=hosttoIP($host); 

   my @ips = split(' ',$ips);
   
   print BOLD RED "$host GEO information: \n";

   foreach (@ips){
      geoiplookup($_);
   }
}


#hosttoIP子函数:host反查获的域名对应的ip
sub hosttoIP{
   my $host = shift;
   my $ips = `host $host  | awk '{i=1; if(NF>0) do {if (\$i ~ /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/) print \$i; i++;} while (i <=NF);}'`;
   return $ips;
}

#geoiplookup子函数,调用geoiplookup与对应的地理数据库获得指定ip的地理信息
sub  geoiplookup{
   my $ip = shift;
   chomp $ip;

   my $country = `geoiplookup -f /usr/share/GeoIP/GeoIP.dat $ip`;
   my $city = `geoiplookup -f /usr/share/GeoIP/GeoLiteCity.dat $ip`;
   my $ASNum = `geoiplookup -f /usr/share/GeoIP/GeoIPASNum.dat $ip`;

   print BOLD BLUE "$ip GEO information: \n";
   print "\t",$country;
   print "\t",$city;
   print "\t",$ASNum;
}


chmod +x geoiplookup.pl

该脚本的使用方法

perl geoiplookup.pl --help
Usage: geoiplookup.pl -ip 61.55.186.15 -host tanjiti.com

where:
-ip : Specify the ip address to query
-host: Specify the host address to query

获得指定ip的地理信息

perl geoiplookup.pl -ip 61.55.186.15
61.55.186.15 GEO information: 
        GeoIP Country Edition: CN, China
        GeoIP City Edition, Rev 1: CN, 10, Hebei, N/A, 39.889702, 115.275002, 0, 0
        GeoIP ASNum Edition: AS4837 CNCGROUP China169 Backbone

获得指定host的地理信息

perl geoiplookup.pl -host weibo.com
weibo.com GEO information: 
114.134.80.187 GEO information: 
        GeoIP Country Edition: HK, Hong Kong
        GeoIP City Edition, Rev 1: HK, N/A, N/A, N/A, 22.250000, 114.166702, 0, 0
        GeoIP ASNum Edition: AS9304 Hutchison Global Communications



二、GeoIP2的使用

我们也可以直接读取地理数据库的内容来获得ip地理信息


第一步:下载地理数据库(免费版本)

wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gzwget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz (其实,有上面那个就ok了gunzip  GeoLite2-Country.mmdb.gz gunzip  GeoLite2-City.mmdb.gz

第二步:使用python解析数据库,查询指定的ip地理信息

pip install maxminddb #用于解析maxmind DB

vim geoiplookup.py  

#!/usr/bin/env python

import sys

import maxminddb

import subprocess

import re

import json

import getopt


#specify the ip geo db path
GeoLit2_city = "/root/getipDB/GeoLite2-City.mmdb"


#ipInfo():获得指定ip的地理信息 ,以json格式返回

def ipInfo(ip):
   readerCity = maxminddb.Reader(GeoLit2_city)

   cityInfo = readerCity.get(ip)
   print "\033[1;33;40m"
   print "%s 's Geo information:" % ip
   print "\033[0m"
   print json.dumps(cityInfo, sort_keys=True, indent=2)

   readerCity.close()


#hostToIP():调用外部命令host,反查域名所在ip

def hostToIP(host):
   try:
      ipInfo = subprocess.check_output(['host',host],stderr=subprocess.STDOUT,)
   except subprocess.CalledProcessError as err:
      print "ERROR:",err
   else:
      ips = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',ipInfo)

      return ips


#hostInfo():获得指定域名的地理信息
def hostInfo(host):

   print "\033[1;31;40m"
   print "%s 's gep information: " % host
   print "\033[0m"
   ips = hostToIP(host)
   for item in ips:

      ipInfo(item)chmod +x geoiplookup.py


#usage(): 脚本帮助信息,显示各个选项的使用方法

def usage():

   print "%s [-ip 61.55.186.15] [-host tanjiti.com]" % sys.argv[0]
   print "\t -d or --domain : specify the host for query"
   print "\t -i or --ip: specify the ip for query"
   print "\t -h or --help: for more help"


#main():主函数体

def main():
   try:
      opts,args = getopt.getopt(sys.argv[1:],"i:d:h",["ip=","domain=","help"])
   except getopt.GetoptError as err:
      print str(err)
      usage()
      sys.exit(2)
   else:
      for opt,val in opts:
         if opt in ('-h','--help'):
            usage()
            sys.exit()
         elif opt in ('-i','--ip'):
            ipInfo(val)
         elif opt in ('-d','--domain'):
            hostInfo(val)
         else:
            assert False,"unhandled option"

if __name__ == "__main__":
   main()

该脚本的使用方法

python geoiplookup.py -h
geoiplookup.py [-ip 61.55.186.15] [-host tanjiti.com]
 -d or --domain : specify the host for query
 -i or --ip: specify the ip for query
 -h or --help: for more help

获得指定ip的地理信息

python geoiplookup.py --ip 74.125.224.84

74.125.224.84 's Geo information:

{
  "city": {
    "geoname_id": 5375480, 
    "names": {
      "de": "Mountain View", 
      "en": "Mountain View", 
      "fr": "Mountain View", 
      "ru": "\u041c\u0430\u0443\u043d\u0442\u0438\u043d-\u0412\u044c\u044e", 
      "zh-CN": "\u8292\u5ef7\u7ef4\u5c24"
    }
  }, 

...

获得指定host的地理信息

python geoiplookup.py --domain tanjiti.com

tanjiti.com 's gep information: 


190.93.246.150 's Geo information:

{
  "city": {
    "geoname_id": 3621849, 
    "names": {
      "de": "San Jos\u00e9", 
      "en": "San Jos\u00e9", 
      "es": "San Jos\u00e9", 
      "fr": "San Jos\u00e9", 
      "ja": "\u30b5\u30f3\u30db\u30bb", 
      "pt-BR": "San Jos\u00e9", 
      "ru": "\u0421\u0430\u043d-\u0425\u043e\u0441\u0435"
    }
  }, 

源码放在我的github上,https://github.com/tanjiti/perl_tools/blob/master/getIPinfoOffline.pl



参考:

http://www.geekfan.net/7863/

http://xmodulo.com/2014/03/geographic-location-ip-address-command-line.html

来源:碳基体

Mac使用rz,sz远程上传或下载文件

SecureCRT有个很便捷的文件上传下载工具sz与rz,我们同样可以把这样的便捷带到mac上,只是稍微有一点点麻烦


第一步:下载并安装iterm2  


地址:http://www.iterm2.com/#/section/downloads


第二步: 下载并安装lrzsz


brew install lrzsz

安装成功后,会在以下路径生成两个可执行文件(具体的路径取决于brew配置,可以用find查找一下)

/usr/local/Cellar/lrzsz/0.12.20/bin/rz

/usr/local/Cellar/lrzsz/0.12.20/bin/sz


建立符号连接

ln -s /usr/local/Cellar/lrzsz/0.12.20/bin/sz /usr/local/bin/sz

ln -s /usr/local/Cellar/lrzsz/0.12.20/bin/rz /usr/local/bin/rz



第三步:下载并安装automatic zmoderm for iTerm2

源码:https://github.com/mmastrac/iterm2-zmodem

注意黄色字体,需要修改为实际sz与rz的路径

cd /usr/local/bin/

wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-send-zmodem.sh

vim iterm2-send-zmodem.sh

#!/bin/bash


# Author: Matt Mastracci (matthew@mastracci.com)


# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script


# licensed under cc-wiki with attribution required


# Remainder of script public domain




FILE=`osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose file with prompt "Choose a file to send"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`


if [[ $FILE = "" ]]; then


        echo Cancelled.


        # Send ZModem cancel


        echo -e \\x18\\x18\\x18\\x18\\x18


        echo \# Cancelled transfer


        echo


else


        echo $FILE


        /usr/local/bin/sz "$FILE"


        echo \# Received $FILE


        echo


fi



wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-recv-zmodem.sh

vim iterm2-recv-zmodem.sh


#!/bin/bash


# Author: Matt Mastracci (matthew@mastracci.com)


# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script


# licensed under cc-wiki with attribution required


# Remainder of script public domain




FILE=`osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`


if [[ $FILE = "" ]]; then


        echo Cancelled.


        # Send ZModem cancel


        echo -e \\x18\\x18\\x18\\x18\\x18


        echo \# Cancelled transfer


        echo


else


        echo $FILE


        cd "$FILE"


        /usr/local/bin/rz


        echo \# Received $FILE


        echo


fi



第四步:编写相应的iTerm2 trigger

iTerm2-Profiles-Open Profiles-Edit Profiles-Advanced-Edit Trigger

如下图所示:

   现在就可以使用iTerm2终端便捷地从远程服务器上上传下载文件了

来源:碳基体

获得IP的地理位置信IP Geolocation及IP位置可视化

一、IP Geolocation API

淘宝提供的IP查询API,用来查询境外IP时,效果不太好(ip-api.com)

curl ip.taobao.com/service/getIpInfo.php?ip=8.35.201.48
{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.35.201.48"}}

(xxxx,\u7f8e\u56fd是有多不友好)

国内的还有ip138TOOL站长工具纯真,但都不提供API

而ip-api.com的IP Geolocation API 则提供更为准确友好的信息

curl ip-api.com/json/8.35.201.48
{"status":"success","country":"United States","countryCode":"US","region":"","regionName":"","city":"","zip":"","lat":"38","lon":"-97","timezone":"","isp":"Level 3 Communications","org":"Google Translate","as":"AS15169 Google Inc.","query":"8.35.201.48"}


而除了以JSON格式提供,还同时支持CSV格式,NEW LINE格式

curl ip-api.com/csv/8.35.201.48     
success,"United States",US,,,,,38,-97,,"Level 3 Communications","Google Translate","AS15169 Google Inc.",8.35.201.48

curl ip-api.com/line/8.35.201.48   
success  (1.是否成功)
United States (2.国家名称)
US (3.国家编号)
    (4. 区域名称)
(5.区域编号)
(6.城市)
(7.城市编号)
38(8.纬度)
-97(9.经度)
(10.时区)
Level 3 Communications(11. ISP运营商名字)
Google Translate(12. 公司名字)
AS15169 Google Inc.(13. AS编号与名字)

8.35.201.48 (查询的IP)

当我们需要批量查询IP的归属地时(其实只要查询到ISP,基本就知道IP的的信息了),可以很方便的写个脚本调用该接口,以下有个例子ipISP.pl

#!/usr/bin/perl -w
$file = shift;
$fileout = $file.'_out_isp';

open IN, "<$file" or die "cannot open $file for reading :  $! ";
open OUT,">$fileout" or die "cannot open $fileout for writing : $!";

while(<IN>){
   chomp;
   if ($_ =~ /(\S+)/){
   $ip = $1;
      }
   $result = `wget -qO- ip-api.com/line/$ip | awk 'NR==11 {print "ISP: "\$0} '`;
   chomp($result);
   print OUT $ip."\t".$result."\n";
   sleep(1);#一定要等待,否则会被封ip
}

close IN;
close OUT;

perl ipISP.pl ip

ip文件如下

61.55.186.22    
61.55.186.21    
61.55.186.20    
61.55.186.18    


运行结果如下ip_out_isp

61.55.186.22    ISP: China Unicom Hebei
61.55.186.21    ISP: China Unicom Hebei
61.55.186.20    ISP: China Unicom Hebei
61.55.186.18    ISP: China Unicom Hebei



ip-api.com 的API对调用的频率限制实在是太小了,官方说调用频率需小于2qps(怀疑有点过小,但我就被封过IP,但官方给出的解释就是如此)


 


二、IP位置可视化(用地图来显示当前IP的位置)——iplookup

github上paulshi大牛就分享了个IP地址可视化的工具iplookup(感谢喜欢做有趣的东西并爱分享的程序猿门)


1. 效果展示

(1)查询当前IP的地理位置

   (2)查询指定IP的地理位置

   (3)查询指定域名的ip地理信息

 

2.iplookup安装

该工具的安装也很简单

第一步:到 https://www.mapbox.com/ 注册帐号,创建一个map,点击Share->Developer,获得mapid

第二步:下载并安装iplookup

git clone https://github.com/paulshi/iplookup.git

cd iplookup/

vim config.py

将第一步中获得的mapid填写进去


创建virtual env

pip install virtualenv

virtualenv ev

source ev/bin/activate


安装依赖包

pip install -r requirements.txt

依赖包有

Flask==0.10.1
Jinja2==2.7.1
MarkupSafe==0.18
Werkzeug==0.9.4
gunicorn==18.0
itsdangerous==0.23
requests==2.0.1
wsgiref==0.1.2


运行就可以了

python main.py

当然有人会说,这样定位地地址不准确,我明明在张江,为啥说我在闵行,拜托,又不是GPS。

来源:碳基体

VirtualBox 安装Extension增强工具的方法

1. 实现本机与虚拟机之间的鼠标拷贝粘贴,屏幕的无缝连接


启动虚拟机 ,在终端 执行以下命令 

apt-get update && apt-get install  -y linux-headers-$(uname -r)

选择VirtualBox菜单的"Install Guest Additions",这时候虚拟机中会出现VBOXADDITIONS-版本号的CD ROM,打开终端将CD-ROM里的VboxLinuxAdditions.run拷贝到本地目录,并执行

cp /media/cdrom/VBoxLinuxAdditions.run /root/

chmod 755 /root/VBoxLinuxAdditions.run

cd /root

./VBoxLinuxAdditions.run


重启虚拟机即可实现,本机与虚拟机之间的鼠标拷贝粘贴,屏幕的无缝连接



2.实现本机与虚拟机之间的文件共享


打开虚拟机管理器,设置-共享文件夹 ,添加共享文件夹,勾选自动挂载


启动虚拟机后,即可在/media/sf_Downloads文件夹实现本机与虚拟机之间的文件共享

来源:碳基体

iOS重置root密码(通过修改/etc/master.passwd)

当忘记iOS系统的root密码后,可以采用修改/etc/master.passwd文件来修改root密码


可以使用iFiles的文本编辑器编辑 /etc/master.passwd文件,修改第二行 root:后,第一个:0前之间的部分 ,这部分的字符串是采用string crypt ( string $str [, string $salt ] )加密函数生成的


$str,就是root明文密码


$salt,就是2个字符的盐


可以使用在线函数运行工具http://www.functions-online.com/crypt.html来生成这段加密字符

 

以上图为例,$str部分的test为root的明文密码, $salt部分的ue为任意的2个长度的字符。ueu4r5eSydxzM这个长度为13个字符的字符串就是通过crypt加密后的密文


将该串字符填写在/etc/master.passwd文件的第二行,root: 与 第一个:0 之间


e.g.   root:ueu4r5eSydxzM:0:0:0:0:System Administrator:/var/root/:/bin/sh


即可将root密码修改为test



参考:

http://realityloop.com/blog/2009/12/31/recover-forgotten-iphone-root-password

来源:碳基体

mac os x开机自动运行程序的方法(以自动运行goagent proxy.py为例)



第一步:打开终端运行如下命令

sudo vim /Library/LaunchDaemons/com.go.agent.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.go.agent</string>
        <key>ProgramArguments</key>
        <array>
        <string>python</string>
        <string>/Users/leedani/Downloads/goagent/local/proxy.py(修改为存放goagent proxy.py的路径)</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>

launchctl load /Library/LaunchDaemons/com.go.agent.plist 


第二步:重启系统

来源:碳基体