学习中的新手求教,谢谢各位!
在struct ip_option结构中,我看到主要是定义了这么几个选项,包括严格路由、宽松路由、时间戳等选项。这些我用不到,我想在选项字段里,添加自己的连续信息,做一个数据包规则匹配过滤模块。能通过结合netfilter实现吗?主要是IP选项字段用什么思路去操作,不知该怎么去实现?我的测试环境是在无线局域网中,只做用户到AP这一段。
在struct ip_option结构中,我看到主要是定义了这么几个选项,包括严格路由、宽松路由、时间戳等选项。这些我用不到,我想在选项字段里,添加自己的连续信息,做一个数据包规则匹配过滤模块。能通过结合netfilter实现吗?主要是IP选项字段用什么思路去操作,不知该怎么去实现?我的测试环境是在无线局域网中,只做用户到AP这一段。
解决方案 »
- 关于realtek 8822be在Linux上的驱动问题
- linux下find命令查找文件诡异事件
- 想安装relion 有一步下载FLTK时出现错误 怎么解决呢 在这里谢谢大家 新年快乐
- Ubuntu14.04 relocation error
- 求大神指点~2.4.18内核如何升级为2.4.20~~
- weblogic12C启动时候遇到的问题,求解
- linux openwrt menuconfig 禁用kmod-buletooth
- 求一份完整的centos 搭建 tacacs+服务器的教程
- 下面如何简单用命令替换,不需要vi进去修改
- Ubuntu 输入reboot后,电脑关机不启动
- Minigui编译问题 - undefined reference to `WndClientRect'
- Linux系统服务器更换主板以后需要如何配置
而且难道对端发送过来的数据包会包含你IP option中的内容?
我只用过ip header中已有的字段,在option添加新字段,我个人感觉影响还是蛮大的。建议更换解决方案。
楼主可以研究一下IP层数据包的处理流程,在IP option中加内容的话,我觉得ip的校验和处是不是需要注意一下,至于在哪里加内容,我觉得直接在内核中IP层部分直接加应该就可以。
我之前做过FreeBSD TCP/IP 协议栈的修改与维护,我们的代码都是直接加在kernel中的。(好像FreeBSD没有netfilter这套架构,所以是直接去动协议栈了)
在tcp_transmit_skb函数中也可以添加TCP Option
一般来说路由器的确不会丢包,但我试了,一般到网站后会被丢掉,可以在出口路由器的qdisc队列转发的过程中把该选项删除
如果要用户态程序可以使用该选项,可能还要修改接口函数。
type注意避开已经在使用的IPOPT_XXX。
(表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节;
由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节;
去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
现在更正,多谢指教
现在更正,多谢指教 那知道怎么在 options中添加自定义信息吗,有何见解
以下是一个示例,还没有测试:
struct ip_opt
{
uint8_t ipt_code;
uint8_t ipt_len;
uint8_t *data;
} ipopt;insert_custom_ipopt(struct ipopt *ipop_p, uint8_t *data_p, uint8_t *ipoptbuff, uint32_t *optlen)
{
//pseudo code:ipopt->len = length(ipopt->code) + length(ipopt->len) + length(*data); //length unit: bytes int i;
if(iptopt_p-code > 1 || iptopt_p->len + 1 > optlen || ipopt_p->len + *optlen + 1 > MAXIPOPTLEN)
{
fprintf(stderr, "ip options build error: options length exceeds MAXIPOPTLEN");
exit(EXIT_FAILURE);
} *((uint16_t *)iptoptbuff) + *optlen= htons(*((uint16_t *)ipopt_p));
ipopt_p = ipopt_p + 2; //确保data是little endian
for (i = 0; i < ipopt_p->len -2 ; i ++)
{
*(iptoptbuff + i) = *(data + i);
} *optlen = *optlen + ipopt_p->len;
}
...
int iolen = 0;
uint32_t *optlen = &iolen;
struct ipopt *ipopt_p = &ipoptstruct iphdr *iphdr = (struct iphdr *)(packet + sizeof(struct ethhdr));
uint8_t *ipoptbuff = packet + sizeof(struct ethhdr) + sizeof(struct iphdr)
...
memset(ipoptbuff, 0, 40)ipopt.code = xxx;
ipopt.len = 40;
char data[37] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
myipopt.data = data;
insert_custom_ipopt(ipopt_p, data_p, ipoptbuff,optlen);
iphdr->ihl = 5 + iol / sizeof(uint32_t);
iphdr->check = 0;
iphdr->check = iphdr_csum(iphdr);查看了RFC和wireshark的示例报文,得到以下几个概念:
1. ip options的总长必须是40byts(这个部分RFC没有找到,仅仅参考wireshark给的samplecaptures),如果不够用0填充
2. ipopt结构体的len必须包含ipopt->code和ipopt->len这两个字节的长度,即data的长度 + 2(这个部分RFC没有找到,仅仅参考wireshark给的samplecaptures)
3. ip options最后的字节必须是0
4.然后填充iphdr->ihl = 5 + iol / sizeof(uint32_t);
5. 最后再计算iphdr->check
首先,我的代码有挺大的问题,我改了一下
#define MAXIPOPTLEN (40 - 1)int add_ipopt(uint8_t ipopt_type, uint8_t ipopt_data_len, uint8_t *data, uint8_t *ipoptbuff, uint32_t optlen, uint8_t *ipopt_finish)
{
int i;
if(*ipopt_finish > 0)
return 0;
if(ipopt_type == IPOPT_EOL)
*ipopt_finish = 1;
return optlen + 1;
if(ipopt_type == IPOPT_NOP)
*(ipoptbuff) = 1;
return optlen + 1; if(optlen + 2 + ipopt_data_len > MAXIPOPTLEN)
{
fprintf(stderr, "ip options build error: options length exceeds MAXIPOPTLEN");
exit(EXIT_FAILURE);
}
*(ipoptbuff ++) = ipopt_type;
*(ipoptbuff ++) = ipopt_data_len + 2;
for (i = 0; i < ipopt_data_len; i ++)
{
*(iptoptbuff ++) = *(data ++);
}
return optlen + 2 + (uint32_t)ipopt_data_len;
}void mypcap_build_ipopt(uint8_t *packet)
{
uint8_t ipopt_finish = 0;
uint32_t optlen = 0;
struct iphdr *iphdr = (struct iphdr *)(packet + sizeof(struct ethhdr));
uint8_t *ipoptbuff = packet + sizeof(struct ethhdr) + sizeof(struct iphdr);
/* 这里用add_ipopt()函数填入各种option
... ...
optlen = add_ipopt(IPOPT_EOL, 0, NULL, ipoptbuff, optlen, &ipopt_finish); //最后必须填充IPOPT_EOL /* 创建iphdr,计算csum */
... ...
}
但是毕竟option是一种无固定结构的数据类型,我暂时无法设计出能适应所有结构的函数(主要是大小端的问题)。java我只是拿来和hadoop、elk交互和生成json,偶尔访问一下数据库,我肯定不会用它来做协议构造分析的开发,因为那是它的短板。就好像一般人不会拿管道煤气炉烧烤,除非是在是没有其它可以用,也不怕难吃(管道煤气有毒且有硫化物的臭味)
所以其实我不熟悉java,也不喜欢java(其实不怪java,主要是一般公司里用java的没有别人提供的框架,就啥也不会干了<框架就是超市里卖的盒饭,除了会加热他啥也不会,但居然和别人说他是个厨子>),但个人认为除了汇编以外,语言没有高下之分,只有使用的人的区别。java虽然处理内核级的问题也许性能比c低点儿,但肯定提供了能处理这种简单问题的库,你只需要构造好报文数据结构。
大致看了一下oracle java doc,没有找到raw socket,但有第三方提供的jpcap、jnetpcap等收发链路层的库。虽然我不太熟悉java,但我可以很肯定的说,如果是一个一年以上经验的誊写工来说,用java做你说的应该是没有难度,最多就是多看看手册。
另外你说的socketoption应该和c里的setsockopt/getsockopt对应,这个在oracle java doc里已经提到,在C里这个函数里是可以设置IPPROTO_IP的IP_OPTINOS,也就是ip option,但看oracle java doc的文档StandardSocketOptions里没有实现这个,估计是因为没有实现raw socket所以没有对网络层的设置就做了限制,避免不可预测错误。
最后再扯扯,ip options是需要设备和系统支持的,我不确定路由器等会不会把它丢弃,除非本身是做网络设备的,估计才会在ip options里下功夫,但用java做网络设备的底层?如果不是,那就真的没有必要在这里放自定义数据。
用什么语言不重要,但至少应该把Ethernet、IP、TCP/UDP的数据结构和协议规范基本清晰。
ip的options和tcp的options其意义的不同是在于如果接收端不是自定义的一些socket处理,比如它是一个标准的网络设备(路由、防火墙或移动核心网分组域设备)或则内核,那么其中标准的字段是有其特殊意义的,这点可以参考rfc文档或则man手册。
因为我对java实现底层socket不熟悉,我只能从网络协议方面说说,一就是ip层处理的时候还没有tcp的端口号,也就是五元组不全,在这层处理的时候必然要自定义tcp这层的处理才能判断,影响延时。二是中间经过的不同厂家网络设备有可能修改ip报头(比如做NAT),可能去掉ip的options(这个我没有较复杂的网络环境做判断,所以无法肯定),但至少移动网络肯定是一个比较复杂的网络体系,并不像局域网和普通的互联网,它核心网分组域有很多的协议层次,你发送的报文在其中要经过GGSN、SGSN或SGW、PGW等设备的处理,而且牵涉到Moblie IP和漫游的处理,有多次隧道包装和头部修改,所以用tcp options信息保持的完整性会应该高于ip options。而且在c里,raw socket是可以只构造tcp数据结构,而把ip交给内核去处理,那么当然会节省一些代码。
java的SocketOptions的标准选项仅仅是告诉内核socket收发缓存、组播、tos、ttl等应该采取的处理方式,并没有针对ip options和tcp options的字段填充和解析,所以肯定满足不了你的需求。至于校验和以及总长度用C的话都是自己定义函数计算然后填充,而jpcap是否有定义好的方法以及是否能够发送报文我就不清楚了。