syimyuzya / tunet-cli

Command line tool for Tsinghua University network authentication
27 stars 8 forks source link

联网认证实名制,原脚本GG #6

Closed realconnor closed 4 years ago

realconnor commented 6 years ago
syimyuzya commented 6 years ago

額⊙﹏⊙……

這個腳本的連線方式是參考了 Lab μ 的 TUNet 的,那個的情況現在如何呢?(目前不在學校…

jiegec commented 6 years ago

目前auth开始大范围上线,我正在逆向,准备发PR

realconnor commented 6 years ago

从我的经验来看(针对有线网),紫荆时而跳转到auth4,时而又恢复成net,主楼到目前为止还是net,这个过渡期可能比较长。我目前模仿这个脚本(A),针对auth4写了个简单的login脚本(B),不过又写了个简单的shell(C)放在crontab里,目的是来判断是不是能ping通 net.tsinghua.edu.cn,如果可以调用A,否则调用B,目前情况还可以,能应付这种跳来跳去的问题。

所以我建议你写个新的tunetctl,但是别把老的覆盖了,因为两个都有用。我可以提供C来判断用哪个…

jiegec commented 6 years ago

主要是今天紫二也上了auth。。。科协的服务器也受影响了。

jiegec commented 6 years ago

仔细研究了一下auth,它需要发两次请求,并且用了一个自定义的编码。最简单的方法就是Headless Chrome配脚本(这个已经写成功了)。但是这个方案对嵌入式设备并不友好。 抓取到的代码:

//jQuery XEncode 扩展
$.extend({
    xEncode: function(str, key) {
        if (str == "") {
            return "";
        }
        var v = s(str, true),
            k = s(key, false);
        if (k.length < 4) {
            k.length = 4;
        }
        var n = v.length - 1,
            z = v[n],
            y = v[0],
            c = 0x86014019 | 0x183639A0,
            m,
            e,
            p,
            q = Math.floor(6 + 52 / (n + 1)),
            d = 0;
        while (0 < q--) {
            d = d + c & (0x8CE0D9BF | 0x731F2640);
            e = d >>> 2 & 3;
            for (p = 0; p < n; p++) {
                y = v[p + 1];
                m = z >>> 5 ^ y << 2;
                m += (y >>> 3 ^ z << 4) ^ (d ^ y);
                m += k[(p & 3) ^ e] ^ z;
                z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
            }
            y = v[0];
            m = z >>> 5 ^ y << 2;
            m += (y >>> 3 ^ z << 4) ^ (d ^ y);
            m += k[(p & 3) ^ e] ^ z;
            z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
        }

        function s(a, b) {
            var c = a.length,
                v = [];
            for (var i = 0; i < c; i += 4) {
                v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
            }
            if (b) {
                v[v.length] = c;
            }
            return v;
        }

        function l(a, b) {
            var d = a.length,
                c = (d - 1) << 2;
            if (b) {
                var m = a[d - 1];
                if ((m < c - 3) || (m > c))
                    return null;
                c = m;
            }
            for (var i = 0; i < d; i++) {
                a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
            }
            if (b) {
                return a.join('').substring(0, c);
            } else {
                return a.join('');
            }
        }

        return l(v, false);
    }
});

//jQuery getJSON 扩展
var get = $.get;
$.extend({
    getJSON: function(url, data, callback) {
        if (url.match("srun_portal") != null || url.match("get_challenge") != null) {
            var enc = "s" + "run" + "_bx1",
                n = 200,
                type = 1,
                base64 = new Hashes.Base64();
            if (data.action == "login") { //login
                $data = data;
                return jQuery.getJSON(url.replace("srun_portal", "get_challenge"), { "username": $data.username, "ip": $data.ip, "double_stack": "1" }, function(data) {
                    var token = "";
                    if (data.res != "ok") {
                        alert(data.error);
                        return;
                    }
                    token = data.challenge;
                    $data.password = $data.org_password;
                    $data.info = "{SRBX1}" + base64.encode(jQuery.xEncode(JSON.stringify({ "username": $data.username, "password": $data.password, "ip": $data.ip, "acid": $data.ac_id, "enc_ver": enc }), token));
                    //alert($data.info);
                    var hmd5 = new Hashes.MD5().hex_hmac(token, data.password);
                    $data.password = "{MD5}" + hmd5;
                    $data.chksum = new Hashes.SHA1().hex(token + $data.username + token + hmd5 + token + $data.ac_id + token + $data.ip + token + n + token + type + token + $data.info);
                    $data.n = n;
                    $data.type = type;
                    return get(url, $data, callback, "jsonp");
                });
            } else if (data.action == "logout") { //logout
                $data = data;
                return jQuery.getJSON(url.replace("srun_portal", "get_challenge"), { "username": $data.username, "ip": $data.ip, "double_stack": "1" }, function(data) {
                    var token = "";
                    if (data.res != "ok") {
                        alert(data.error);
                        return;
                    }
                    token = data.challenge;
                    $data.info = "{SRBX1}" + base64.encode(jQuery.xEncode(JSON.stringify({ "username": $data.username, "ip": $data.ip, "acid": $data.ac_id, "enc_ver": enc }), token));
                    //alert($data.info);
                    var str = token + $data.username + token + $data.ac_id + token + $data.ip + token + n + token + type + token + $data.info;
                    $data.chksum = new Hashes.SHA1().hex(str);
                    $data.n = n;
                    $data.type = type;
                    return get(url, $data, callback, "jsonp");
                });
            } else {
                return get(url, data, callback, "jsonp");
            }
        }
        return get(url, data, callback, "json");
    }
});

function GetQueryString(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return unescape(r[2]);
    return null;
}

$(function() {
    $("#form2").submit(function(e) {
        e.preventDefault();
        var acid = $("#ac_id"),
            uname = $("#username"),
            pwd = $("#password"),
            uip = $("#user_ip");
        if (acid.val() == "" || acid.val() == "0") {
            alert("您打开的认证页面未经重定向,点击确定后将自动重定向到正确的页面。");
            location = "http://www.baidu.com";
            return false;
        }
        if (uname.val() == "") {
            alert("请填写用户名(Please fill in the username)");
            uname.focus();
            return false;
        }

        if (pwd.val() == "") {
            alert("请填写密码(Please fill in the password)");
            pwd.focus();
            return false;
        }

        // var save_me = 0;
        // if ($("input[name='save_me']").is(':checked')) {
        //     save_me = 1;
        // }
        if ($('#cookie')[0].checked == false) {
            $.cookie("off_campus", "off", { expires: 30 });
            uname.val(uname.val()+"@tsinghua");
        } else {
            $.cookie("off_campus", null);
        }

        //login  认证
        var qData = {
            "action": "login",
            "username": uname.val(),
            "org_password": pwd.val(),
            "password": pwd.val(),
            "ac_id": acid.val(),
            "ip": "",
            "double_stack": "1"
        };
        $.getJSON("/cgi-bin/srun_portal", qData, function(data) {
            if ($('#cookie')[0].checked == false) {
                uname.val(uname.val().replace("@tsinghua", ''));
            }
            if (data.error == "ok") {
                $.cookie('access_token', data.access_token);
                qData.password = pwd.val();
                //提交两次
//                if (data.client_ip.indexOf(":") >= 0){
//                    $.getJSON(location.protocol + "//" + "auth4.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
//                }else {
//                    $.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
//                }
                //提交一次
                //$.getJSON(location.protocol + "//" + location.hostname + "/cgi-bin/srun_portal", qData, function(data) {});
                var redirect = getUrlParam('userurl');
                if (redirect != ""){
                    location.href = redirect;
                } else {
                    if ($('#cookie')[0].checked == false) {
                        location.href = location.protocol + "//" + location.hostname + "/succeed_wired.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token + "&access=no";
                    }else {
                        location.href = location.protocol + "//" + location.hostname + "/succeed_wired.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token;
                    }
                }
                return false;
            }
            if (data.error_msg.indexOf("E2616") >= 0) {
                alert("您的账户已余额不足(Your account has insufficient balance)");
            } else {
                for (var i in PortalError) {
                    if (data.error_msg.indexOf(i) >= 0) {
                        alert(PortalError[i]);
                        return false;
                    }
                }
                alert(data.error_msg);
                return false;
            }
        });
        // //$.ajaxSettings.async = false;
        // //$.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
        //
        // //$.getJSON(location.protocol + "//" + "auth4.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {
        //     if ($('#cookie')[0].checked == false) {
        //         uname.val(uname.val().replace("@tsinghua", ''));
        //     }
        //     if (data.error == "ok") {
        //         $.cookie('access_token', data.access_token);
        //         if ($('#cookie')[0].checked == false) {
        //             location.href = location.protocol + "//" + location.hostname + "/succeed_wired.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token + "&access=no";
        //         }else {
        //             location.href = location.protocol + "//" + location.hostname + "/succeed_wired.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token;
        //         }
        //         // $.cookie('username', uname.val());
        //         // $.cookie('password', pwd.val());
        //         return false;
        //     }
        //     if (data.error_msg.indexOf("E2616") >= 0) {
        //         alert("您的账户已余额不足(Your account has insufficient balance)");
        //     } else {
        //         for (var i in PortalError) {
        //             if (data.error_msg.indexOf(i) >= 0) {
        //                 alert(PortalError[i]);
        //                 return false;
        //             }
        //         }
        //         alert(data.error_msg);
        //         return false;
        //     }
        //     return false;
        // });
        // return false;
    });

    $("#form3").submit(function(e) {
        e.preventDefault();
        var uname = $("#username"),
            uip = $("#user_ip");
        //logout  注销
        var pData = {
            "action": "logout",
            "username": uname.val(),
            "ac_id": GetQueryString('ac_id'),
            "ip": "",
            "double_stack": "1"
        };
        //$.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", pData, function(data) {});
        $.getJSON("/cgi-bin/srun_portal", pData, function(data) {
            if (data.error == "ok") {
//                if (data.client_ip.indexOf(":") >= 0) {
//                    $.getJSON(location.protocol + "//" + "auth4.tsinghua.edu.cn" + "/cgi-bin/srun_portal", pData, function (data) {});
//                }else {
//                    $.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", pData, function(data) {});
//                }
                //$.getJSON(location.protocol + "//" + location.hostname + "/cgi-bin/srun_portal", pData, function(data) {});
                // if (confirm("下线成功(Logoff Success)")){
                //     window.opener=null;
                //     window.open('','_self');
                //     window.close();
                // }
                alert("下线成功(Logoff Success)");
                location.href = location.protocol + "//" + location.hostname + "?noforward=1";
                return false;
            }
            for (var i in PortalError) {
                if (data.error_msg.indexOf(i) >= 0) {
                    alert(PortalError[i]);
                    return false;
                }
            }
            alert(data.error_msg);
            return false;
        });

        return false;
    });

    //phone
    $("#phone-form2").submit(function(e) {
        e.preventDefault();
        $this = $(this);
        var acid = $this.find("input[name=\"ac_id\"]"),
            uname = $this.find("input[name=\"username\"]"),
            pwd = $this.find("input[name=\"password\"]"),
            uip = $this.find("input[name=\"user_ip\"]");
        if (acid.val() == "" || acid.val() == "0") {
            alert("您打开的认证页面未经重定向,点击确定后将自动重定向到正确的页面。");
            location = "http://www.baidu.com";
            return false;
        }
        if (uname.val() == "") {
            alert("请填写用户名");
            uname.focus();
            return false;
        }

        if (pwd.val() == "") {
            alert("请填写密码");
            pwd.focus();
            return false;
        }

        // var save_me = 0;
        // if ($this.find("input[name=\"save_me\"]").is(':checked')) {
        //     save_me = 1;
        // }
        if ($('#cookie')[0].checked == false) {
            $.cookie("off_campus", "off", { expires: 30 });
            uname.val(uname.val()+"@tsinghua");
        } else {
            $.cookie("off_campus", null);
        }

        //login  认证
        var qData = {
            "action": "login",
            "username": uname.val(),
            "password": pwd.val(),
            "org_password": pwd.val(),
            "ac_id": acid.val(),
            "ip": "",
            "double_stack": "1"
        };
        //$.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
        $.getJSON("/cgi-bin/srun_portal", qData, function(data) {
            if ($('#cookie')[0].checked == false) {
                uname.val(uname.val().replace("@tsinghua", ''));
            }
            if (data.error == "ok") {
                $.cookie('access_token', data.access_token);
//                if (data.client_ip.indexOf(":") >= 0){
//                    $.getJSON(location.protocol + "//" + "auth4.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
//                }else {
//                    $.getJSON(location.protocol + "//" + "auth6.tsinghua.edu.cn" + "/cgi-bin/srun_portal", qData, function(data) {});
//                }
                //$.getJSON(location.protocol + "//" + location.hostname + "/cgi-bin/srun_portal", qData, function(data) {});
                var redirect = getUrlParam('userurl');
                if (redirect != ""){
                    location.href = redirect;
                } else {
                    if ($('#cookie')[0].checked == false) {
                        location.href = location.protocol + "//" + location.hostname + "/srun_portal_phone_succeed.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token + "&access=no";
                    }else {
                        location.href = location.protocol + "//" + location.hostname + "/srun_portal_phone_succeed.php?ac_id=" + acid.val() + "&username=" + data.username + "&ip=" + data.client_ip + "&access_token=" + data.access_token;
                    }
                }
                return false;
            }
            for (var i in PortalError) {
                if (data.error_msg.indexOf(i) >= 0) {
                    alert(PortalError[i]);
                    return false;
                }
            }
            alert(data.error_msg);
            return false;
        });
        return false;
    });

    $("#phone-form3").submit(function(e) {
        e.preventDefault();
        $this = $(this);
        var uip = $this.find("input[name=\"user_ip\"]");
        //logout  注销
        var pData = {
            "action": "logout",
            "username": $.cookie("uname"),
            "ac_id": GetQueryString('ac_id'),
            "ip": ""
        };
        $.getJSON(location.protocol + "//" + location.hostname + ":69/cgi-bin/srun_portal", pData, function(data) {
            if (data.error == "ok") {
                $.cookie('uname', null);
                $.cookie('access_token', null);
                location.href = location.protocol + "//" + location.hostname;
                return false;
            }
            return false;
        });
        return false;
    });
});
syimyuzya commented 6 years ago

@jiegec 咦我這才注意到「srun」、69 端口什麼的……這好像是之前校園網 PC 版客戶端也一直在使用的方式吧?(甚至在 2015 年校園網認證改版之前就在用的……)

……其實我這個腳本還有個「完整版」,srun 和 web 兩種方式都能用的……不過那版我只掛到了敝系科協的 git9 上(敝系科協服務器上用的應該也是默認 srun 的),Github 這版我把 srun 的方式砍掉了😂

所以現在大清的有線網是要全面用 srun 了麼……?

jiegec commented 6 years ago

不清楚。。现在的问题是我本机现在连不上net9.org的服务器了。。

jiegec commented 6 years ago

https://git.net9.org/syimyuzya/tunet-cli/blob/srun2015/tunetctl 找到了这个

jiegec commented 6 years ago

但这个和现在的auth也不一样了。。。

realconnor commented 6 years ago

注意还有auth6,现在紫荆不认证上不了IPv6了,为什么合并在一起呢?源代码倒是和auth4的一模一样,而且认证auth4还不能上v6网站,但是只认证auth6却能同时上v4和v6网站…可能是觉得有IPv6必有IPv4,否则不这样?

还有终端得到IPv6地址不像原先那样是结合MAC地址无状态生成的,而是疑似80位的前缀,这是什么鬼?不知道能不能支持DHCPv6-PD,感兴趣可以试试。我猜测如果支持DHCPv6,路由器分配全局IPv6地址,终端会验证到手发麻,所以现在安心用NAT6了。

我想这两处变动,能解释这几天宿舍的网时断时续了:( 确实在维护

jiegec commented 6 years ago

以前是SLAAC,现在上了DHCPv6.。药丸

yuantailing commented 6 years ago

http://its.tsinghua.edu.cn/ 上有命令行版认证程序,我简单包装了一下 https://github.com/yuantailing/tunet2018-auto ,也没考虑 IPv6。

😂😂😂 好吧,我刚也是苦逼地晚上跑到 FIT 楼去联网

yuantailing commented 6 years ago

另外搜了两个考虑了 auth 的,都是用 js 实现:

syimyuzya commented 6 years ago

@yuantailing 校園網現在認證已經這麼亂了麼😂

yuantailing commented 6 years ago

现在校园网有两步:

  1. 认证。认证后可以访问校内IP,否则只能访问 auth4.tsinghua.edu.cn(和 auth6),net、info、learn 都访问不了。
  2. 计费。就是 net。

认证这一步在东主楼还没有实施,宿舍区和 FIT 楼都实施了。

认证的 API 比较 net 要复杂:

  1. 发送一个 get 请求,获取下一步的 token,每次都会变化。
  2. 用这个 token 加密字符串 {username: username, password: password, ...}(像是稍加修改过的某加密算法)。加密算法里全是移位和异或,没有模,因此猜是一个对称加密算法。
  3. 密文、用户名、token、一些魔法数字,放一起算 MAC。(里面 base64.b64encode 算法都是篡改过的)
  4. 发送第二个 get 请求即可登录。

登出的 API 也是一样的。搞这么麻烦并没有用啊,如果是 https,直接明文传就可以了;如果不是 https,怎么加密都没用。

P.S. 只有计费可以在 usereg.tsinghua.edu.cn 上操作,认证只能本机操作。

jiegec commented 6 years ago

对,篡改过base64是最不清真的。所以我直接拿了他改过的js丢本地nodejs跑。

bnkrr commented 6 years ago

还有一点补充一下吧,“校外访问”就是直接发user和passwd,如果没有勾选“校外访问”,其实是在user后边加上@tsinghua发送。即user字段是user@tsinghua.这样就不会触发之后的登录校园网计费的那一步。 魔改了很多函数,纯python要重新实现,有点懒。不过好像已经有人做了。

Harry-Chen commented 6 years ago

P.S. 可以选择 https://github.com/z4yx/GoAuthing/ ,完整支持 net 和 auth P.P.S. 向网络部前辈问好(

twd2 commented 5 years ago

向网络部前辈问好