免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 12492 | 回复: 20
打印 上一主题 下一主题

[网络子系统] iptables string模块识别网站,与-j REJECT (-j DROP)结合使用问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-31 15:11 |只看该作者 |倒序浏览
本帖最后由 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;
}

谢谢

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2011-10-31 18:03 |只看该作者
回复 1# lujian19861986

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包放行了?

   
这个 --host 是你的扩展吗。
你的这个问题需要明确一下放过去的那个 请求是否真的应该命中规则。

其次,Linux 内核中 bm 算法(某个版本以前)是有个 BUG 的,有些条件下本应匹配上的,结果匹配失败。

这两个可能性你都要排查一下

论坛徽章:
0
3 [报告]
发表于 2011-10-31 19:06 |只看该作者
回复 2# Godbach


    好,我试试,再贴出测试结果。tcp三次握手后,前7次http get都是命中的,我觉得是最后一次没命中,可能是你说的那样,bm算法有问题,先研究一下。非常感谢

论坛徽章:
0
4 [报告]
发表于 2011-10-31 19:30 |只看该作者
本帖最后由 lujian19861986 于 2012-12-20 09:14 编辑

回复 2# Godbach


哥德巴赫兄,能否就以下问题,讲解一下?
  ip_finish_output(mc);//ip_route_output,作用是查找出去的路由,ip_finish_output作用类似,具体是什么?是否是将创建好的mc包马上发回内网ip??
//设置skb的标志位RST,是否是为了通知www.qq.com服务器,断开连接?

论坛徽章:
2
巨蟹座
日期:2014-03-09 21:37:25射手座
日期:2014-04-16 16:23:03
5 [报告]
发表于 2011-10-31 22:20 |只看该作者
为什么不自己写match模块提取出HTTP报文中的URL进行匹配呢,并不复杂嘛,怎么大家都喜欢去用string模块

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
6 [报告]
发表于 2011-11-01 10:26 |只看该作者
回复 4# lujian19861986

你这是什么意思,代码不是你写的吗?

论坛徽章:
0
7 [报告]
发表于 2011-11-01 15:26 |只看该作者
本帖最后由 lujian19861986 于 2012-12-20 09:25 编辑

回复 6# Godbach


    -j REJECT这个动作是开源的。
我用source insight查了一下源代码,新建的mc包,然后设置mc的各个成员变量值(有设目的方向),ip_finish_output最终调用ip_finish_output2(含释放mc动作)直接发包出去(不需要通过路由表了)。

论坛徽章:
0
8 [报告]
发表于 2011-11-01 15:30 |只看该作者
回复 5# kwest


    你所说的string模块都实现了,而且有比较多功能。一直沿用的。
kwest兄有现成的match模块吗?分享一下,呵呵

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
9 [报告]
发表于 2011-11-01 15:41 |只看该作者
回复 7# lujian19861986
应该是在这个动作之前已经查过路由了,也就是 skb 中的路由项是已经存在了。

Netfilter 架构你了解一下,就知道明白了

        return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev,
                            ip_finish_output,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));


转发的数据包在 PREROUTING 之后就确定路由了,本机发出的数据包,经过 LOCALOUT 之后,进入 POSTROUTING 之前确定路由。

论坛徽章:
2
巨蟹座
日期:2014-03-09 21:37:25射手座
日期:2014-04-16 16:23:03
10 [报告]
发表于 2011-11-01 15:45 |只看该作者
回复 8# lujian19861986
可以在string模块的基础上做些更改,加上对HTTP数据报文的识别,以后规则就可以这样写:
iptables -t filter -A FORWARD -p tcp --dport 80 -m string --url "www.tencent.com" -j DROP
不过这种方式对HTTPS连接无效。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP