免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5384 | 回复: 6
打印 上一主题 下一主题

[vpn] (已解决)移植pppoe服务器的问题(pppd2.4.2里的mppe加密) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-29 14:11 |只看该作者 |倒序浏览
不好意思哈,不知道到底应该发到哪个板块!
  使用的是rp-pppoe3.10,pppd2.4.2。
  不用mppe加密,winodws自带的默认client, 能正常连接,但假如使用mppe的话就不行了!看了pppd日志,发现windows client要求mppe用statefull,而pppd2.4.2好像只支持stateless。(不知道是不是自己参数配置上有哪里错了,还是说就是pppd2.4.2就是这样的?)
ps:后来修改pppd ccp.c关于mppe的源码,给server传入statefull,windows client能登陆了,但却ping都ping不同,抓包的一看,回的好像是lcp信息(手边没有环境,所以都是凭记忆的)。
   开始以为是自己手边的pppd有问题,可是后来使用从网上下的pppd2.4.2,似乎也是不行,有同样的问题!!!
   有没有哪位兄弟碰到过这种问题的啊?google了一天也没有找到有用的东西,郁闷!

[ 本帖最后由 qiangsheng_cu 于 2009-12-1 16:40 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-11-29 14:57 |只看该作者

回复 #1 qiangsheng_cu 的帖子

没有编译内核支持

论坛徽章:
0
3 [报告]
发表于 2009-11-29 15:06 |只看该作者
内核那一块应该没有问题吧
因为前面移了pptpd,mppe时能正常使用!我也看了pptpd时的log,发现windos pptpd client用的是stateless,而pppoe client则是statefull。
还是说statefull和stateless有对应的内核选项吗?的确编译内核的时候压缩的那几个选项都没选的,另外好像还有一两个选项也没有选,记不大清了。

论坛徽章:
0
4 [报告]
发表于 2009-12-01 16:37 |只看该作者
大概搞定了,至少能ping通和访问网页了!晕,这两天都在弄这个东东。
在网上找一大圈(pppd,pppoe的maillist都去找了),发觉很有可能是mppe实现的问题。今天就对照mppe的最新补丁和rfc3078去修改。---,只是修改了解密那个函数,真的是运气啊!说实话,自己是完全没有信心的,毕竟假如有问题的话,怎么可能就在那一个函数里面!!!当然还有一个理由就是stateless时能正确处理。
其实自己之所以动手,也是误打误撞的结果: 抓包发现windows client发 flushed包时,并没有特别设置ccount,而自己记忆中的mppe_decompress()好像是假设两者都要设置的!这似乎和rfc里的描述好像也有不对应的地方。所以就......
修改处都有注释:@2009.12.01。就改了几处而已!
/*
* Decompress (decrypt) an MPPE packet.
* @2009.12.01 参考mppe最新补丁 和rfc3078 修改
* 主要修改的地方是:
*   1.discard state,它的步进竟然是256,而后面新版是1;它那里的算法好像也有点问题,主要是循环条件那里
*   2.normal state和 flushed那里,将mppe_rekey()的调用提到normal state,flushed处调用的是arcfour_setkey().这里没明白单独调用arcfour_setkey()有什么用,只是按照最新patch的做法而已,嘿
* 当然,state->ccount 的增长那里可以像新patch那样写成一个函数或者宏,嘿,俺是新手,怕出问题,而且也就两个地方而已,所以就...
*/
int
mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
        int osize)
{
    ppp_mppe_state *state = (ppp_mppe_state *) arg;
    unsigned ccount;
    int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
    int sanity = 0;

    if (isize <= PPP_HDRLEN + MPPE_OVHD) {
    if (state->debug)
        printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n",
           state->unit, isize);
    return DECOMP_ERROR;
    }
    /* Strange ... our output size is always LESS than the input size. */
    /* assert(osize >= isize - MPPE_OVHD - 2); */

    osize = isize - MPPE_OVHD - 2;

    ccount = MPPE_CCOUNT(ibuf);

    /* sanity checks -- terminate with extreme prejudice */
    if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
    printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
           state->unit);
    state->sanity_errors += 100;
    sanity = 1;
    }
    if (!state->stateful && !flushed) {
    printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
           "stateless mode!\n", state->unit);
    state->sanity_errors += 100;
    sanity = 1;
    }
    #if 1 //question. when 0xff, must set flushed? I don't know, so I don't deal with it
    if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
    printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
           "flag packet!\n", state->unit);
    state->sanity_errors += 100;
    sanity = 1;
    }
    #endif

    if (sanity) {
    if (state->sanity_errors < SANITY_MAX)
        return DECOMP_ERROR;
    else
        /*
         * Take LCP down if the peer is sending too many bogons.
         * We don't want to do this for a single or just a few
         * instances since it could just be due to packet corruption.
         */
        return DECOMP_FATALERROR;
    }

    /*
     * Check the coherency count.
     */

    if (!state->stateful) {
    /* RFC 3078, sec 8.1.  Rekey for every packet. */
    while (state->ccount != ccount) {
        mppe_rekey(state, 0);
        state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
    }
    } else {
    /* RFC 3078, sec 8.2. */
    if (!state->discard) {
        /* normal state */
        state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
        #if 1 //下面(discard state 也有调用)也有调用,可以做成一个宏@2009.12.01
        if ((state->ccount & 0xff) == 0xff) {
            //mppe_change_key(state, 0);
            mppe_rekey(state, 0);
        }   
        #endif
        if (ccount != state->ccount) {
        /*
         * (ccount > state->ccount)
         * Packet loss detected, enter the discard state.
         * Signal the peer to rekey (by sending a CCP Reset-Request).
         */
        state->discard = 1;
        return DECOMP_ERROR;
        }
    } else {
        /* discard state */
       if (!flushed) {
        /* ccp.c will be silent (no additional CCP Reset-Requests). */
        return DECOMP_ERROR;
        } else {
        /* Rekey for every missed "flag" packet. */
        #if 0 //@2009.12.01
        while ((ccount & ~0xff) != (state->ccount & ~0xff)) {
            mppe_rekey(state, 0);
            state->ccount = (state->ccount + 256) % MPPE_CCOUNT_SPACE;
        }
        #else
        while( ccount != state->ccount ){
            state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
            if ((state->ccount & 0xff) == 0xff) {
                //mppe_change_key(state, 0);
                mppe_rekey(state, 0);
            }               
        }
        #endif
        /* reset */
        state->discard = 0;
        state->ccount = ccount;
        /*
         * Another problem with RFC 3078 here.  It implies that the
         * peer need not send a Reset-Ack packet.  But RFC 1962
         * requires it.  Hopefully, M$ does send a Reset-Ack; even
         * though it isn't required for MPPE synchronization, it is
         * required to reset CCP state.
         */
        }
    }
    #if 0 //@2009.12.01
    if (flushed)
        mppe_rekey(state, 0);
    #else
    if (flushed){
        printk(KERN_DEBUG" recv packet have seted flushed(FLUSHED bit) in stateful mode\n";
        arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen);
    }
    #endif
    }
    /*
     * Fill in the first part of the PPP header.  The protocol field
     * comes from the decrypted data.
     */
    obuf[0] = PPP_ADDRESS(ibuf);    /* +1 */
    obuf[1] = PPP_CONTROL(ibuf);    /* +2 */
    obuf  += 2;
    ibuf  += PPP_HDRLEN + MPPE_OVHD;
    isize -= PPP_HDRLEN + MPPE_OVHD;    /* -6 */
                    /* net: -4 */

    /* And finally, decrypt the packet. */
    arcfour_decrypt(&state->arcfour_context, ibuf, isize, obuf);

    state->stats.unc_bytes += osize;
    state->stats.unc_packets++;
    state->stats.comp_bytes += isize;
    state->stats.comp_packets++;

    /* good packet credit */
    state->sanity_errors >>= 1;

    return osize;
}
ps:说实话,回头看自己的过程,真的很惊险,完全都是运气使然!!!
而且好像对自己的提高也不大! 并没有理清/理解 整个框架就在动手了!(嘿,对加解密真的完全不明白,比如密码的初始化、如何加解密、密匙的分发、密匙的同步,一大堆...)。到头来 也没有什么收获,哎......

论坛徽章:
0
5 [报告]
发表于 2009-12-01 16:48 |只看该作者
原帖由 qiangsheng_cu 于 2009-12-1 16:37 发表
大概搞定了,至少能ping通和访问网页了!晕,这两天都在弄这个东东。
在网上找一大圈(pppd,pppoe的maillist都去找了),发觉很有可能是mppe实现的问题。今天就对照mppe的最新补丁和rfc3078去修改。--- ...

源码
参照下

论坛徽章:
0
6 [报告]
发表于 2009-12-01 16:59 |只看该作者
嗯,都是从网上找的。
patch:http://mppe-mppc.alphacron.de/#BUGS  
rfc:http://www.ietf.org/rfc/rfc3078.txt
我自己用的那个就不用了吧,公司项目里的,呵呵。
大概是:kernel2.4.18,linux-2.4.18-mppe-mppc-0.92.patch.gz,ppd2.4.2,rp-pppoe3.10。
参考patch是linux-2.4.31-mppe-mppc-1.3.patch.gz  patch for kernel 2.4.31

论坛徽章:
0
7 [报告]
发表于 2009-12-01 18:04 |只看该作者

回复 #6 qiangsheng_cu 的帖子

实现的方式不同
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP