2012-10-17 2 views
0

내 PC로 들어오는 ip 패킷을 수정하려고합니다. iptables를 사용하여 패킷을 큐에 넣고 libnetfilter_queue 라이브러리를 사용하여 실제로는 일부 http-header 내용을 수정합니다. 단일 문자를 변경하더라도 패킷은 TCP 체크섬의 변경으로 인해 거부됩니다. 그래서, 수정 된 패킷의 TCP 체크섬을 다시 계산하려고합니다. 처음에는 체크섬 기능을 테스트하기 위해 패킷을 수정하는 것이 아니라 단순히 체크섬을 다시 계산합니다. 그러나 계산 된 체크섬은 원래의 체크섬과 일치하지 않습니다. `여기서계산 된 tcp checksum과 원래 tcp checksum이 일치하지 않습니다.

unsigned short tcp_sum_calc(unsigned short len_tcp, unsigned short src_addr[],unsigned short dest_addr[], unsigned short buff[]) 
{ 
unsigned char prot_tcp=6; 
unsigned long sum; 
int nleft; 
unsigned short *w; 

sum = 0; 
nleft = len_tcp; 

w=buff; 

/* calculate the checksum for the tcp header and payload */ 
while(nleft > 1) 
{ 
sum = sum + ntohs(*w); 
w++; 
nleft = nleft - 2; 
} 

/* if nleft is 1 there ist still on byte left. We add a padding byte (0xFF) to build a 16bit word */ 
if(nleft>0) 
{ 
    cout<<"check out"; 
// sum += *w&0xFF; 
sum += ntohs(*w&0xFF00);   // is this the correct way of doing 
} 

/* add the pseudo header */ 
sum += ntohs(src_addr[0]); 
sum += ntohs(src_addr[1]); 
sum += ntohs(dest_addr[0]); 
sum += ntohs(dest_addr[1]); 
sum += len_tcp; 
sum += prot_tcp; 

// keep only the last 16 bits of the 32 bit calculated sum and add the carries 
sum = (sum >> 16) + (sum & 0xFFFF); 
sum += (sum >> 16); 

// Take the one's complement of sum 
sum = ~sum; 

return ((unsigned short) sum); 
} 

libnetfilter_queue 모듈의 콜백 함수이다 : 여기서

static int analyzeResponse(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,struct nfq_data *nfa, void *data) 
{ 
int len=0,id=0; 
struct iphdr *ip; 
struct tcphdr *tcp; 
    char *pktData; 
string tempPkt; 
unsigned short chksum=0,ip_hdr_len,tcp_len; 
unsigned int src_ip, des_ip; 
struct nfqnl_msg_packet_hdr *pktHeader; 
pktHeader = nfq_get_msg_packet_hdr(nfa); 

if (pktHeader) 
{ 
    id = ntohl(pktHeader->packet_id); 
} 
len = nfq_get_payload ((struct nfq_data *) nfa, (char**)&ip); 

if(len) 
{ 
    pktData=(char*)ip; 
    ip_hdr_len=(unsigned short)(pktData[0]&0x7); 
    src_ip=ip->saddr; 
    des_ip=ip->daddr; 
    int pos; 
    tempPkt.assign(pktData,len); 
    pos=tempPkt.find("teststring",0); 
     tempPkt.replace("teststring"); 
    pktData=(char*)tempPkt.c_str(); 
      tcp = (struct tcphdr*) (pktData + (4*ip_hdr_len)); 

    cout<<"*********************************************************************************"; 
    cout<<ip_hdr_len; 
    cout<<"\ntcp checksum: "<<tcp->check; 
    cout<<"\nip packet length: "<<ip->tot_len; 
    cout<<"\nip packet length_calc: "<<len; 
    cout<<"\nip source address: "<<src_ip; 
    cout<<"\nip destination address: "<<des_ip; 
    cout<<"*********************************************************************************"; 
    tcp->check=0; 
tcp_len=len - (4*ip_hdr_len); 
    chksum = tcp_sum_calc(tcp_len, (unsigned short *) &src_ip, (unsigned short *) &des_ip, (unsigned short *) &tcp); 
    tcp->check=chksum; 
    cout<<"\nnew checkksum: "<<chksum; 
return nfq_set_verdict(qh, id, NF_ACCEPT, len, (unsigned char*)pktData); 

} 
return nfq_set_verdict(qh, id, NF_ACCEPT, len, (unsigned char*)pktData); 
} 

출력된다

5 
tcp checksum: 11687 
ip packet length: 54017 
ip packet length_calc: 467 
ip source address: 1719453657 
ip destination address: 2569775296 
new checkksum: 36507 

`

답변

2

그 모습 여기 체크섬 함수이다 데이터의 엔디안 - 의사 헤더를 수정하지 않습니다. 원시 데이터는 빅 엔디안이지만 인텔 아키텍처는 리틀 엔디안입니다. 따라서 직접 추가하기 전에 단어의 바이트를 바꿔야합니다. ntohs()을 사용할 수 있습니다.

이 부분은 example을 참조하십시오.

+0

나는 필요한 수정을했다. 그러나 아직도 작동하지 않는다. –

+0

@adnankamili 그것은 아직도 작동하지 않는다. .. 그러나 행동은 바뀌 었 느냐? –

+0

예 행동이 바뀌 었습니다. 아무도 수정 된 코드를 게시 할 수 있습니까? –