- PHP code
<?php //数据 $dns_id = "\x80\xc1"; $dns_flags = "\x01\x00"; $dns_count_queries = "\x00\x01"; $dns_count_answers = "\x00\x00"; $dns_count_auth_rr = "\x00\x00"; $dns_count_add_rr = "\x00\x00"; $dns_qry_name = "\x02\x69\x70\x02\x63\x6e\x00"; $dns_qry_type = "\x00\x01"; $dns_qry_class = "\x00\x01"; $dns = $dns_id . $dns_flags . $dns_count_queries . $dns_count_answers . $dns_count_auth_rr . $dns_count_add_rr . $dns_qry_name . $dns_qry_type . $dns_qry_class; //IP头 $ip_version = "\x45"; //4位版本 $ip_hdr_len = ""; // 4位首部长度 $ip_dsfield = "\x00"; //8位服务类型 $ip_len = pack('n*',28 + strlen($dns)); //16位总长度 $ip_id = "\x55\xf0"; //16位标识 $ip_flags = "\x00"; //3位标识 $ip_frag_offset = "\x00"; // 13位偏移 $ip_ttl = "\x80"; //8位生存时间 $ip_proto = "\x11"; //8位协议 $ip_src = ipto16("192.168.1.100"); //32位源IP $ip_dst = ipto16("8.8.4.4"); //32位目的IP $ip_checksum = ipchecksum($ip_version,$ip_hdr_len,$ip_dsfield,$ip_len,$ip_id,$ip_flags,$ip_frag_offset,$ip_ttl,$ip_proto,$ip_src,$ip_dst); //16位首部效验和 $ip_header = $ip_version . $ip_hdr_len . $ip_dsfield . $ip_len . $ip_id . $ip_flags . $ip_frag_offset . $ip_ttl . $ip_proto . $ip_checksum . $ip_src . $ip_dst; //UDP头 $udp_srcport = "\xfc\x39"; //16位源端口 $udp_dstport = "\x00\x35"; //16位目的端口 $udp_length = pack('n*',8 + strlen($dns)); //16位UDP长度 $udp_checksum = udpchecksum($ip_src,$ip_dst,$ip_proto,$udp_length,$udp_srcport,$udp_dstport,$dns); //16位UDP效验和 $udp = $udp_srcport . $udp_dstport . $udp_length . $udp_checksum; //$buf = $ip_header . $udp . $dns; $buf = $udp . $dns; function send($host,$port,$buf,$dns_flags) { // $socket = socket_create(AF_INET, SOCK_PACKET, getprotobyname("ip")); $socket = socket_create(AF_INET, SOCK_RAM,1); $timeout = array('sec'=>1,'usec'=>500000); // socket_set_option($socket,IPPROTO_IP,IP_HDRINCL,SO_RCVTIMEO,$timeout); socket_set_option($socket,SOL_SOCKET,SO_RCVTIMEO,$timeout); // while(1) socket_sendto($socket, $buf, strlen($buf), 0, $host, $port); } function udpchecksum($ip_src,$ip_dst,$ip_proto,$udp_length,$udp_srcport,$udp_dstport,$dns) { $data = $ip_src . $ip_dst . "\x00" . $ip_proto . $udp_length . $udp_srcport . $udp_dstport . $udp_length . "\x00\x00" . $dns; if (strlen($data)%2) $data .= "\x00"; $bit = unpack('n*', $data); $sum = array_sum($bit); while ($sum >> 16) $sum = ($sum >> 16) + ($sum & 0xffff); return pack('n*', ~$sum); } function ipchecksum($ip_version,$ip_hdr_len,$ip_dsfield,$ip_len,$ip_id,$ip_flags,$ip_frag_offset,$ip_ttl,$ip_proto,$ip_src,$ip_dst) { $data = $ip_version . $ip_hdr_len . $ip_dsfield . $ip_len . $ip_id . $ip_flags . $ip_frag_offset . $ip_ttl . $ip_proto . "\x00\x00" . $ip_src . $ip_dst; $bit = unpack('n*', $data); $sum = array_sum($bit); while ($sum >> 16) $sum = ($sum >> 16) + ($sum & 0xffff); return pack('n*', ~$sum); } function ipto16($ip) { $tmp = explode(".",$ip); $ip = ""; foreach($tmp as $a => $b) { $tmp = dechex($b); if (strlen($tmp)==1) $tmp = "0" . $tmp; $ip .= $tmp; } $ip = pack("h*",$ip); return $ip; } send("8.8.4.4",53,$buf,$dns_flags);
这是个查询向指定dns服务器查询指定域名IP信息的程序,用Wireshark抓包测试可用,但是现在没有用自己的网络层,也就是IP头,我要用自己构造的IP头,
把
$buf = $ip_header . $udp . $dns;
//$buf = $udp . $dns;
改成
$buf = $ip_header . $udp . $dns;
//$buf = $udp . $dns;
结果还是不行,应该是send那函数的问题,请问下应该怎么修改
------解决方案--------------------
不知道你在干什么?利用 sock 包的肯定是在用户层了
封装 ip 应该在下一层