http 重定向 302报文

我这里的重定向环境是对客户端的请求直接截断重定向到其他页面。

 

以太头和Ip头想应数据对调。

Tcp头flags标记和序号问题。主要问题

数据内容主要的就两条:

"HTTP/1.1 302 Moved Temporarily"

"Location: 路径"

 

 

一、以太头结构

 

 

在帧结构里我用到的有MAC目的地址,以太类型。至于802.1Q标签,如果加了,对以太类型想对地址要向生移4个字节。源来的地址值则为0x8100。

 

用到的以太类型是 0x800 表以后一个负载段的内容是一个IP包。这个宏定义在if_ether.h头文件里。

 

#define ETH_P_PUPAT     0x0201              /*Xerox PUP Addr Trans packet      */

#define ETH_P_IP    0x0800              /*Internet Protocol packet     */

#define ETH_P_X25 0x0805              /* CCITTX.25                     */

#define ETH_P_ARP         0x0806              /*Address Resolution packet */

 

先看是不是IP包

         是:对换MAC地址,复制以太头结构到buffer

         不是:这个就直接转发的转发,丢包的丢包了不管了。

 

 

 
         unsignedshort *port = NULL;
         unsignedshort h_poto = 0;
        
         if(pkt->eth_hdr_ptr->h_proto== htons(ETH_P_8021Q))
         {
                   h_poto= *((unsigned short *) pkt ->eth_hdr_ptr + 8);
         }
         else
         {
                   h_poto= pkt ->eth_hdr_ptr->h_proto;
         }
        
         if( h_poto != htons(ETH_P_IP) )
         {
                   returnERROR_FAIL;
         }
 
         port= (unsigned short *) pkt->l4_hdr_ptr;
         if(port== NULL)
         {
                   returnERROR_FAIL;
         }

 

 

 

 

 

 

 

二、IP报文头结构的话

 

 

 

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
         __u8         ihl:4,
                   version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
         __u8         version:4,
                ihl:4;
#else
#error       "Pleasefix <asm/byteorder.h>"
#endif
         __u8         tos;
         __be16     tot_len;
         __be16     id;
         __be16     frag_off;
         __u8         ttl;
         __u8         protocol;
         __sum16 check;
         __be32     saddr;
         __be32     daddr;
         /*Theoptions start here. */
};
 

 

 

 

 

 

Version = 4;

Ihl 一般情况下都是5。我在重定向的时候直接 new_ipv4_hdr->ihl  = old_ipv4_hdr->ihl;因为长度使用收到报文头长度,所以如果后还有选项的话是直接复制到新的头结构中。

Tos两样复制接收到的报文数据。现在都不怎么用这个字段了。

Tot_len是指从IP头结构到数据的总长度,自己算。我在算你在算,在校验之前算好。

Id我比较简单直接用0。这个会用于分片和重新组装数据报。我也没用到只是发一个302重定向报文。

Frag_off直接0。我也没有分片,用不到偏移。

Ttl一般不是32就是64。

Protoco 根据自己的实际情况为6。

Check 去网上找个现成的就可以。也可以找找lib库接口函数

Saddr daddr 直接对换了就可以。

 

 

要是有大小端的情况下,在这些头结构中如果字段是32位的就用 htonl 或是 ntohl;要是16位的话就用 htons 或是 ntohs。这个问题当时还纠结了好几天。唉

 

 

 

 
int reply_packet_iphdr_data(pkt_info_s *pkt,struct iphdr *ipv4_hdr)
{
         //其他没有填写字段的内容需要在算校验之前填好
         ipv4_hdr->id=0;
         ipv4_hdr->version=4;
         ipv4_hdr->ihl=pkt->ipv4_hdr_ptr->ihl;
         ipv4_hdr->ttl=64;
         ipv4_hdr->protocol=6;      //tcp 6
         ipv4_hdr->frag_off=ntohs(0x4000);
         ipv4_hdr->tos=pkt ->ipv4_hdr_ptr->tos;
 
         ipv4_hdr->daddr=pkt ->ipv4_hdr_ptr->saddr;
         ipv4_hdr->saddr=pkt ->ipv4_hdr_ptr->daddr;
         ipv4_hdr->check= 0;
 
         returnERROR_OK;
}

 

 

 

 

 

 

 

 三、tcp头结构

 

 

 

struct tcphdr {
    __be16 source;
    __be16 dest;
    __be32 seq;
    __be32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u16  res1:4,
        doff:4,
       fin:1,
       syn:1,
       rst:1,
       psh:1,
       ack:1,
       urg:1,
       ece:1,
       cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
    __u16  doff:4,
       res1:4,
       cwr:1,
       ece:1,
       urg:1,
       ack:1,
       psh:1,
       rst:1,
       syn:1,
       fin:1;
#else
#error "Adjustyour <asm/byteorder.h> defines"
#endif
    __be16 window;
    __sum16    check;
    __be16 urg_ptr;
};
 

 

 

 

 

 

 

TCP协议头最少20个字节,和IP头到是一样

TCP源端口(Source Port),TCP目的端口(Destination port) 对换

 

  TCP序列号(序列码,Sequence Number):32位

TCP应答号(Acknowledgment Number):32位

 

数据偏移量(HLEN):4位包括TCP头大小,指示何处数据开始。其实也是tcp头部长度。

  保留(Reserved):6位值域,这些位必须是0。为了将来定义新的用途所保留。

标志(Code Bits):6位标志域:

1.       URG:紧急标志

紧急(The urgent pointer) 标志有效。紧急标志置位,

2.       ACK:确认标志

确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure:1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

3.       PSH:推标志

该标志置位时,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或rlogin 等交互模式的连接时,该标志总是置位的。

4.       RST:复位标志

复位标志有效。用于复位相应的TCP连接。

5.       SYN:同步标志

同步序列编号(SynchronizeSequence Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

6.       FIN:结束标志

带有该标志置位的数据包用来结束一个TCP回话,但对应端口仍处于开放状态,准备接收后续数据。

  窗口(Window):16位,用来表示想收到的每个TCP数据段的大小。随便写个就好不要太小了。

  校验位(Checksum):16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。

  优先指针(紧急,Urgent Pointer):16位,指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。

选项(Option):长度不定,但长度必须以字节。如果没有 选项就表示这个一字节的域等于0。 一般只用出到在syn包中

数据(Date):应用程序的数据。

 

 

 

 

从三次握手开始。

C -------> S:     syn 1; ack 0;客户端seq,ack_seq会有值。可能是一个随机值,写一个就可以

C <------- S:      syn 1; ack 1; 捎带ack。服务端回 seq = 随机值。Ack_seq = old_seq + 1

C -------> S:     syn 0; ack 1; 端回 seq = old_ack_seq; Ack_seq= old_seq + 1

C -------> S: get psh1; ack 1; 端回seq  Ack_seq 和上一个ack包的一样。

C <------- S: 302 fin 1;psh 0; ack 1; 端回 seq= old_ack_seq; Ack_seq = old_seq + data_len

 

对于客户端发过来的seq和ack_seq 值直接取就可以,为了给回包用。之后就直接丢了。

在头两个syn包里会有选项字段内容。要注意MSS

 

重定向主要就回了两个包:一个是syn_ack包。另一个是http 302包。

注意get 报文可能会进行tcp分片:发两个ack数据包等一个ack确认回包。真到psh,ack包发之后才算是一个完整的get 报文。

 

 

 

//这些数据基本不用变。
    tcp_hdr->dest= pdesc->tcp_hdr_ptr->source;
    tcp_hdr->source= pdesc->tcp_hdr_ptr->dest;
    tcp_hdr->doff= pdesc->tcp_hdr_ptr->doff;
    tcp_hdr->window= pdesc->tcp_hdr_ptr->window;
    tcp_hdr->check= 0;
    tcp_hdr->seq= pdesc->tcp_hdr_ptr->ack_seq;
    tcp_hdr->ack= 1;
 
// ack_seq字段的两种情况
    if(send_falg!= 0)
    {
        tcp_hdr->ack_seq= htonl(ntohl(pdesc->tcp_hdr_ptr->seq)+ data_len);
    }
    else
    {
        tcp_hdr->ack_seq= htonl(ntohl(pdesc->tcp_hdr_ptr->seq)+ 1);
    }

 

 

 

 

 

//剩下的就是根据下边四个状态进行处理了。

        fin:1,

        syn:1,

        rst:1,

        psh:1,

 

 四、http 302报文最小头部

在组过302报文头内容之后需要自己组http302报文内容

 

1,最小可用http 302报文头

 

HTTP/1.1 302 Moved Temporarily

Server: JSP2/1.0.26

Location: www.hao123.com

 

 

这里需要注意server: 的内容必须是location认识的服务器类型,不知道的话可以去抓个包看下。要是不对的话302报文不认。

 

2,自组302报文不认,

 

在进行三次握手重定向时自组syn_ack报文复回正确,到了302报文客户端接收了,wirshark抓包也没错但就是不认的情况,可以调试下http302头部字段内容。

eg: 如果有Content-Length:字段但是值不对,对于有的服务器来就不认。这是我碰到的一个问题,调试了好几天MD。而且这个值还不怎么好添加,直接干掉OK。

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brickie-liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值