如果http GET包经过ip层(有些厂商走了加速机制后,http的GET可能不经过IP层),可以用这两个命令之一完成:
iptables -I FORWARD 1 -i br0 -p tcp --dport 80 -m string --algo kmp --string "sina.cn" -j DROP
iptables -I FORWARD 1 -i br0 -p tcp --dport 80 -m string --algo bm --string "" -j REJECT --reject-with host-unreach
最好用第二条。这个实现方法有个缺点:不能对https进行url过滤。
如果http的GET包不经过ip层,就需要通过对DNS解析的截获来达到url过滤的目的。这个就可以同时达到对http和https的url过滤。
iptables -t nat -I PREROUTING 1 -i br0 -p udp --dport 53 -m string --algo bm --url-filter "sina.cn" -j DROP
其中,url-filter是我在libipt_string.c中添加的,添加的代码如下:
-------------------------------------------------------------
"--string [!] string Match a string in a packet\n"
+"--url-fiter url Match a string in a packet\n"
"--hex-string [!] string Match a hex string in a packet\n",
....
{ "hex-string", 1, 0, '5' },
+ { "url-filter", 1, 0, '6' },
{0}
....
+ static void
+parse_url(const char *s, struct ipt_string_info *info)
+{
+#define URL_LEN_MAX 128
+#define URL_LEVEL_MAX 10
+ char url[URL_LEN_MAX] = {0};
+ unsigned char part_len = 0;
+ int levels = 0;
+ int copied = 0;
+ char *p = NULL;
+
+ if (strlen(s) <= URL_LEN_MAX) {
+ /*for detail, please refer to format of url in dns request packet*/
+ for (levels=0; levels
+ p = strchr(s, '.');
+ if (p){
+ part_len = (unsigned char)(p - s);
+ (info->pattern+copied)[0] = part_len;
+ copied += 1;
+
+ strncpy(info->pattern+copied, s, p-s);
+ copied += (int)(p-s);
+
+ s = p+1;
+ } else {
+ part_len = (unsigned char)(strlen(s));
+ (info->pattern+copied)[0] = part_len;
+ copied += 1;
+
+ strncpy(info->pattern+copied, s, strlen(s));
+ copied += strlen(s);
+ break;
+ }
+ }
+ info->patlen = copied;
+ return;
+ }
+ exit_error(PARAMETER_PROBLEM, " url too long `%s'", s);
+}
+
...
*flags |= STRING;
break;
-
+ case '6':
+ if (*flags & STRING)
+ exit_error(PARAMETER_PROBLEM,
+ "Can't specify multiple --url-filter");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_url(argv[optind-1], stringinfo);
+ if (invert)
+ stringinfo->invert = 1;
+ stringinfo->patlen=strlen((char *)&stringinfo->pattern);
+ *flags |= STRING;
+ break;
default:
----------------------------------------------------
以上只是在通常情况下做到url过滤,没有做很多的判断,如:
1. 上面实现中,url最多允许127字节,而实际上,肯定不止这么点,但是通常情况下不会太长,太长了谁去访问你呀,记都记不住啊。
2. 以为例,其中有两个“.”,上面的实现中最多允许出现10个"."。同样的,我还没见过超过5个"."的,所以一般情况下,10个足够用了。
阅读(6739) | 评论(0) | 转发(0) |