百思不得其解:从ip包头中取源目地址不正确

smn 2003-11-29 04:59:37
用libpcap抓包,目的是得到该包的源目IP地址。首先参照tcpdump的sniffer.c定义两个结构体
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ip_hl:4, /* header length */
ip_v:4; /* version */
#if BYTE_ORDER == BIG_ENDIAN
u_int ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
#endif /* not _IP_VHL */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
抓到包后就在其前加上以太网头
struct sniff_ip *ip=(struct sniff_ip*)(packet + sizeof(struct sniff_ethernet));
然后从中取出源目IP地址
printf("\tFrom: %s\n", inet_ntoa(ip->ip_src));
printf("\tTo: %s\n", inet_ntoa(ip->ip_dst));

当我pcap_lookupnet()里用的网络设备是eth0的时候,得到的两个IP地址就只是我的网卡和ADSL MODEM的IP,例如192.168.1.2和192.168.1.1。但我的目的是想得到本机在互联网上的IP和我所浏览的网站的IP,例如218.20.225.71和216.239.41.99。
于是我pcap_lookupnet()里用的网络设备是ppp0(当然是用pppoe虚拟拨号后才能运行),结果很奇怪,源目IP的位置移位了!
例如,我查到本机在互联网的IP是61.144.119.155,然后一边 ping 202.96.128.68,一边运行我的抓包程序,连续抓几个包显示如下:1
From: 58.217.61.144
To: 119.155.202.96
2
From: 162.203.202.96
To: 128.68.61.144
3
From: 58.217.61.144
To: 119.155.202.96
4
From: 162.65.202.96
To: 128.68.61.144
......
从中可见,两个IP的位置都移动了,源IP 61.144.119.155 在第一个包中前两个字节在源IP,后两个字节在目的IP;目的IP 202.96.128.68 在第一个包中前两个字节在目的IP,后两个字节就不在此包中了。
难道IP包头的结构会变化的吗?请高手们指点一下吧,我在此问题上已经磨了很久了,看过很多例子都是用这个IP头结构来取得源目IP地址的,但用的都是eth0网络设备,所以都只能得到在局域网内的IP,而不是互联网IP。

分不够的再加,多少都行。
...全文
73 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
t0mychen 2003-12-03
  • 打赏
  • 举报
回复
gz
smn 2003-12-03
  • 打赏
  • 举报
回复
局域网我抓过没问题,因为是用eth0设备,一旦用ppp0设备就不行了.

我试过加长IP HEADER,现在只有试一下加长ETHER HEADER了.

谢谢你的建议.
kissing 2003-12-03
  • 打赏
  • 举报
回复
我在windows环境下抓包的时候网络环境比较单纯,就是ethernet局域网,
所以我解析ip包的时候就是把ether header加长。如果这样处理还不行的话
我怀疑是你的包格式与你设想的不一样
我建议你一边用你的程序抓,一边用sniffer抓一下,看看到底跑的是什么包
什么情况下你的抓包程序能正常解析,什么情况下不能,这样对比一下,我想
肯定能找到原因所在的
嗬嗬,个人见解,仅供参考
smn 2003-12-02
  • 打赏
  • 举报
回复
还有,请问你确定windows里抓包是后移两位后,是怎么处理的?

还望指点迷津啊!
smn 2003-12-02
  • 打赏
  • 举报
回复
header length 和 version各占四位,4+4=8位,一个字节没错啊?
kissing 2003-12-02
  • 打赏
  • 举报
回复
我在windows里面抓包确实是后移了两位的
不如将sniff_ethernet 的后面增加一个u_16,这样也许看的清楚一点
还有一点我不太看得明白,ip header 的版本号加上长度是1个字节,
按照上面的写法,虽然是各用了4bit,但是仍然是一个uint,4个字节啊
smn 2003-12-02
  • 打赏
  • 举报
回复
feng_me 2003-12-01
  • 打赏
  • 举报
回复
我的也是如此,不过没有继续下去。

IP包移位,是不是因为转换高低位的问题?
smn 2003-12-01
  • 打赏
  • 举报
回复
谢谢kissing(风满楼),我也试过将struct sniff_ip结构体加大了16位(即增加一个u_int16_t类型的成员),结果是有的包能取得正确的两个IP,有时候又不行,估计此方法也不对.

不知在windows里的编程会有同样问题吗?
smn 2003-12-01
  • 打赏
  • 举报
回复
顶一下
hotwind 2003-12-01
  • 打赏
  • 举报
回复
包对齐的问题。
delphimm 2003-12-01
  • 打赏
  • 举报
回复
强烈关注
hecCIBN 2003-12-01
  • 打赏
  • 举报
回复
up
kissing 2003-12-01
  • 打赏
  • 举报
回复
刚才我的解释看来不能正确解释这个现象
刚才查了一下资料,事实上在rfc中ether头虽然是14个字节,但是在分配包的空间时
为了使ip包头数据对齐,所以在分配ether头时多分配了两个字节,为16字节。
所以解析ip包应该从第17个字节开始
kissing 2003-12-01
  • 打赏
  • 举报
回复
如果是用ppp拨号上网的话那么包的格式确实是不同的
ppp是第二层的协议,如果你是通过网卡连接到modem的话,跑的可能是pppoe,这种格式
的封包会在ether头后面增加ppp的包头,所以你如果想正确分析包的话就需要去查一下
pppoe的封包格式
至于你说的第一个问题,原因可能在于你解析的是网卡与猫之间的通讯封包,而在这个封包
里面封装了整个ppp的包,这个封包到达猫后应该会被解析出来
这是个人理解,希望对你有些帮助
smn 2003-11-29
  • 打赏
  • 举报
回复
哦, 会么? 只是一个拨号软件, 不会这样改变包头结构吧?
elife 2003-11-29
  • 打赏
  • 举报
回复
可能用ppp0 with pppoe你抓到的包最外就不是ethernet包, 而是经过ppp封装的, 所以你要先解ppp包头

23,118

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧