Linux下软件发布技巧

Linux现在能够被越来越多的人认识及使用,在很大程度上可以归结为其具有强大的C编译器——gcc、便于交流的环境——Internet,以及雄厚的师资——有数不清的程序员在开发数不清的代码。
  
  有了Linux和Internet,我们可以很容易地在世界范围内发布软件作品,与他人交流开发心得与技巧。当我们完成了自己的软件作品,怎么样才能让其他人以快捷、方便的方式与自己分享成果、理解开发思想呢?这就是我们要讨论的Linux下软件打包和发布的方法。
  
  在Linux尚未流行之前,Linux下软件打包和发布应用仅仅停留在程序员中,因此软件分发基本都使用源代码方式,便于大家相互学习和交流。随着大量普通用户和商业应用的参与,源代码方式就显得过于繁琐,对用户要求太高,而且耗费时间,所以编译好的二进制文件发布方式开始流行起来。这就是Linux下两种主要的软件发布方式:源代码方式和二进制方式。源代码方式通常是将源文件以tar、tgz格式打包,解包后进行配置、编译和安装;二进制方式以Red Hat公司的RPM(Red Hat Package Manager)格式最广泛,它可以完成所有的步骤,自动将软件安装到系统中。
  
  tgz源代码方式
  
  使用这种源代码方式发布的软件,一般需要进行下列步骤:
  
  1.解开压缩文件,如tar、gz、bz2或tgz。
  
  2.执行./configure [–options] 进行软件的配置。
  
  3.执行make、make install等命令编译代码,并安装到系统中。
  
  因此,如果要发布软件,就需要生成可供配置的configure文件和进行编译安装的Makefile。
  
  下面以一个简单的例子来说明。假设要发布一个标准的hello程序,它打出“Hello, world!”的文字,该源程序命名为hello.c。在这个目录下(注意只有源文件hello.c,不需要编译hello.o或者hello),首先执行命令autoscan:
  
  $autoscan
  
  这样会生成configure.scan文件,它包含了系统配置的基本选项。作为一个简单的例子,其中很多东西是不需要的,所以可以修改这个文件,让它仅仅包含下面几行:
  
  AC_INIT(hello.c)
  AM_INIT_AUTOMAKE(hello, 0.1)
  AC_PROG_CC
  AC_OUTPUT(Makefile)
  
  然后把这个文件复制为configure.in,作为配置的输入文件。
  
  由于使用了m4宏(AM_INIT… 语句),必须运行aclocal命令生成相应的宏文件:
  
  $aclocal
  
  在当前目录中会产生aclocal.m4文件。
  
  然后执行autoconf,以生成configure执行脚本:
  
  $autoconf
  
  这样关于配置的部分就完成了,下面是和编译生成有关的。
  
  我们需要手工编辑一个文本文件——Makefile.am,内容如下:
  
  AUTOMAKE_OPTIONS=foreign
  bin_PROGRAMS=hello
  hello_SOURCES=hello.c
  
  这个文件应该很好理解,foreign告诉系统这是一个普通的应用软件,该程序名称为hello,而hello程序包含的源程序(SOURCES)只有hello.c这个文件。接着执行:
  
  $automake –add-missing
  
  automake会自动生成所有必须的文件,包括Makefile.in等重要文件。
  
  最后进行压缩、打包,整个工作就完成了。
  
  获得这个压缩包的用户只需要进行前面提到的三个安装步骤,就可以顺利地得到hello应用程序了。
  
  RPM二进制方式
  
  正如前面介绍的,使用源代码方式发布软件无论是对作者还是用户都比较麻烦。于是,Red Hat公司开发出一种直接安装编译好的二进制文件方式,并可根据不同的平台发布不同的版本。用户只需要一个命令,就可以完成所有要安装的步骤,十分适合普通用户使用。那么,如何把自己的软件制作成RPM包呢?
  
  下面以Red Hat Linux为例,在默认情况下,和RPM包相关的目录是/usr/src/redhat/下的SOURCES、SPECS和RPMS。其中SOURCES目录存放需要制作的源代码文件,一般是tgz格式压缩;SPECS目录存放编写的spec文件,这些文件指示RPM制作工具如何进行打包工作;而RPMS下有i386、i586、noarch等子目录,分别对应不同的体系结构,如Intel 80386、586处理器等,noarch则是通用的,制作完成的RPM包就存放在这些目录中。
  
  仍然以前面的hello为例,直接将hello.c压缩成hello.tgz格式:
  
  $tar cfvz hello.tgz hello.c
  
  然后把hello.tgz拷贝到/usr/src/redhat/SOURCES下,并在/usr/src/redhat/SPECS/下编写一个简单的hello.spec文件,内容如下:
  
  Name: hello program
  Summary: My first linux software
  Version: 0.1
  Release: 1
  Copyright: OpenSource
  Group: Extensions/Chinese
  Source: hello.tgz
  Packager: NetSnake
  %description
  This is a example software, just for see README for detail,
  NetSnake, some day.
  %changelog
  *Fri Dec 27 2002 NetSnake
  -build for the first time.
  %prep
  %setup
  %build
  make hello
  %install
  install -m 755 hello /usr/local/bin/hello
  %files
  %doc README
  /usr/local/bin/hello
  
  这个spec文件是整个制作过程的关键,它控制着整个软件包的制作流程,因此我们需要仔细分析一下。
  
  前面的Name、Summary等都是关于软件性质、版本等的说明,可以看作是一个概述和总揽,其中Version和Release将会影响到生成软件包的名称。例如这里版本是0.1,发布是1,那么做出来的RPM包就是hello-0.1-1.i386.rpm。而Group指的是在X-Window下生成快捷方式的位置,Chinese就是在“中文”下生成子目录。然后就进入了具体的制作流程,所有以“%”开头的宏语句都表示制作流程中的一步。
  
  由此不难看出,制作过程大概需要这样几步:
  
  ◆ %description是对整个软件的注释,比如写一些粗略的功能说明,可以分成若干行;
  
  ◆ %prep和%setup可以认为是预处理阶段,对于小软件来说没什么实质性用途;
  
  ◆ 接下来就是%build阶段,这时候会将所有打包文件解开,并根据实际情况将源文件编译为二进制文件(make hello);
  
  ◆ Build完成之后是%install,这个步骤通过%config、%file、%doc等宏将编译好的软件、文档、配置文件等安装到指定的位置;
  
  ◆ 最后是所有被安装到系统中的文件列表。
  
  这就是整个RPM包安装过程。它与Makefile比较起来要简单得很多,因为它将所有操作集中到一个文件中,非常有利于整理和纠错。
  
  接下来就需要执行,以生成自己的RPM软件包:
  
  $rpm -ba hello.spec
  
  需要注意的是,在新版本的Red Hat 8.0 下,制作RPM包的命令已经完全从rpm命令中分离出来,成为了一个单独的rpmbuild,所以应该是rpmbuild -ba hello.spec。
  
  如果不用-target=[i486][i586]…指定体系结构,默认会是i386,这样,会在/usr/src/redhat/RPMS/i386/下生成hello-xx-xxx.i386.rpm文件。
  
  总的来说,源代码方式的缺点是用户安装比较麻烦,而且容易出现各种错误;优点是可控制性强、灵活。RPM方式刚好相反,用户安装简单,易于使用,但是基本不能按照自己的意思对软件进行配置。这两种发布方法各有千秋,具体选择哪种发布方式可以根据自己的需要确定。

tcpreplay 工具详解【中文】

工具的名称就能猜到工具的作用,就是重放TCP的报文,但是这个工具究竟功能如何,是不是仅仅局限于在一个网卡上回放报文,这篇说明书主要介绍tcprelay的一些与测试有关的使用,在介绍tcpreplay命令的使用之前,先要介绍与之密切相关的一个命令:tcpprep,中文直译就是tcp准备的意思,它的作用可以参见官方网站的介绍说明:

tcpprep is the pcap pre-processor for tcpreplay and tcprewrite. The purpose of tcpprep is to create a cache file which is used to "split" traffic into two sides (often called primary/secondary or client/server). If you are intending to use tcpreplay with two NIC’s, then tcpprep is what decides which interface each packet will use. By using a seperate process to generate cache files, tcpreplay can send packets at a much higher rate then if it had to do the calculations to split traffic itself.

个人翻译:(建议大家看man文件,阅读3次就能够比较好的理解了)

 

P:<list> – Must be one of the listed packets where the list corresponds to the packet number in the capture file.

Ex: -xP:1-5,9,15 would only send packets 1 through 5, 9 and 15.

根据参数后的参数值(报文编号)发送指定的报文。可以在ethereal中确认报文的编号,然后把需要的报文发送。可以用于排除ARP报文。

F:"<filter>" – BPF filter. See the tcpdump(8) man page for syntax.

未知,以后补充。

-X <match> Send all the packets except those specified

可选参数,就是-x参数的取反,参数内容也是一样。

-v Verbose

可选参数,显示trpprep生成cache文件的处理过程,就是一些信息的即时打印。

-V Version

显示版本号。
Tcpprep使用小结

再构造cache文件的过程中我用的比较多的选项参数就-v、-P、-xB、-xP,一般都是client和server的模式,其它两种模式没有实验过,暂时还不知道怎么使用,bridge模式我使用过一次,结果发现报文是从一个网卡送出。

对于tcp和udp协议都做了测试,是可以支持的,icmp还没有成功。对于网络上的BT报文,只要你有pcap文件,也是可以构造cache文件来模拟完全真实的BT流量。

目前的使用就是这么多,感觉还是很有用的,tcpreplay的参数有一部分是和tcpprep重复,下面的帮助文件说明就不详细说明了,但是特殊有好用的参数会使用蓝色字体标记出来给予重视。存在的不足是还没有学会在nat模式下重放报文,现在所有的报文重放都是在透明模式下完成的。
Tcpreplay帮助文件说明

Usage: tcpreplay [args] <file(s)>

-A "<args>" Pass arguments to tcpdump decoder (use w/ -v)

可选参数,在使用tcpdump风格打印输出信息时,同时再调用tcpdump中的参数,默认已经带有“-n,-l”,所以一般看到的都是ip地址,而没有主机名的打印,注意这个是在tcpreplay使用了-v参数时,才能使用,不带-v不会报错,但是没有实际意义。格式:-vA “nnt”表示以tcpdump风格输出报文信息,并且不打印时间戳、主机名、端口服务名称。注意不要使用-c参数来指定打印的数据报文的个数,这样发送出去的报文也会变少。

-b Bridge two broadcast domains in sniffer mode

可选参数,没有用过

-c <cachefile> Split traffic via cache file

双网卡回放报文必选参数,后面紧跟cache文件名,该文件为tcpprep根据对应的pcap文件构造出来。

-C <CIDR1,CIDR2,…> Split traffic by matching src IP

可选参数,

-D Data dump mode (set this BEFORE -w and -W)

可选参数,把应用层的数据,使用dump mode写入到指定文件中去,和-w、-W参数一起使用。

-e <ip1:ip2> Specify IP endpoint rewriting

可选参数,指定端点的ip,即把发送报文的和接收的报文的ip都修改称对应的参数值中指定的ip,但是这样发送的出的报文不会区分client和server,还没有发现使用的地方。

-f <configfile> Specify configuration file

可选参数,指定配置文件,目前不会使用。

-F Fix IP, TCP, UDP and ICMP checksums

可选参数,在发送报文时,自动纠正错误的校验和。对测试DUT的校验和检验还是有用的。

-h Help

显示帮助文件。

-i <nic> Primary interface to send traffic out of

双网卡回放报文必选参数,指定主接口。

-I <mac> Rewrite dest MAC on primary interface

可选参数,重写主网卡发送出报文的目的MAC地址。

-j <nic> Secondary interface to send traffic out of

双网卡回放报文必选参数,指定从接口。

-J <mac> Rewrite dest MAC on secondary interface

可选参数,重写从网卡发送出报文的目的MAC地址。

-k <mac> Rewrite source MAC on primary interface

可选参数,重写主网卡发送报文的源MAC地址。

-K <mac> Rewrite source MAC on secondary interface

可选参数,重写从网卡发送报文的源MAC地址。

-l <loop> Specify number of times to loop

可选参数,指定循环的次数,测试过程发现不是那么好用,有待确认。

-L <limit> Specify the maximum number of packets to send

可选参数,指定最大的发包数量。可以在确认连接的调试时使用。

-m <multiple> Set replay speed to given multiple

可选参数,指定一个倍数值,就是必默认发送速率要快多少倍的速率发送报文。加大发送的速率后,对于DUT可能意味着有更多的并发连接和连接数,特别是对于BT报文的重放,因为连接的超时是固定的,如果速率增大的话,留在session表中的连接数量增大,还可以通过修改连接的超时时间来达到该目的。

-M Disable sending martian IP packets

可选参数,表示不发送“火星”的ip报文,man文件中的定义是0/8、172/8、255/8。

-n Not nosy mode (not promisc in sniff/bridge mode)

可选参数,在使用-S参数,不对混杂模式进行侦听。没有测试过。

-N <CIDR1:CIDR2,…> Rewrite IP’s via pseudo-NAT

可选参数,通过伪造的NAT,重写IP地址。这个参数应该有很重要的应用,目前没有测试使用。

-O One output mode

可选参数,没有测试使用

-p <packetrate> Set replay speed to given rate (packets/sec)

可选参数,指定每秒发送报文的个数,指定该参数,其它速率相关的参数被忽略,最后的打印信息不会有速率和每秒发送报文的统计。

-P Print PID

可选参数,表示在输出信息中打印PID的信息,用于单用户或单帐户模式下暂停和重启程序。

-r <rate> Set replay speed to given rate (Mbps)

可选参数,指定发送的速率。目前-m/-r/-p这3个参数的相互关系还需要确认。

-R Set replay speed to as fast as possible

可选参数,让报文线速发送。

-s <seed> Randomize src/dst IP addresses w/ given seed

可选参数,

-S <snaplen> Sniff interface(s) and set the snaplen length

可选参数,

-t <mtu> Override MTU (defaults to 1500)

可选参数,指定MTU,标准的10/100M网卡的默认值是1500。

-T Truncate packets > MTU so they can be sent

可选参数,截去报文中MTU大于标准值的部分再发送出去,默认是不发送,skip掉。目前还有疑问,为什么会产生MTU大于1500字节的包,在BT报文中,这种包比较常见。

-u pad|trunc Pad/Truncate packets which are larger than the snaplen

可选参数,后面的参数值二选一,snaplen是指保留数据包的长度,这里的trunc参数值和MTU没有任何关系,不要混淆。

-v Verbose: print packet decodes for each packet sent

可选参数,没发送一个报文都以tcpdump的风格打印出对应的信息。

-V Version

查看版本号。

-w <file> Write (primary) packets or data to file

可选参数,将主网卡发送的报文写入一个文件中,参数后紧跟文件名。

-W <file> Write secondary packets or data to file

可选参数,将从网卡发送的报文写入一个文件中,参数后紧跟文件名。

-x <match> Only send the packets specified

可选参数,发送匹配参数值的报文,这里各个参数具体的含义和tcpprep中的一样,

S:<CIDR1>,… – Src IP must match specified CIDR(s)

在CIDR模式下必须匹配源IP,格式:-xS:100.1.1.0/24,10.10.10.0/26。多个用逗号隔开,参数个数没有试过,3个没有问题。

D:<CIDR1>,… – Dst IP must match specified CIDR(s)

在CIDR模式下必须匹配目的IP,格式同上。

B:<CIDR1>,… – Both src and dst addresses must match

必须同时匹配源和目的IP,格式同上。

E:<CIDR1>,… – Either src or dst address must match

匹配源或目的IP,格式同上。

P:<list> – Must be one of the listed packets where the list corresponds to the packet number in the capture file.

Ex: -xP:1-5,9,15 would only send packets 1 through 5, 9 and 15.

根据参数后的参数值(报文编号)发送指定的报文。可以在ethereal中确认报文的编号,然后把需要的报文发送。可以用于排除ARP报文。

F:"<filter>" – BPF filter. See the tcpdump(8) man page for syntax.

未知,以后补充。

-X <match> Send all the packets except those specified

可选参数,-x的参数内容取反。参数内容一样。

-1 Send one packet per key press

可选参数,参数内容就是阿拉伯数字1,这个参数对于确定连接的建立,相当好用,根据按回车键发送报文,可以将报文一个一个发送,来判断连接的状态。也可以用于故障定位。

-2 <datafile> Layer 2 data

可选参数,在2层加入数据。

-4 <PORT1:PORT2,…> Rewrite port numbers

可选参数,重写端口号,对于测试特殊端口的应用比较实用。

<file1> <file2> … File list to replay

可选参数,没有实验过。
配置实例

1、 重放在客户端ftp连接的报文

a、 在客户端使用ethereal抓包,存为ftp.pcap文件

b、 将ftp.pcap文件进行tcpprep操作,制作cache文件。

[root@A ~]# tcpprep -an client -i ftp.pcap -o ftp.cache –v

c、 将DUT设备的两个接口和PC的两个接口使用网线连接,使用tcpreplay重放报文。注意防火墙的配置为网桥(透明)模式。

[root@A ~]# tcpreplay -c ftp.cache -i eth0 -j eth1 ftp.pcap -R –v

-R参数表示全速发送,-v显示打印信息。

2、 重放在客户端BT连接的报文

a、 在实验室BT下载一些台湾的娱乐节目和热门的大片,使用ethereal抓包,存为bt.pcap文件。注意pcap文件大小的控制,对pc的内存要求比较高,我保存了一个600多M的pcap文件用了40多分钟,大家有需要可以直接从实验室copy。

b、 将bt.pcap文件进行tcpprep操作,制作cache文件。

[root@A ~]# tcpprep -an client -i bt.pcap -o bt.cache -C "100M BT Packet" –v

制作cache文件,在cache文件中写入“100M BT Packet”的注释。

c、 使用tcpreplay重放报文。

[root@A ~]# tcpreplay -c bt.cache -i eth0 -j eth1 bt.pcap -v –R

3、 重放tftp服务器上抓到的报文

a、 在tftp服务器上使用ethereal抓包,存为tftp.pcap文件。

b、 将pcap文件进行tcpprep的操作,制作cache文件。

[root@A ~]# tcpprep -an server -i tftp.pcap -o tftp.cache –v

注意:我在测试的时候犯了一个错误,使用DUT的tftp升级来做实验,同时穿过DUT重放报文,结果在网卡发送报文的后,DUT的mac地址做了的回应,导致交互过程没有穿过DUT,这个问题比较搞笑,上午弄了半天才发现原因,开始还以为udp的连接不能重放。

c、 使用tcpreplay重放报文。

[root@A ~]# tcpreplay -c tftp.cache -i eth0 -j eth1 tftp.pcap –v
Tcpprep和Tcprepaly的原理

对于原理部分,目前还没有看过代码,王海斌同学打算先看过源码后,再在windows上调试一个tcpreplay的程序供测试使用。具体的实现原理日后补充。

 

tcpprep是一个在tcpreplaytcprewrite3.0.beta11版本才有,这里不讨论)之前使用的pcap文件的处理程序。使用tcpprep的目的就是建立一个cache文件,用于分离通信流量中的两方(通常叫做 主要的/次要的 或者 客户端/服务器)。如果你正打算在两块网卡上使用tcpreplay的话,那么tcpprep就是用来决定每一个报文(packet)从哪一个接口发出。通过使用这样一个分离的程序来建立一个cache文件,tcpreplay就可以根据这个cache文件通过自身的计算来分离流量,高速率的发送报文。

目前王海斌看过代码后,对cache文件的作用解释,主要是加速报文的发送,cache文件中存放着pcap文件中每个帧的编号和时间戳等信息,以达到tcpreplay回放时可以更加快速的发送报文的目的。

其实我们要使用tcpreplay的功能的话,肯定就是它的重放功能,而重放的话肯定是一个客户端和服务器的交互过程,例如ftptftpsqlnetrtspmms等应用层协议的交互过程,我们只要有正确和足够的pcap文件,只需要制作cache文件,使用tcpreplay的命令,就不需要每次都搭建一个真实的测试环境来测试DUT对该协议的支持程度。所以在介绍tcpreplay之前先介绍tcpprep这个命令的使用。tcprewrite提供的功能暂时不做研究。

Tcpprep帮助文件说明

    由于时间问题,这次不能对man文件一一做解释,这个说明文档主要是对-h打印出来的命令参数作一个说明,结合几个实际的例子来说明tcpprep的使用。强烈建议大家去官方网站去阅读他们提供的文档,http://tcpreplay.synfin.net/trac/我这里有打印的内容,有兴趣的可以拿去看一下。

    Usage: tcpprep [-a -n <mode> -N <type> | -c <cidr> | -p | -r <regex>]

                -o <out> -i <in> <args>

 

                 -a <st1:city w:st="on"><st1:place w:st="on">Split</st1:place></st1:city> traffic in Auto Mode<o:p></o:p>

一般情况下都需要该参数,表示按模式自动分离的通讯流量生成cache文件,这个参数一半都和-n参数一起使用,表示自动分离采取的拓扑模式,来决定采取那种模式分离通讯流量的双方。

-c CIDR1,CIDR2,…      Split traffic in CIDR Mode

可选参数,表示分离流量时采用CIDR(无类别域间路由选择)模式。格式:tcpprep  -ac <st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">10.10.0</st1:chsdate>.0/24,表示把源地址匹配10.10.0.0/24网段的报文全部由主网卡发送,剩下的报文由从网卡发送出来,这里还有一点需要补充,就是tcpreplay在重放报文时对两个网卡的定义很明确,一个主网卡(primary interface),一个是从网卡(secondary interface),不同的模式,两块网卡的属性不一样。该参数不能和-r,-a一起使用。<o:p></o:p>

-C <comment>            Embed comment in tcpprep cache file

可选参数,表示在cache文件中嵌入注释内容,可以用于注释说明cache文件的内容,注意使用时参数位置,不要放在最后,我测试时放在-o参数值的后面就报错,放到-i参数之前就可以。生成cache文件后使用-P可以查看写入的内容。

-h                      Help

显示帮助文件。

-i <capfile>            Input capture file to process

生成cache文件的必带参数,后面紧跟pcap文件名,表示这个pcap文件需要处理。

-m <minmask>            Minimum mask length in Auto/Router mode

可选参数,在选用router模式时使用,表示最小掩码,默认是302个有效ip地址)。

-M <maxmask>            Maximum mask length in Auto/Router mode

可选参数,在选用router模式时使用,表示最大掩码,默认是81600万个ip地址)。

-n <auto mode>          Use specified algorithm in Auto Mode

生成cache文件的必带参数,后面紧跟模式名称,可选项有(bridge|router|client|server),目前<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.3.5</st1:chsdate>版本只支持这4种模式。模式的选择很关键,例如在客户端使用ftp软件下载文件,那么你在客户端抓到的报文生成的pcap文件,那么就选用client模式,在服务器端抓到的报文生成的pcap文件就选用server模式。只有模式选对了,才能正确的分离流量从正确的接口发出正确的报文。注意:Server端的报文由主网卡发送出去,Client端的报文由从网卡发送出去。怎么确定主从网卡由tcpreplay的命令(-i –j两个参数)来决定。

-N client|server        Classify non-IP traffic as client/server

可选参数,表示非IP的流量(例如ARP报文)从哪个接口送出,因为很多的tcpprcp支持的模式中,都依赖于IP头部中的IP地址信息来决定报文是从client端还是从server端发送出去。但是并不是所有的报文都是IPv4结构的,所以这种情况下,tcpprep不能确定这些非IPv4类型的报文应该从哪个接口发送出去,所以,默认的配置就是从client的接口发送出去。如果你硬要正确的分离出非IPv4报文的话,可以使用MAC address模式(–mac)。3.0版本才支持。

-o <outputfile>         Output cache file name

生成cache文件的必带参数,后面紧跟cache文件名,表示这个输出的cache文件以这个名字命名。

-p                     <st1:place w:st="on"><st1:city w:st="on">Split</st1:city></st1:place> traffic based on destination port

    可选参数,基于目的端口来分离通讯流量,它区分的依据是认为0-1023端口都是服务器的端发出的报文,其它的端口都是客户端发出的报文,具体的端口对应的/etc/services文件里的的内容。使用的格式:-p /etc/services,可以根据自己的需要来制作一个文件也可以。

-P <file>               Print comment in tcpprep file

    可选参数,查看cache文件的内容。

-r <regex>             <st1:place w:st="on"><st1:city w:st="on">Split</st1:city></st1:place> traffic in Regex Mode

    可选参数,表示使用Regex模式分离通讯流量,有点类似于CIDR模式,但是它匹配的是服务器的源IPman文件提示不能和-a-c参数一起使用,但是我使用了也没有报错,格式:-r "(192)"-r "(192|172)\…..*",具体应用还有待实验。

-R <ratio>              Specify a ratio to use in Auto Mode

    可选参数,一个比例值,这个比例值的意义是服务器端发起的连接数和客户端发起的连接数的比例,这个值大于2的话就视为server端。这个英文原意我也不是太肯定,大家可以参考一下原文:

The ratio of server connections to client connections  necessary to  be classified as a server in auto mode.  A system is classified as a server if [# server connections] >= ([# client connections] * [ratio]).  Default is: 2.0

-s <file>               Specify service ports in /etc/services format

    可选参数,在man文件中没有对该参数的解释,估计就是按/etc/services文件里的格式来定义服务的端口,没有太多的研究意义。

-x <match>              Only send the packets specified

    重要的可选参数,表示按照参数定义的需求来定义发送报文。后面还有具体的参数,因为在我们的抓包过程中,可能会由于网络环境原因,抓到了许多我们不需要回放的报文,我们就可以根据这个参数决定我们需要回放哪些报文内容。具体的参数意思如下:

    S:<CIDR1>,… – Src IP must match specified CIDR(s)

    CIDR模式下必须匹配源IP,格式-xS:100.1.1.0/24,<st1:chsdate w:st="on" year="1899" month="12" day="30" islunardate="False" isrocdate="False">10.10.10</st1:chsdate>.0/26多个用逗号隔开,参数个数没有试过,3个没有问题。

D:<CIDR1>,… – Dst IP must match specified CIDR(s)

CIDR模式下必须匹配目的IP,格式同上。

B:<CIDR1>,… – Both src and dst addresses must match

必须同时匹配源和目的IP,格式同上。

E:<CIDR1>,… – Either src or dst address must match

匹配源或目的IP,格式同上。

sendip 命令详解【中文】

在从事网络产品尤其是网络安全产品开发时,我们一直面临着一个问题,就是对产品的 UDP报文的构造
先看man文件中显示支持可以构造的UDP报文字段有哪些,然后在参数后直接说明该字段的含义。构造报文首先要求对报文的各个字段非常熟悉,所以先看一下UDP首部的图表:

UDP首部:
0 15 16 31
    

        

            

            

        

        

            

            

        

        

            

        

    

            

16位源端口号

            

            

16位目的端口号

            

            

16位UDP长度

            

            

16位UDP检验和

            

            

数据(若有)

            

sendip_表3
Arguments for module ./udp.so:
-us x UDP source port
构造UDP报文的源端口,默认为0。
-ud x UDP destination port
构造UDP报文的目的端口,默认为0。
-ul x UDP packet length
构造UDP报文的报文长度,这个值可以任意输入,测试在接收端抓包的结果显示是参数值,但是ethereal会自动分析出实际的报文长度。默认是正确的长度,8个字节。
-uc x UDP checksum
构造checksum的值,覆盖了首部和数据字段。可以用于测试DUT设备是不是检验UDP报文的checksum值。这里有点需要注意,在测试的过程中,发现如果length字段不正确,网卡在收到报文后不会检查checksum,如果length是正确的,checksum才会被认出来不正确,从ethereal的抓包来看是这样的。默认是正确的checksum。
实例:
[root@FC5 ~]# sendip -v -p ipv4 -is 192.168.96.7 -id 192.168.96.1 -p udp -us 8000 -ud 4000 192.168.96.1 –d asdfasdf
发送一个源地址为192.168.96.7,源端口为8000的udp包,到目的为192.168.96.1,目的端口为4000设备上,数据包的内容是asdfasdf,如果要直接引用一个文件的内容的话可以使用-f参数,后面写文件的路径即可。

<h2>ICMP报文的构造</h2>

先看man文件中显示支持可以构造的ICMP报文字段有哪些,然后在参数后直接说明该字段的含义。构造报文首先要求对报文的各个字段非常熟悉,所以先看一下UDP首部的图表:
ICMP结构:
0 15 16 31
    

        

            

            

            

        

        

            

        

    

            

8位类型

            

            

8位代码

            

            

16位检验和

            

            

其它一些细节信息内容

            

sendip_表4
Arguments for module ./icmp.so:
-ct x ICMP message type
构造ICMP报文类型,一个字节。内容比较多,最常见的类型如下:
0 表示Echo Reply
3 表示Eestination Unreachable
这个又分很多类型,这里不作分析,具体可以参见资料。
4 Source Quench
5 Redirect
8 Echo
10 Router Selection
11 Time Exceeded
13 Timestamp
-cd x ICMP code
构造代码字段,取值范围0-255,超过255后变为0,默认配置为0。
-cc x ICMP checksum
构造checksum字段,2个字节。默认是正确内容。
[root@FC5 ~]# sendip -v -p ipv4 -is 192.168.96.253 192.168.96.202 -p icmp -ct 3
发送一个源地址为192.168.96.253的类行为3的icmp报文给192.168.96.202这个地址。

小结:

这篇文档主要是介绍sendip的报文构造方式,而sendip的缺陷就在于它不能连续的发送报文,所以这里提供一个简单的perl脚本,来循环的发送数据包,虽说不能形成flood的效果,但是对于测试可以达到数量控制的目的,有助于自动化脚本的测试,提高测试的效率。
#!/usr/bin/perl -w
$i=1;
while ($i<2)
{
for($j=0;$j<=65;++$j)
{
system "sendip -v -d r64 -p ipv4 -iv 4 -ih 5 -il 20 -ifm 1 -if 0 -iy 8 -is 13.1.1.2 -id 192.168.98.173 -p udp -us $j -ud $j -ul 56 192.168.98.173";
system "sendip -v -d r64 -p ipv4 -iv 4 -ih 5 -il 20 -ifm 0 -if 0x3 -iy 8 -is 13.1.1.2 -id 192.168.98.173 -p udp -us $j -ud $j -ul 56 192.168.98.173";
system "sendip -v -d r64 -p ipv4 -iv 4 -ih 5 -il 65535 -ifm 1 -if 10 -iy 4 -is 13.1.1.2 -id 192.168.98.173 -p tcp -ts $j -td $j -tt 8 192.168.98.173";
}
++$i
}
//i代表循环的次数,j代表端口,本来是65535,我修改了一下,可以根据需要来调整次数和//端口范围,这个脚本感谢吴梦洁的提供,我只是做了注释和修改。

TCP/IP 协议栈进行稳定性或安全性测试,确保开发产品在遇到各种不规则的错误的IP 包时仍可正常稳定高效地工作,我们知道,在正常的网络环境中,很难产生错误的IP 包,也很难产生我们想要的错误的IP 包,为此,要完成对产品的测试,我们必须自己来制造各种各样错误的IP 包,本篇的目的就是介绍如何利用各种发包工具来制造自己想要的错误的IP 包。SENDIP 是一个LINUX 下的命令行工具,可以通过命令行参数的方式发送各种格式的IP 包,它有大量的命令行参数来规定各种协议的头格式,目前可支持NTP, BGP, RIP, RIPng,TCP, UDP, ICMP 或raw IPv4 和IPv6 包格式,并且可以随意在包中添加数据。

<h2>帮助文件说明</h2>

Usage: sendip [-v] [-d data] [-h] [-f datafile] [-p module] [module options] hostname
-d data add this data as a string to the end of the packet
Data can be:
rN to generate N random(ish) data bytes;
0x or 0X followed by hex digits;
0 followed by octal digits;
any other stream of bytes
-f datafile read packet data from file
-h print this message
-p module load the specified module (see below)
-v be verbose
参数含义:
-v: 详细模式,即打印出你发送报文的内容,类似于debug模式,建议配置该参数,可以清楚的看到发送的报文内容是否正确。
-d: 添加data字段的内容,有option字段的话放在options字段之后,任意添加。也可以一次用文件导入,不过参数是下面的-f。
-h: 显示上面的帮助文件。
-f: 在data字段添加参数后所指的文件里的内容,参数后跟的内容就是一个文件名。
-p: 指定发送报文的类型,选项就是帮助提示中的ipv4 ipv6 icmp tcp udp bgp rip ntp的8种类型,注意各个协议之间的搭配使用,例如ntp是用udp传输,而rip是用tcp传输。这个参数可以复用来更加精确的确定一个报文的类型和各个字段,例如:-p ipv4 –p tcp –p rip是可以一起用的。该参数必须配置。
hostname: 直接输入ip地址即可,也可以是主机名,但是之前要把主机名和对应的ip写入到/etc/hosts的文件中。该参数必须配置。注意不需要输入hostname这个字段,要不是ip,要不是主机名。
配置完以上参数后就可以发送报文了,但是具体报文的各个字段都是default配置,并没有达到自己要构造报文的目的。下面以ipv4、udp、tcp、icmp为例根据man文件的内容来说明各个字段的构造方法,ipv6、rip、bgp和ntp希望后面有时间再补充。

ipv4报文的构造

先看man文件中显示支持可以构造的IPV4报文字段有哪些,然后在参数后直接说明该字段的含义。构造报文首先要求对报文的各个字段非常熟悉,所以先看一下IP首部的图表:
IP首部:
0 15 16 31
    

        

            

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

        

        

            

        

        

            

        

        

            

        

    

            

4位版 本

            

            

首部长 度

            

            

8位

            

服务类型(TOS)

            

            

16位

            

总长度(字节)

            

            

16位

            

标识

            

            

3位标志

            

            

13位

            

片偏移

            

            

8位

            

生存时间TTL

            

            

8位

            

协议

            

            

16位

            

首部检验和

            

            

32位

            

源IP地址

            

            

32位

            

目的IP地址

            

            

32位

            

选项(若有)

            

            

数据

            

            

sendip_表1
上面是一个简单的图示,具体各个字段可以参见高文宇的《IP协议》文档。
Arguments for module ./ipv4.so:
-is x Source IP address (see README)
构造源IP地址,任意构造。判断不是很严格,可以输入错误,它会自动补充或用255.255.255.255来代替,例如输入1.1.则用255.255.255.255来代替;如果输入1.1则会自动补齐中间的两位,显示为1.0.0.1;如果输入1.1.1则会自动填充为1.1.0.1。目的IP地址也是一样。源IP默认为127.0.0.1。
-id x Desitnation IP address
构造目的IP地址,这里其实可以不用写,因为hostname为一个必带的参数字段,最后的目的地址是匹配hostname参数后的内容。注意,这里的ip和hostname的内容要求一样,不然sendip发出了报文(它发出的报文目的地址是-id参数后的地址),但是id和hostname所带参数内容所指的主机的网卡并收不到报文。默认以-id后的参数为准。
-ih x IP header length (see README)
构造header(首部)长度,这里所指的是32-bit的word的个数,就是以4个字节为单位元,你定义的结果要乘以4,要求最小为5(5×4=20bytes),最大为15(15×4=60bytes)。如果构造首部不是20bytes的报文,网卡收到的时候ethereal只解析到mac地址,它不认为是一个完整的IP报文。默认是20字节。
-iv x IP version (you almost definately don’t want to change this)
构造IP版本,这个可以任意,0到15任意选择,超过15发出的报文IP version为0。默认为4。
-iy x IP type of service
构造服务类型,这里先说明一下Type of service(PreDTRCx)的各个标志位的意义:
Precedence(000-111)
D(1 = minimize delay)
T(1 = maximize throughout)
R(1 = maximize reliability)
C(1 = minimize cost)
x(reservd and set to 0)
服务类型的前3位设置分组的优先级,数值越大,则分组越重要。接下来的3位分别表示延迟、吞吐率和可靠性,如果为0则表示常规服务,如果为1则表示短延迟、高吞吐率和高可靠性。最后两位没有使用。sendip并不能细致到定义每一个bit位的数值,默认是全0。
-il x Total IP packet length (see README)
构造IP报文的总长度,这里的总长度是包括数据字段的,就是说如果没有数据字段,这里的值应该和首部长度字段的值是一样的。最大值为65535(二进制16个1),但是注意配置这个值的意义不大,用ethereal抓到这个报文时显示的值还是一个正确的值,这个报文本来有多大就是多大。默认是根据报文内容来确定,是一个正确的值。
-ii x IP packet ID (see README)
构造IP报文的标识号,这个时随机的,没有太多意义,不知道是不是会在校验的时候用到。默认是随机构造。在IP协议中的作用是标识报文,例如一个分片后的IP报文,它的ID肯定是一样的。取值的范围是1-65535,不在这个范围的话,程序会随机构造一个id号。
-ifr x IP reservced flag (see README)
保留的标志位。默认为0,选项为0、1、r。
-ifd x IP don’t fragment flag (see README)
构造强制不分片标志位,默认为0,选项为0、1、r。
-ifm x IP more fragments flag (see README)
构造分片标志位,这个标志位只有在报文需要分片时才置为1,默认为0,选项为0、1、r。
-if x IP fragment offset
构造需要分片的报文的位偏移,默认发送的报文没有分片的话就是0。
-it x IP time to live
生存时间值,修改的意义不大,默认配置为255。
-ip x IP protocol
协议字段,判断哪个协议使用了IP封装来传输,例如ICMP为0x01,TCP为0x06,UDP为0x11。
-ic x IP checksum (see README)
构造首部校验和字段,只覆盖首部,不包括数据字段。默认是正确的校验和,看不出什么规律来,应该是有一种算法。测试时可以随意构造一个错误的checksum,看DUT是不是检测checksum这个字段。但是验证的过程中发现配置后没有作用,并没有修改。测试了icmp的包倒是修改了,不知道是不是软件的bug。
注意:以下内容都是选项字段,之前没有了解过的话,可能会觉得有些陌生,为了更好的了解这些字段的意思,可以先用ping这个简单的命令来进行一些实践操作,理解其中的一些字段的含义。
实例
1、返回一个时戳,表示到达目的地址的时间,在reply的回应包中可以看到。
C:\>ping -s 1 192.168.100.18
Pinging 192.168.100.18 with 32 bytes of data:
Reply from 192.168.100.18: bytes=32 time<1ms TTL=63
Timestamp: 192.168.100.18 : 9612956
2、记录路由,表示在ping包到达目的地址时经过的路由设备,需要设备的支持。
C:\>ping -r 1 192.168.100.18 -n 1
Pinging 192.168.100.18 with 32 bytes of data:
Reply from 192.168.100.18: bytes=32 time<1ms TTL=63
Route: 192.168.100.18
Ping statistics for 192.168.100.18:
-r表示记录路由的跳数,注意这个参数值只能是1-9,原因是因为记录路由这个选项需要3个字节的开销,后面每跟一个ip地址需要4个字节,而选项字段的最大值为40个字节。这个参数的作用被之后的tracert命令代替。
-n 表示发多少个ping包。
3、严格源路由和记录路由,表示不但要记录路由,还要求到达目的地址必须要经过指定的路由地址。
C:\>ping -k 192.168.96.2 192.168.98.1 192.168.100.18
表示到达192.168.100.18时,先必须经过192.168.96.2和192.168.98.1这两个路由设备,再到达目的ip。
现在逐一来看各个参数的含义:
-ionum x
根据《TCP/IP详解》卷2第9章,并没有这个选项字段,这里应该是软件自己为了控制选项字段的长度而设计的。这里先说明一些选项字段的基础知识:
选项字段必须是4字节的整数倍,原因很简单,因为IP header length是以4字节为一个单位元;
IP选项字段可能包含0个或多个单独选项,选项有两种类型,单字节和多字节,如下图:
sendip_图1(这里贴不上来,想办法中)
所有选项1都以字节类型(type)字段开始。在多字段选项中,类型字段后面紧接着一个长度(len)字段,其它的字节是数据(data)。许多选项数据字段的第一个字节是1字节的位移(offset)字段,指向数据字段内的某个字节。长度(len)字节的计算覆盖了类型、长度、和数据字段。类型(type)被继续分成了3个子字段:1bit备份(copied)、2bit类(class)字段和5bit数字(number)字段。
现在来看各个选贤字段的定义和使用方法。默认这个参数后的长度值总是正确的,默认没有选项字段。
-ioeol IP option: end of list
1字节,表示选项表的结尾,就是一个选项字段的结束标识符。
-ionop IP option: no-op
1字节,没有任何意义,表示无操作,碰到这个字段可以忽略。
-iorr x
长度可变,作用是记录路由。格式是pointer:addr1:addr2,这里的pointer其实就是一个具体的offset值,是一个十六进制的值,我测试最小值是十进制的10(这里只能用十进制表示,10刚好对应的是0x16)。使用可以参照这个命令行:
[root@FC5 ~]# sendip -v -p ipv4 -is 192.168.96.111 -id 192.168.96.202 -iorr 10:192.168.96.1 192.168.96.202 -d asf
这里要说明一点为什么要加一个asf的3个字节的数据字段,因为在测试的时候,我在被发送报文的pc端抓包发现如果ethereal分析显示total length这个值不对的话,它就不会分析其它字段,这样会导致不能清楚看到option字段,不知道是不是正确构造了报文,所以在构造报文时还需要注意这个小窍门,ethereal分析后还少几个字节就加几个字符。这样你就可以看到你刚才发送的option字段里的内容了。
-iots x
长度可变,作用是时戳。格式是pointer:overflow:flag:(ip1:)ts1:(ip2:)ts2,pointer表示位偏移,overflow表示??,flag是标识位(0表示记录时间戳、1表示记录地址和时间戳、3表示只在预先指定的系统记录时间戳,其它保留)。注意只有flag位置1时才有ip1、ip2的参数。
[root@FC5 ~]# sendip -v -p ipv4 -is 192.168.96.222 -iots 11:4:1:192.168.96.1:11:
192.168.9.8:90 192.168.96.202
11是位偏移,4表示??,1表示记录地址和时间戳,后面就是一个ip对应一个时间戳。
构造这样的报文主要可以用于测试DUT是不是检查option字段,如果检查,是不是检查时间戳等信息。
-iolsr x
长度可变,表示宽松源路由和记录路由(LSRR)。格式很简单了,上面ping的实例如果运行后抓包看过以后,就发现这个是按照标准的格式来定义的。
[root@FC5 ~]# sendip -v -p ipv4 -is 192.168.96.253 -iolsr 10:192.168.96.1 192.168.96.202 -d 1
-iosid x
4个字节,构造identifier(标识符),取值范围0-65535,超过该范围自动变为0。我测试的结果显示前2个字节总是0x8804,后面2个字节就是输入的参数值。
-iossr x
长度可变,表示严格源路由和记录路由(SSRR),格式同-iolsr。

<h2>TCP报文的构造</h2>

先看man文件中显示支持可以构造的TCP报文字段有哪些,然后在参数后直接说明该字段的含义。构造报文首先要求对报文的各个字段非常熟悉,所以先看一下TCP首部的图表:
TCP首部:
0 15 16 31
    

        

            

            

        

        

            

        

        

            

        

        

            

            

            

            

            

            

            

            

            

        

        

            

            

        

        

            

        

        

            

        

        

            

            

            

            

            

            

            

            

            

        

    

            

16位源端口号

            

            

16位目的端口号

            

            

32位序列号

            

            

32位确认号

            

            

4位

            

首部

            

长度

            

            

6位

            

保留

            

            

U

            

R

            

G

            

            

ACK

            

            

P

            

S

            

H

            

            

RST

            

            

SYN

            

            

FIN

            

            

16位窗口大小

            

            

16位TCP检验和

            

            

16位紧急指针

            

            

选项(若有)

            

            

数据(若有)

            

sendip_表2
Arguments for module ./tcp.so:
-ts x TCP source port
构造TCP的源端口,默认为0。
-td x TCP destination port
构造TCP的目的端口,默认为0。
-tn x TCP sequence number
构造TCP的序列号,默认为随机。
-ta x TCP ack number
构造TCP的应答号,默认为0。
-tt x TCP data offset
构造TCP的首部长度,默认是正确值,标准是20字节,最大60字节。
-tr x TCP header reserved field EXCLUDING ECN and CWR bits
TCP头部保留位。
-tfe x TCP ECN(Explicit Congestion Notification)bit (rfc2481)
TCP标志位中保留的ECN字段,默认为0,选项为0、1或r。
-tfc x TCP CWR(Congestion Window Reduced)bit (rfc2481)
TCP标志位中保留的CWR字段,默认为0,选项为0、1或r。
注意:ECN和CWR
-tfu x TCP URG bit
构造TCP标志位中的URG,表示紧急指针有效。当紧急指针(Urgent Pointer)字段有内容时有效。默认为0,选项为0、1或r。
-tfa x TCP ACK bit
构造TCP标志位中的ACK,表示确认ack number有效。默认为0,选项为0、1或r。
-tfp x TCP PSH bit
构造TCP标志位中的PSH,表示接收方应该尽快将这个报文段交给应用层。默认为0,选项为0、1或r。
-tfr x TCP RST bit
构造TCP标志位中的RST,表示需要重建连接,断开目前的连接。默认为0,选项为0、1或r。
-tfs x TCP SYN bit
构造TCP标志位中的SYN,表示使用同步序号用来发起一个连接。默认为1,选项为0、1或r。
-tff x TCP FIN bit
构造TCP标志位中的FIN,表示完成了发送任务。默认为0,选项为0、1或r。
-tw x TCP window size
构造TCP的期望接收的窗口大小值,默认为65535字节。
-tc x TCP checksum
构造TCP的checksum,检验和覆盖了整个TCP的报文段。默认为正确值。可以用于测试DUT设备是不是检验TCP报文的checksum值。
-tu x TCP urgent pointer
构造紧急指针,所谓紧急指针是一个正的位偏移量,和序号字段中的值相加可以得出紧急数据最后一个字节的序号。默认配置为0。注意这个值只有在-tfu置1时才有效,默认情况下如果有-tu参数,-tfu会自动为1,但是强制把-tfu置为1的话会导致-tu的参数无效。
-tonum x
TCP option as string of hex bytes (length is always correct)
选项字段的长度,但是标准字段没有这个选项。默认是没有选项字段的内容。
-toeol TCP option: end of list
选项字段结束的标识符。
-tonop TCP option: no op
没有任何意义,表示无操作,碰到这个字段可以忽略。
-tomss x
表示最长报文大小,每个连接方通常都在通信的第一个报文段中指明这个选项。
-towscale x
TCP option: window scale (rfc1323)
-tosackok
TCP option: allow selective ack (rfc2018)
-tosack x
TCP option: selective ack (rfc2018), format is l_edge1:r_edge1,l_edge2:r_edge2…
-tots x
TCP option: timestamp (rfc1323), format is tsval:tsecr
关于一些不常见的tcp选项字段的含义,以后继续补充。

mysql的“Client does not support authentication protocol requested by server” 问题

从mysql4 到mysql5 一般会遇到这个问题:
Client does not support authentication protocol requested by server; consider upgrading MySQL client

这可以看作是一个客户端的问题,也可以看作是一个服务器端的问题,因为更新客户端可以解决这个问题,修改服务器设置也可以解决这个问题;

1. 在Linux上升级了mysql服务器后,链接mysql服务器就出现了这个问题,以为是多么致命的问题,就升级了客户端,原来用的动态链接库是libmysqlclient.so.10 ,换成libmysqlclient.so.14就可以了

2. 后来发现同样版本的mysql服务器,一个服务器用libmysqlclient.so.10 不能连接,一个用libmysqlclient.so.10 就能连接,感觉不是客户端的问题了,网上查了一下,其实在服务器端简单设置一下就行了,下面是抄人家的,但是我也是验证过了的,我的mysql版本,5.0.14

mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

官方说明:http://dev.mysql.com/doc/refman/5.0/en/old-client.html

(转)解决ARP攻击的方法和原理

(转)解决ARP攻击的方法和原理

【故障原因】

  局域网内有人使用ARP欺骗的木马程序(比如:传奇盗号的软件,某些传奇外挂中也被恶意加载了此程序)。

【故障原理】

  要了解故障原理,我们先来了解一下ARP协议。

  在局域网中,通过ARP协议来完成IP地址转换为第二层物理地址(即MAC地址)的。ARP协议对网络安全具有重要的意义。通过伪造IP地址和MAC地址实现ARP欺骗,能够在网络中产生大量的ARP通信量使网络阻塞。

  ARP协议是“Address Resolution Protocol”(地址解析协议)的缩写。在局域网中,网络中实际传输的是“帧”,帧里面是有目标主机的MAC地址的。在以太网中,一个主机要和另一个主机进行直接通信,必须要知道目标主机的MAC地址。但这个目标MAC地址是如何获得的呢?它就是通过地址解析协议获得的。所谓“地址解析”就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的顺利进行。

  每台安装有TCP/IP协议的电脑里都有一个ARP缓存表,表里的IP地址与MAC地址是一一对应的,如下所示。

主机             IP地址              MAC地址
A             192.168.16.1    aa-aa-aa-aa-aa-aa
B             192.168.16.2    bb-bb-bb-bb-bb-bb
C             192.168.16.3    cc-cc-cc-cc-cc-cc
D             192.168.16.4    dd-dd-dd-dd-dd-dd

  我们以主机A(192.168.16.1)向主机B(192.168.16.2)发送数据为例。当发送数据时,主机A会在自己的ARP缓存表中寻找是否有目标IP地址。如果找到了,也就知道了目标MAC地址,直接把目标MAC地址写入帧里面发送就可以了;如果在ARP缓存表中没有找到相对应的IP地址,主机A就会在网络上发送一个广播,目标MAC地址是“FF.FF.FF.FF.FF.FF”,这表示向同一网段内的所有主机发出这样的询问:“192.168.16.2的MAC地址是什么?”网络上其他主机并不响应ARP询问,只有主机B接收到这个帧时,才向主机A做出这样的回应:“192.168.16.2的MAC地址是bb-bb-bb-bb-bb-bb”。这样,主机A就知道了主机B的MAC地址,它就可以向主机B发送信息了。同时它还更新了自己的ARP缓存表,下次再向主机B发送信息时,直接从ARP缓存表里查找就可以了。ARP缓存表采用了老化机制,在一段时间内如果表中的某一行没有使用,就会被删除,这样可以大大减少ARP缓存表的长度,加快查询速度。

  从上面可以看出,ARP协议的基础就是信任局域网内所有的人,那么就很容易实现在以太网上的ARP欺骗。对目标A进行欺骗,A去Ping主机C却发送到了DD-DD-DD-DD-DD-DD这个地址上。如果进行欺骗的时候,把C的MAC地址骗为DD-DD-DD-DD-DD-DD,于是A发送到C上的数据包都变成发送给D的了。这不正好是D能够接收到A发送的数据包了么,嗅探成功。

  A对这个变化一点都没有意识到,但是接下来的事情就让A产生了怀疑。因为A和C连接不上了。D对接收到A发送给C的数据包可没有转交给C。

  做“man in the middle”,进行ARP重定向。打开D的IP转发功能,A发送过来的数据包,转发给C,好比一个路由器一样。不过,假如D发送ICMP重定向的话就中断了整个计划。

  D直接进行整个包的修改转发,捕获到A发送给C的数据包,全部进行修改后再转发给C,而C接收到的数据包完全认为是从A发送来的。不过,C发送的数据包又直接传递给A,倘若再次进行对C的ARP欺骗。现在D就完全成为A与C的中间桥梁了,对于A和C之间的通讯就可以了如指掌了。

【故障现象】

  当局域网内某台主机运行ARP欺骗的木马程序时,会欺骗局域网内所有主机和路由器,让所有上网的流量必须经过病毒主机。其他用户原来直接通过路由器上网现在转由通过病毒主机上网,切换的时候用户会断一次线。

  切换到病毒主机上网后,如果用户已经登陆了传奇服务器,那么病毒主机就会经常伪造断线的假像,那么用户就得重新登录传奇服务器,这样病毒主机就可以盗号了。

  由于ARP欺骗的木马程序发作的时候会发出大量的数据包导致局域网通讯拥塞以及其自身处理能力的限制,用户会感觉上网速度越来越慢。当ARP欺骗的木马程序停止运行时,用户会恢复从路由器上网,切换过程中用户会再断一次线。

【HiPER用户快速发现ARP欺骗木马】

  在路由器的“系统历史记录”中看到大量如下的信息(440以后的路由器软件版本中才有此提示):

  MAC Chged 10.128.103.124
   MAC Old 00:01:6c:36:d1:7f
   MAC New 00:05:5d:60:c7:18

  这个消息代表了用户的MAC地址发生了变化,在ARP欺骗木马开始运行的时候,局域网所有主机的MAC地址更新为病毒主机的MAC地址(即所有信息的MAC New地址都一致为病毒主机的MAC地址),同时在路由器的“用户统计”中看到所有用户的MAC地址信息都一样。
   如果是在路由器的“系统历史记录”中看到大量MAC Old地址都一致,则说明局域网内曾经出现过ARP欺骗(ARP欺骗的木马程序停止运行时,主机在路由器上恢复其真实的MAC地址)。

【在局域网内查找病毒主机】

  在上面我们已经知道了使用ARP欺骗木马的主机的MAC地址,那么我们就可以使用NBTSCAN(下载地址:http://www.utt.com.cn/upload/nbtscan.rar)工具来快速查找它。

  NBTSCAN可以取到PC的真实IP地址和MAC地址,如果有”传奇木马”在做怪,可以找到装有木马的PC的IP/和MAC地址。

  命令:“nbtscan -r 192.168.16.0/24”(搜索整个192.168.16.0/24网段, 即192.168.16.1-192.168.16.254);或“nbtscan 192.168.16.25-137”搜索192.168.16.25-137 网段,即192.168.16.25-192.168.16.137。输出结果第一列是IP地址,最后一列是MAC地址。

  NBTSCAN的使用范例:

  假设查找一台MAC地址为“000d870d585f”的病毒主机。

  1)将压缩包中的nbtscan.exe 和cygwin1.dll解压缩放到c:下。

  2)在Windows开始—运行—打开,输入cmd(windows98输入“command”),在出现的DOS窗口中输入:C: btscan -r 192.168.16.1/24(这里需要根据用户实际网段输入),回车。

  3)通过查询IP–MAC对应表,查出“000d870d585f”的病毒主机的IP地址为“192.168.16.223”。

【解决思路】

  1、不要把你的网络安全信任关系建立在IP基础上或MAC基础上,(rarp同样存在欺骗的问题),理想的关系应该建立在IP+MAC基础上。

  2、设置静态的MAC–>IP对应表,不要让主机刷新你设定好的转换表。

  3、除非很有必要,否则停止使用ARP,将ARP做为永久条目保存在对应表中。

  4、使用ARP服务器。通过该服务器查找自己的ARP转换表来响应其他机器的ARP广播。确保这台ARP服务器不被黑。

  5、使用"proxy"代理IP的传输。

  6、使用硬件屏蔽主机。设置好你的路由,确保IP地址能到达合法的路径。(静态配置路由ARP条目),注意,使用交换集线器和网桥无法阻止ARP欺骗。

  7、管理员定期用响应的IP包中获得一个rarp请求,然后检查ARP响应的真实性。

  8、管理员定期轮询,检查主机上的ARP缓存。

  9、使用防火墙连续监控网络。注意有使用SNMP的情况下,ARP的欺骗有可能导致陷阱包丢失。

【HiPER用户的解决方案】

  建议用户采用双向绑定的方法解决并且防止ARP欺骗。

  1、在PC上绑定路由器的IP和MAC地址:

  1)首先,获得路由器的内网的MAC地址(例如HiPER网关地址192.168.16.254的MAC地址为0022aa0022aa)。

  2)编写一个批处理文件rarp.bat内容如下:

  @echo off
   arp -d
   arp -s 192.168.16.254 00-22-aa-00-22-aa

  将文件中的网关IP地址和MAC地址更改为您自己的网关IP地址和MAC地址即可。

  将这个批处理软件拖到“windows–开始–程序–启动”中。

  3)如果是网吧,可以利用收费软件服务端程序(pubwin或者万象都可以)发送批处理文件rarp.bat到所有客户机的启动目录。Windows2000的默认启动目录为“C:\Documents and SettingsAll Users「开始」菜单程序启动”。

  2、在路由器上绑定用户主机的IP和MAC地址(440以后的路由器软件版本支持):

  在HiPER管理界面–高级配置–用户管理中将局域网每台主机均作绑定。

 

另一篇:

对付ARP欺骗现在使用最多就是双向IP_MAC绑定

具体操作是在所有电脑上用批处理绑定或间隔一定时间自动绑定路由的MAC, 假如路由IP为192.168.0.1 MAC为00-AA-BB-CC-DD-EE, 则在每个电脑上运行arp -s 192.168.0.1 00-AA-BB-CC-DD-EE
然后再在路由器上绑定所有电脑的IP-MAC

以上方法可以防止ARP欺骗, 游戏帐号的就不会被盗, (在有些操作系统中这样操作也还会被欺骗)
另外你如果要防止内部游戏服务器、电影服务器以及收银机能不被ARP欺骗,则你还要把这些机器的IP-MAC与所有电脑以及路由器绑定。

但是这样一样不能阻止ARP攻击的发生,
有些软件通过限制某些文件安装的方式来限制ARP攻击软件的安装, 实际上一方面你限制的范围很有限, 另外一个方面病毒软件完全可以破你这个限制, 病毒可以把你的限制去掉, 还可以简单的修改调用的dll的文件名, 你就没戏了,  所以说这个方法就好比小孩子办家家.

由于ARP攻击启动时发送大量ARP数据包, 所有的交换机下的网络设备无论是否在相同网断都会收到这些数据报, 并且都会对这些数据报作出响应, 发送ARP回应数据报, 就好比一个电脑在调用所有电脑同时互相攻击, 而局域网数据通讯对带宽的利用是有多少用多少, 没有限制, 这样, 网络中就不断爆发ARP数据流量, 你的网络肯定会瘫痪,  也就是说ARP攻击一启动, 即使你的电脑不被欺骗, 也一样会掉线, 因为ARP流量堵塞了整个网络, 你的网络就瘫痪了
所以说绑定没用

vim 中的backspace问题

1. 经常遇到vim中backspace不能删除字符的问题,下面是解决办法:

在vimrc中添加如下内容即可:

se nocompatible
se bs=2

具体含义,参看
:help
compatible

vi中就不要这么弄了,不支持

2. vim中方向键不好使的解决办法

set t_ku=^[OA
set t_kd=^[OB
set t_kr=^[OC
set t_kl=^[OD

不过可能和term有关系,set term=xterm 试试

国际风云

美国从来没有担心过伊朗的军力, 中俄也从来没有寄希望过伊朗的军力. 美国的军事力量在伊朗能否成功, 只与中俄有关, 与伊朗无关.


伊朗只是棋子, 这个世界在较量的, 就是美国(+欧盟) <—– >中+俄. 这个角力是全方位的, 从经济文化政治到军事. 美国要取得更高的战略地位对付中俄, 中俄要打乱美国的战略步骤(美攻,中俄守). 除了欧盟自己都搞不清自己的目标是什么外,美俄中的目标是一致的:想尽办法削弱敌人的实力, 直至掐死敌人. 谁也不会让对方舒服!
  
  一切政治都是可以谈判和交易的, 就看以实力为后盾的价钱是多少. 什么gou pi "民主自由人权", 都是幌子而已. 自越战后, 美国确实是好好钻研过孙子兵法的, 不像以前那么鲁莽了.

在 Vim 中使用 Tab 键自动完成 PHP 函数

说一下如何使用 Tab 键自动完成,按照习惯,Tab 键通常是用来缩进行的,如输入 4 个空格如果要把 Tab 映射为自动完成,可能使用上稍微有点麻烦,下面会讲如何解决这个问题。

首先需要为 Vim 提供一个 PHP 的函数列表文件,这样 Vim 才能知道如何自动完成一个 PHP 函数。函数列表不需要自己做,PHP 网站上有现成的,拿来用就可以了:

http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt

得到这个文件,直接拷贝到 Vim 目录中,比如根目录下面,然后在 vimrc 中加入如下代码,告知 vim 在自动完成时,需要扫描这个文件来分析关键字。

"You can obtain the completion dictionary file from:

" http://cvs.php.net/viewvc.cgi/phpdoc/funclist.txt

set dictionary-=$VIM/funclist.txt dictionary+=$VIM/funclist.txt

"Use the dictionary completion

set complete-=k complete+=k

那么如何解决缩进的问题呢?我们肯定不愿意在映射另外一个键来做缩进用,感觉会很别扭。下面的函数会解决这个问题。

"Auto completion using the TAB key

"This function determines, wether we are on

"the start of the line text(then tab indents)

"or if we want to try auto completion

function! InsertTabWrapper()

let col=col(‘.’)-1

if !col || getline(‘.’)[col1] !~ ‘\k’

return "\<TAB>"

else

return "\<C-N>"

endif

endfunction

"Remap the tab key to select action with InsertTabWrapper

inoremap <TAB> <C-R>=InsertTabWrapper()<CR>

 

这个函数的作用是判断当前光标前的一个字符是否为一个 Keyword 字符(:help iskeyword),vim 中用 \k 表示,这个字符的范围大约是所有非空白的可打印的字符,但除开某些特殊字符,比如 @ * " 等等。

 

于是效果就出来了,当前导字符为空白或者 @ * 等字符时,Tab 就映射为 成为缩进键。否则就映射为 ,也就是 CTRL+N 调用自动完成功能。