请求网络高手???

请求网络高手???

我要用perl写一个分析器,一台www服务器,要求当远方访问的时候得到远方的整个请求链.以下是用perl iptables::ipv4::IPqueue 实现部份代码:
          #!/usr/bin/perl
    use iptables::ipv4::ipqueue
    use netpacket::IP
    my $ipq=new iptables::ipv4::ipqueue
     (copy_mode=>ipq_copy_packe)
              while(1)
{
                 my $msg->get_message;
                 my $ip=Netpak::ip->decode($msg->payload);
                 print "accepted packet from" ,$ip->{dest_ip} "\n";
                 $ipq->set_verdict($msg->packet-id,NF_ACCEPT);
}
这里只有取出IP,有没有办法取了请求链接内容.例如,远端用户输入http://www.testhost.com/1.rmvb  此时www服务器就能取得该链接???
谢谢
楼主,这个基本上很难!!!
或者说很复杂,
如果你能在http的服务器上工作就可以直接处理他的日志就可以了,

否则从这么底层处理很复杂,
你目前做到的只是捕获了ip包(得到了目的地址)
这还远远不够, 你还要找出tcp包,并且查看tcp的端口是不是http端口(如果端口不固定又更麻烦)
还要看包的数据部分, 找到类似get /head ....的http请求标志,那么就差不多了
但是如果请求的数据分片了的话,你还要处理后续的包才能组合成一个完整的url  -_-!


QUOTE:
原帖由 dajun 于 2008-4-23 09:39 发表
楼主,这个基本上很难!!!
或者说很复杂,
如果你能在http的服务器上工作就可以直接处理他的日志就可以了,

否则从这么底层处理很复杂,
你目前做到的只是捕获了ip包(得到了目的地址)
这还远远不够, 你还要找 ...

现在的IP链已经找出了,也可以找到IP的ID,从ID中应该有方法取得链接的内容?一起探讨一下.谢谢??
你先给我讲讲iptables吧
modprobe ip_queue
iptables -t mangle -A OUTPUT -p tcp -j QUEUE

mangle表具体是做甚的? perlipq文档中说的是icmp,但是我换成tcp,机器网络就挂了,只好重启,

为啥不用pcap ?
在OUTPUT上的所有输出,对包进行修改,并送到QUEUE用户空间,你可能是远程连接主机,所有访问TCP的软件都在OUTPUT链上转到QUEUE用户空间中,等待处理.所以网络断了!
了解, 把进mangle表的包规则搞的窄一些就好了
modprobe ip_queue
iptables -t mangle -A OUTPUT -p tcp -s 192.168.1.7 -d 192.168.1.2 --dport 80 -j QUEUE

这是我参照pod说明写的程序,你看看吧,应该很多地方需要修改,比如ip分片:

[Copy to clipboard] [ - ]
CODE:
#!/usr/bin/perl

use IPTables::IPv4::IPQueue qw(:constants);
use NetPacket::IP qw(:strip);
use NetPacket::TCP;

use constant TIMEOUT => 1_000_000 * 2;          # 2 seconds

my $i=0;
my $q = new IPTables::IPv4::IPQueue(copy_mode => IPQ_COPY_PACKET,copy_range => 2048)
    || die IPTables::IPv4::IPQueue->errstr;

while(1) {
    my $msg = $q->get_message(TIMEOUT);
    if (!defined $msg) {
            next if IPTables::IPv4::IPQueue->errstr eq 'Timeout';
            die IPTables::IPv4::IPQueue->errstr;
    }
    get_url($msg->payload()) if $msg->data_len();
    $q->set_verdict($msg->packet_id, NF_ACCEPT);
}

sub get_url {
    my $p = shift;
    my $tcp = NetPacket::TCP->decode(ip_strip($p));
    if ($tcp->{dest_port} == 80) {
        my $data = $tcp->{data};
        if ($data =~/^(GET|HEAD|POST)\s(.*?)\s.*?[\r]\n.*?Host\:\s(.*?)[\r]\n/si) {  
#get前似乎有空格也符合http协议吧,其他的\s类似, 还有host定位也不保险, 你自己修改吧
         #   print $data;
            print "http://$3$2\n";

        }

    }
}

(没想到没那么复杂-_-, 但是这样的架构,估计数据量大就麻烦了,如果程序挂了,连接就会被挂住)

我试下来的结果是性能是原来的一半:  不加iptables规则10000条请求大约9秒多,加了以后17.9~19.x秒

这位大哥,如果我不考虑分片,不考虑来自任何IP服务器的访问.现在服务器应用在rtsp服务器中.rtsp://1.2.3.4/123.3gp?token=1,如何让token=1时让其通过.其它不通过.
dajun    (弓虽) 兄到那去了??打印的数据内容是乱码,怎么办.

使用你的例子不能打印出http链接啊??请看一下有没有其它错的地方
这个问题并不难,我大致讲讲。

1. 按照你说的“token=1时让其通过.其它不通过”,这样就是类似于IPS了,你要注意perl脚本是否能够达到你的负载要求。

2. 数据先被你的perl程序拿到,简单的办法有三种。一种是iptables转向,将数据发给你的perl,然后你脚本过滤处理,转发数据到真实应用;第二种是直接将域名解析到你的perl程序的机器,perl监听端口得到请求,然后过滤处理,转发数据;第三种是你提到过的,直接用perl操作iptables模块。如果是apache之类的,你还可以给apache写模块。

3. 一般来说,上面的几种方法都是需要你实现协议解码的。你没说明白到底是什么协议,一会似乎是http,一会儿似乎是rstp的。