首页 > 其他 > 详细

portal 认证的双向nat

时间:2020-08-29 00:56:22      阅读:125      评论:0      收藏:0      [点我收藏+]

  在外使用手机连接无线网络时,连上无线网络后,手机会自动弹出一个portal 认证页面或者访问某网站时 会重定向到一个认证portal 页面;其网络拓扑如下:

  sta-------------网络设备--------------公网

比如sta 终端ip 是100.100.100.100  访问百度,但是按道理应该返回百度啊?那怎么返回的是 认真页面呢?这里面涉及到报文拦截 。

当sta 的报文经过网络设备时,网络设备会将报文copy到网络设备自身处理,而不是转发出去。但是报文的目的ip 指向的是baidu.com ,到了网络设备cpu 处理时,其协议栈也会forward啊?

所以为了防止报文forward出去,协议栈会读报文进行双向nat处理。

比如100.100.100.100-------->baidu.com -------------经过dnat sant 后会变成 3.3.3.1----------------->3.3.3.2 此时3.3.3.2 正好是网络设备本机接口ip ,所以本机设备就会收取次报文然后回复http 报文

但是内核协议栈的nat 模块有个奇怪的地方就是:

local_out出去的报文经过dnat后,又会重新路由,这就会导致网络设备回复报文时,出接口错误。可以看到如下代码:可能调用ip_route_me_harder  重新路由

nf_nat_local_fn(unsigned int hooknum,
        struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
        int (*okfn)(struct sk_buff *))
{
    const struct nf_conn *ct;
    enum ip_conntrack_info ctinfo;
    unsigned int ret;

    /* root is playing with raw sockets. */
    if (skb->len < sizeof(struct iphdr) ||
        ip_hdrlen(skb) < sizeof(struct iphdr))
        return NF_ACCEPT;

    ret = nf_nat_fn(hooknum, skb, in, out, okfn);
    if (ret != NF_DROP && ret != NF_STOLEN &&
        (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

        if (ct->tuplehash[dir].tuple.dst.u3.ip !=
            ct->tuplehash[!dir].tuple.src.u3.ip) {
            if (ip_route_me_harder(skb, RTN_UNSPEC))
                ret = NF_DROP;
        }

    }
    return ret;
}

 

所以一般 portal 认证的双向nat 不会用内核协议栈本身的逻辑实现。一般都会自身写一个conn-nat。

一般都会使用conntrack  的扩展功能实现。具体就不讲了

        
/* We must be after connection tracking and before packet filtering. */

static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
    /* Before packet filtering, change destination */
    {
        .hook        = nf_test_nat_in,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,
        .priority    = NF_IP_PRI_CONNTRACK + 1,
    },
    /* After packet filtering, change source */
    {
        .hook        = nf_test_nat_out,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_OUT,
        .priority    = NF_IP_PRI_CONNTRACK + 1,
    },
};

也就是在PRE_ROUTING 直接替换 源ip 目的ip 将报文直接送到本机出来

     iph->saddr =  htonl(3.3);
        iph->daddr =  htonl(3.1);
        tcph->source = htons(auth_info->alloc_port);

        ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip = htonl(3.1);
        ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip = htonl(3.3);
        ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port = htons(auth_info->alloc_port);

 

LOCAL_OUT直接反向替换 源ip 目的ip  然后将报文dev_xmit到设备

auth_info = nf_ct_ext_find(ct, NF_CT_EXT_TEST);
    if (auth_info == NULL ){
        return NF_ACCEPT;
    }
    --------------
  iph->saddr =  auth_info->org_dip;
    iph->daddr =  auth_info->org_sip;

    tcph->dest = auth_info->org_port;
--------------------------
nat_output_with_info()

 

portal 认证的双向nat

原文:https://www.cnblogs.com/codestack/p/13580428.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!