IP头部“选项”字段如何添加自定义的信息?主要是作为自定义的匹配字段用

FlashBaby518 2017-03-20 10:16:24
学习中的新手求教,谢谢各位!
在struct ip_option结构中,我看到主要是定义了这么几个选项,包括严格路由、宽松路由、时间戳等选项。这些我用不到,我想在选项字段里,添加自己的连续信息,做一个数据包规则匹配过滤模块。

能通过结合netfilter实现吗?主要是IP选项字段用什么思路去操作,不知该怎么去实现?

我的测试环境是在无线局域网中,只做用户到AP这一段。
...全文
5311 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
Evan_ZGYF丶 2018-05-21
  • 打赏
  • 举报
回复
我有一个思路,你可以把自己想要的字段添加到ip报文的数据段,(就是发送时将应用层传下来的数据偏移几个字节,用于添加自己的字段),接收方收到数据后,在IP层向上传之前,对这段数据进行处理,并且偏移回来
mysqqq 2018-01-16
  • 打赏
  • 举报
回复
楼主做出来了吗?我也在做类似的事情。。想请教一下。
代码誊写工 2017-11-30
  • 打赏
  • 举报
回复
ip的options和tcp的options单单从raw socket、pcap(linux C)或则jpcap、jnetpcap构造解析来说,只是不同类型的数据段,方法上基本类似,难易程度也没有太大区别。如果接收端也是用raw socket或jnetpcap库,应该也就没有太多不同。 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是否有定义好的方法以及是否能够发送报文我就不清楚了。
引用 25 楼 jlu_baqiaoyan 的回复:
SocketOptions这个只是java提供了几个固定的属性,对我感觉没有用。周围人跟我说先实现在tcp报文头部的options中添加信息,(我不是很明白这两种方式有什么区别吗,为什么别人口中tcp实现会比ip实现更容易些)试了jpcap,发现他抓取的报文是镜像包,我想要做的是要在手机app发送的每个请求中都增加自定义数据,raw socket 在跟jdk代码的时候并没有发现,最后跟到的方法是用native 声明的,应该是java 虚拟机去实现了最底层的东西,目前想的是尽量在变动不是很大的情况下实现,但是又一想会导致tcp 报文的校验和和总长度发生变化,觉得自己是在幻想了,不知道有什么意见没,指导指导~
jlu_baqiaoyan 2017-11-30
  • 打赏
  • 举报
回复
引用 21 楼 prolee750607 的回复:
引用 19 楼 jlu_baqiaoyan 的回复:
那知道怎么在 options中添加自定义信息吗,有何见解
SocketOptions这个只是java提供了几个固定的属性,对我感觉没有用。周围人跟我说先实现在tcp报文头部的options中添加信息,(我不是很明白这两种方式有什么区别吗,为什么别人口中tcp实现会比ip实现更容易些)试了jpcap,发现他抓取的报文是镜像包,我想要做的是要在手机app发送的每个请求中都增加自定义数据,raw socket 在跟jdk代码的时候并没有发现,最后跟到的方法是用native 声明的,应该是java 虚拟机去实现了最底层的东西,目前想的是尽量在变动不是很大的情况下实现,但是又一想会导致tcp 报文的校验和和总长度发生变化,觉得自己是在幻想了,不知道有什么意见没,指导指导~
代码誊写工 2017-11-13
  • 打赏
  • 举报
回复
引用 23 楼 jlu_baqiaoyan 的回复:
java不能做到吗,java中有一个socketOption,搞不懂和它有没有关系
既然你继续聊,那我大致说一下: 首先,我的代码有挺大的问题,我改了一下
#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的数据结构和协议规范基本清晰。
jlu_baqiaoyan 2017-11-13
  • 打赏
  • 举报
回复
引用 21 楼 prolee750607 的回复:
引用 19 楼 jlu_baqiaoyan 的回复:
那知道怎么在 options中添加自定义信息吗,有何见解
java不能做到吗,java中有一个socketOption,搞不懂和它有没有关系
jlu_baqiaoyan 2017-11-13
  • 打赏
  • 举报
回复
java不能做到吗,java中有一个socketOption,搞不懂和它有没有关系
代码誊写工 2017-11-10
  • 打赏
  • 举报
回复
引用 19 楼 jlu_baqiaoyan 的回复:
那知道怎么在 options中添加自定义信息吗,有何见解
代码誊写工 2017-11-10
  • 打赏
  • 举报
回复
构造并不复杂,但是添加的自定义信息怎么用?接收方用什么解析?需要发回吗? 以下是一个示例,还没有测试:
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 = &ipopt

struct 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
jlu_baqiaoyan 2017-11-10
  • 打赏
  • 举报
回复
引用 18 楼 prolee750607 的回复:
[quote=引用 17 楼 jlu_baqiaoyan 的回复:] 楼上为啥这么说,没听懂,IP报文头部不是有option这一块吗
是我想当然了,ip确实有options,只是在做报文分析和构造的时候没有见过,而一直都看到tcp options.久而久之就忘了。 现在更正,多谢指教 [/quote] 那知道怎么在 options中添加自定义信息吗,有何见解
代码誊写工 2017-11-09
  • 打赏
  • 举报
回复
引用 17 楼 jlu_baqiaoyan 的回复:
楼上为啥这么说,没听懂,IP报文头部不是有option这一块吗
是我想当然了,ip确实有options,只是在做报文分析和构造的时候没有见过,而一直都看到tcp options.久而久之就忘了。 现在更正,多谢指教
jlu_baqiaoyan 2017-11-09
  • 打赏
  • 举报
回复
楼上为啥这么说,没听懂,IP报文头部不是有option这一块吗
代码誊写工 2017-11-06
  • 打赏
  • 举报
回复
ip没有options,tcp才有
jlu_baqiaoyan 2017-11-06
  • 打赏
  • 举报
回复
楼主,你最后怎么做的,分享一下呗,我也遇到这个问题了
codingMozart 2017-04-14
  • 打赏
  • 举报
回复
引用 12 楼 flash78910 的回复:
[quote=引用 11 楼 nswcfd 的回复:] 是Ip头的一部分,添加自定义选项之后还要修改iphdr->ihl字段 (表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节; 由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节; 去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
麻烦再请教下。我加了自定IP选项后,还应该注意MTU的限制吗?是否要考虑到这个分片的问题,有没有可能我加了IP选项字段就超过了MTU的限制?[/quote] MTU可以通过设置TCP的mss来解决,以太网MTU1500,可以设置tcp的mss为1400左右,来避免分片
FlashBaby518 2017-04-13
  • 打赏
  • 举报
回复
引用 6 楼 codingMozart 的回复:
发送端ip_queue_xmit函数中可以自己添加个IP Option 在tcp_transmit_skb函数中也可以添加TCP Option 一般来说路由器的确不会丢包,但我试了,一般到网站后会被丢掉,可以在出口路由器的qdisc队列转发的过程中把该选项删除 如果要用户态程序可以使用该选项,可能还要修改接口函数。
谢谢回答,其实我只想做从用户到AP这一跳的阶段,想象中应该不会丢包吧。就像在收端做个过滤匹配
FlashBaby518 2017-04-12
  • 打赏
  • 举报
回复
引用 11 楼 nswcfd 的回复:
是Ip头的一部分,添加自定义选项之后还要修改iphdr->ihl字段 (表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节; 由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节; 去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
麻烦再请教下。我加了自定IP选项后,还应该注意MTU的限制吗?是否要考虑到这个分片的问题,有没有可能我加了IP选项字段就超过了MTU的限制?
nswcfd 2017-03-31
  • 打赏
  • 举报
回复
是Ip头的一部分,添加自定义选项之后还要修改iphdr->ihl字段 (表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节; 由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节; 去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
FlashBaby518 2017-03-29
  • 打赏
  • 举报
回复
引用 9 楼 nswcfd 的回复:
SIP/DIP是源IP目的IP。 struct ip_options是存放option解析结果或待添加的option选项的,不是最终报文上的option结构。 最后报文里的选项就是 type length payload的结构,注意4byte对齐就行。 type注意避开已经在使用的IPOPT_XXX。
意思是IP头的选项字段其实就是数据段的一部分吗?我直接在IP固定报头20字节后添加就可以了吗(然后注意4字节对齐)?对选项在报文中的结构或内存描述,我查资料这部分内容确实比较少。大部分都是struct ip_option。新人刚学习,谢谢指教!
nswcfd 2017-03-27
  • 打赏
  • 举报
回复
SIP/DIP是源IP目的IP。 struct ip_options是存放option解析结果或待添加的option选项的,不是最终报文上的option结构。 最后报文里的选项就是 type length payload的结构,注意4byte对齐就行。 type注意避开已经在使用的IPOPT_XXX。
加载更多回复(8)

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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