- 论坛徽章:
- 0
|
在开源程序urlfilterd里面,当一个包被DROP时(比如PC的浏览器访问了被家长控制的网页),我利用原始套接字构造了一个IP包(回给浏览器)(请看下面Manju updated begin 和Manju updated end.之间的代码)。问题出在我通过语句:
clew_tcphdr->ack_seq = htonl(payload_len) + tcp->seq;
设置确认号ack_seq。printf打印出来的结果表明该值设置成功,但是抓包发现该值payload_len并没有加上去,导致对端(PC浏览器)不断重传上一次的包。
请问:利用原始套接字,如何才能设置TCP的确认号?
望不吝赐教为盼!
部分代码如下:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__u16 tot_len;
__u16 id;
__u16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
__u32 saddr;
__u32 daddr;
/*The options start here. */
};
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 "Adjust your <asm/byteorder.h> defines"
#endif
__be16 window;
__sum16 check;
__be16 urg_ptr;
};
static int pkt_decision(struct nfq_data * payload)
{
char *data;
char *match, *folder, *url;
PURL current;
int payload_offset, data_len;
struct iphdr *iph;
struct tcphdr *tcp;
match = folder = url = NULL;
data_len = nfq_get_payload(payload, &data);
if( data_len == -1 )
{
//printf("data_len == -1!!!!!!!!!!!!!!!, EXIT\n");
exit(1);
}
//printf("data_len=%d ", data_len);
iph = (struct iphdr *)data;
tcp = (struct tcphdr *)(data + (iph->ihl<<2));
payload_offset = ((iph->ihl)<<2) + (tcp->doff<<2);
unsigned int payload_len = (unsigned int)ntohs(iph->tot_len) - ((iph->ihl)<<2) - (tcp->doff<<2);
match = (char *)(data + payload_offset);
if(strstr(match, "GET ") == NULL && strstr(match, "POST ") == NULL && strstr(match, "HEAD ") == NULL)
{
//printf("****NO HTTP INFORMATION!!!\n");
return PKT_ACCEPT;
}
//printf("####payload = %s\n\n", match);
for (current = purl; current != NULL; current = current->next)
{
if (current->folder[0] != '\0')
{
folder = strstr(match, current->folder);
}
if ( (url = strstr(match, current->website)) != NULL )
{
if (strcmp(listtype, "Exclude") == 0)
{
if ( (folder != NULL) || (current->folder[0] == '\0') )
{
//printf("####This page is blocked by Exclude list!\n");
// Manju updated begin...
if (iph->version == 4)
{
printf("%s@%u:%u %u %x %x %u %u\n", __FUNCTION__, __LINE__,
iph->version, iph->tot_len, iph->saddr, iph->daddr,
tcp->source, tcp->dest); // Manju debug
struct sockaddr_in addr;
bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = tcp->source;
addr.sin_addr.s_addr = iph->saddr;
int on=1;
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sockfd >= 0)
{
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
setsockopt(sockfd, IPPROTO_TCP, IP_HDRINCL, &on, sizeof(on));
int head_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
char http_buf[] = {"HTTP/1.1 302 Found\r\nLocation: http://192.168.0.1/sky_http_limit.html\r\n"};
char buf[256];
bzero(buf, sizeof(buf));
strncpy(buf+head_len, http_buf, sizeof(buf)-head_len);
struct iphdr *clew_iphdr = (struct iphdr *)buf;
clew_iphdr->version = iph->version;
clew_iphdr->ihl = sizeof(struct iphdr)>>2;
clew_iphdr->tos = 0;
clew_iphdr->tot_len = htons(head_len+strlen(http_buf)+1);
clew_iphdr->id = 0;
clew_iphdr->frag_off = 0;
clew_iphdr->ttl = MAXTTL;
clew_iphdr->protocol = IPPROTO_TCP;
clew_iphdr->check = 0;
clew_iphdr->daddr = iph->saddr;
clew_iphdr->saddr = iph->daddr;
struct tcphdr *clew_tcphdr = (struct tcphdr *)(buf + sizeof(struct iphdr));
clew_tcphdr->source = tcp->dest;
clew_tcphdr->dest = tcp->source;
clew_tcphdr->seq = tcp->ack_seq;
clew_tcphdr->ack_seq = htonl(payload_len) + tcp->seq;
printf("clew_tcphdr->ack_seq=%x %x %x %x\n", ntohl(clew_tcphdr->ack_seq), payload_len, ntohl(payload_len), tcp->seq); // Manju debug
clew_tcphdr->doff = 5;
clew_tcphdr->ack = 1;
clew_tcphdr->window = 6501;
clew_tcphdr->check = 0;
sendto(sockfd, buf, head_len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
clew_tcphdr->psh = 1;
sendto(sockfd, buf, head_len+strlen(http_buf)+1, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
clew_tcphdr->psh = 0;
clew_tcphdr->fin = 1;
sendto(sockfd, buf, head_len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
//close(sockfd);
}
}
// Manju updated end.
return PKT_DROP;
}
else
{
//printf("###Website hits but folder no hit in Exclude list! packets pass\n");
return PKT_ACCEPT;
}
}
else
{
if ( (folder != NULL) || (current->folder[0] == '\0') )
{
//printf("####This page is accepted by Include list!");
return PKT_ACCEPT;
}
else
{
//printf("####Website hits but folder no hit in Include list!, packets drop\n");
return PKT_DROP;
}
}
}
}
if (url == NULL)
{
if (strcmp(listtype, "Exclude") == 0)
{
//printf("~~~~No Url hits!! This page is accepted by Exclude list!\n");
return PKT_ACCEPT;
}
else
{
//printf("~~~~No Url hits!! This page is blocked by Include list!\n");
return PKT_DROP;
}
}
//printf("~~~None of rules can be applied!! Traffic is allowed!!\n");
return PKT_ACCEPT;
} |
|