- 论坛徽章:
- 0
|
本帖最后由 lujian19861986 于 2012-12-20 09:15 编辑
目的:阻挡访问腾讯首页,
iptables规则一:
iptables -A FORWARD -i eth0 -p tcp --dport 80 -m string --algo bm --host "www.qq.com" -j DROP
测试结果:http get包会一直重复(大概10次),等2分钟后,tcp重发包竟然通过了防火墙,导致可以访问网站。查看源代码没发现有控制session数量为10个,为什么后续的get包放行了?
iptables规则二:
iptables -A FORWARD -i eth0 -p tcp --dport 80 -m string --algo bm --host "www.qq.com" -j REJECT --reject-with url-block
作用:REJECT拒绝并且返回包(可含This URLs or Page has been blocked.),客户端立即知道无法到达。
测试结果:用IE访问www.qq.com,立即显示“This URLs or Page has been blocked.”
REJECT相关的代码:
libipt_REJECT.c中
static const struct reject_names reject_table[] = {
{"icmp-net-unreachable", "net-unreach",
IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
{"icmp-host-unreachable", "host-unreach",
IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
{"icmp-proto-unreachable", "proto-unreach",
IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
{"icmp-port-unreachable", "port-unreach",
IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
#if 0
{"echo-reply", "echoreply",
IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
#endif
{"icmp-net-prohibited", "net-prohib",
IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
{"icmp-host-prohibited", "host-prohib",
IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
{"tcp-reset", "tcp-rst",
IPT_TCP_RESET, "TCP RST packet"},
{"url-block", "url-block",
IPT_TCP_URLBLOCK, "url block packet"},
{"icmp-admin-prohibited", "admin-prohib",
IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
};
ipt_REJECT.c中
static unsigned int reject(struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
const struct ipt_reject_info *reject = targinfo;
/* Our naive response construction doesn't deal with IP
options, and probably shouldn't try. */
if ((*pskb)->nh.iph->ihl<<2 != sizeof(struct iphdr))
return NF_DROP;
/* WARNING: This code causes reentry within iptables.
This means that the iptables jump stack is now crap. We
must return an absolute verdict. --RR */
switch (reject->with) {
case IPT_ICMP_NET_UNREACHABLE:
send_unreach(*pskb, ICMP_NET_UNREACH);
break;
case IPT_ICMP_HOST_UNREACHABLE:
send_unreach(*pskb, ICMP_HOST_UNREACH);
break;
case IPT_ICMP_PROT_UNREACHABLE:
send_unreach(*pskb, ICMP_PROT_UNREACH);
break;
case IPT_ICMP_PORT_UNREACHABLE:
send_unreach(*pskb, ICMP_PORT_UNREACH);
break;
case IPT_ICMP_NET_PROHIBITED:
send_unreach(*pskb, ICMP_NET_ANO);
break;
case IPT_ICMP_HOST_PROHIBITED:
send_unreach(*pskb, ICMP_HOST_ANO);
break;
case IPT_ICMP_ADMIN_PROHIBITED:
send_unreach(*pskb, ICMP_PKT_FILTERED);
break;
case IPT_TCP_RESET:
send_reset(*pskb, hooknum);
break;
case IPT_ICMP_ECHOREPLY:
/* Doesn't happen. */
break;
}
return NF_DROP;
}
static int check(const char *tablename,
const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const struct ipt_reject_info *rejinfo = targinfo;
const struct ipt_entry *e = e_void;
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
return 0;
}
/* Only allow these for packet filtering. */
if (strcmp(tablename, "filter") != 0) {
DEBUGP("REJECT: bad table `%s'.\n", tablename);
return 0;
}
if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
| (1 << NF_IP_FORWARD)
| (1 << NF_IP_LOCAL_OUT))) != 0) {
DEBUGP("REJECT: bad hook mask %X\n", hook_mask);
return 0;
}
if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
printk("REJECT: ECHOREPLY no longer supported.\n");
return 0;
} else if (rejinfo->with == IPT_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (e->ip.proto != IPPROTO_TCP
|| (e->ip.invflags & IPT_INV_PROTO)) {
DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
return 0;
}
} else if (rejinfo->with == IPT_TCP_URLBLOCK) {
/* Must specify that it's a TCP packet */
if (e->ip.proto != IPPROTO_TCP
|| (e->ip.invflags & IPT_INV_PROTO)) {
DEBUGP("REJECT: IPT_TCP_URLBLOCK\n");
return 0;
}
}
return 1;
}
谢谢 |
|