#######DNS部分########
//dns全局配置
dns::Global {
    dns_listen = 0.0.0.0:6653;
    cachePath = /dev/null;
}
//dns分流，httpDNS解析速度快，但是只支持解析A记录(ipv4)，acl顺序从上往下
dnsAcl {
    destAddr = 210.22.247.196:8090;
    header_host = 119.29.29.29:80;
    httpMod = http_replace_auth;
    //查询A/AAAA记录才使用httpDNS
    query_type = A;
    query_type = AAAA;
}
dnsAcl {
    destAddr = 210.22.247.196:8091;
    header_host = 223.5.5.5:53;
    tunnel_proxy = on;
    tunnelHttpMod = http_replace_auth;
    lookup_mode = tcpdns;
}




#######UDP部分########
httpUDP::udp {
    //如果搭建了clns服务器可以删除下一行的注释
    //destAddr = 210.22.247.196:8091;
    udp_tproxy_listen = 0.0.0.0:6650;
    encrypt = 加密密码;
    header_host = 服务器IP:服务器端口;
    httpMod = http_replace_auth;
}




#######TCP部分########
tcp::Global {
    tcp_listen = 0.0.0.0:6650;
    //----------------免流host----------------//
    ml_host = dns.weixin.qq.com;
}

//设置请求头中的Q-GUID  Q-TOKEN，执行顺序从上往下
httpMod::http_replace_auth {
    del_line = Q-GUID;
    del_line = Q-Token;
    //将"\n\r"替换为"\nQ-GUID: [GUID]\r\nQ-TOKEN: [TOKEN]\r\n\r"
    //一个http请求头只有一处包含有\n\r，那就是结尾处的\r\n\r\n，所以先删除q-guid,q-token，再在结尾加上就可以了
    strrep = "\n\r" -> "\nQ-GUID: [GUID]\r\nQ-TOKEN: [TOKEN]\r\n\r";
}
//配置核心自己的CONNECT请求头，指定服务器为pros.cutebi.taobao69.cn:80
httpMod::dynamic_api {
    set_first = "CONNECT pros.cutebi.taobao69.cn:80 HTTP/1.1\r\n";
}


//这个配置POST代理
tcpProxy::http_POST_proxy {
    //可以同时使用多个IP
    destAddr = 210.22.247.196:8090;
    httpMod = http_replace_auth;
}
//QQ浏览器8090 8091只改变IP
tcpProxy::QQBrowse_8090 {
    destAddr = 210.22.247.196:8090;
}
tcpProxy::QQBrowse_8091 {
    destAddr = 210.22.247.196:8091;
}
//这个配置tunnel代理
tcpProxy::tunnel_proxy {
    destAddr = 210.22.247.196:8091;
    tunnelHttpMod = http_replace_auth;
    tunnel_proxy = on;
}
//这个配置CONNECT的tunnel代理
tcpProxy::CONNECT_tunnel_proxy {
    destAddr = 210.22.247.196:8091;
    tunnel_proxy = httpOverTunnel;
    tunnelHttpMod = http_replace_auth;
}
//这个配置代理核心发出去的http请求
tcpProxy::dynamic_api_proxy {
    destAddr = 210.22.247.196:8091
    tunnel_proxy = on;
    tunnelHttpMod = dynamic_api;
}


/*
    QQ浏览器的tcpAcl比较复杂，是clnc的缺点但也是其强大之处，其他核心想要实现完美的代理必须直接写在源码里，没有这么灵活:
        首先要解决下载/上传验证的时候也可以免流
        然后就是部分http使用8090端口无法代理(通过tunnel，也就是CONNECT代理http可解决)
        再之后就是不能所有http都通过CONNECT代理(POST跟CONNECT不能再加一层CONNECT处理)
        最后还要同时在本地抓取Q-Token，抓取的时候只改变IP而不修改请求(不修改请求只是不做无用功)
    tcpAcl处理流程:
        一、执行顺序从上往下，matchMode = firstMatch优先。所以先执行tcpAcl::dynamic_api，这个只判断IP是否为127.0.0.3，如果匹配成功，则不再执行ACL，使用进行代理
        二、执行tcpAcl::firstConnect，端口不为8090-8091，则先不再匹配ACL，使用tcpProxy::tunnel_proxy先进行代理(因为reMatch语法，所以还需要匹配一次数据)
            1.当收到客户端发送的请求时，执行tcpAcl::http_POST和tcpAcl::http_CONNECT(reMatch语法);
                (1)如果匹配成功，则更换匹配成功的ACL为tcpAcl::http_POST或者tcpAcl::http_CONNECT
                (2)如果匹配不成功，则继续使用tcpAcl::firstConnect处理
        三、如果(一)(二)都匹配不成功，则执行tcpAcl::token_8091，continue_match语法规定8091端口匹配通过还继续匹配，hdr_key(Q-TOKEN) = .表示只要请求头中包含Q-Token头就匹配成功
            1.匹配成功使用tcpProxy::QQBrowse_8091
        四、如果(一)(二)(三)都匹配不成功，则执行tcpAcl::token_8090，匹配流程同(三)，只不过tcpProxy = QQBrowse_8090
        五、tcpAcl执行结束。前面这几个tcpAcl已经匹配了所有TCP可能的情况，所以tcpAcl::http_POST/tcpAcl::http_CONNECT只能有reMatch或者include_module语法指定来执行
*/


//核心自身的动态api通过CONNECT代理
tcpAcl::dynamic_api {
    tcpProxy = dynamic_api_proxy;
    //执行顺序提前，与客户端建立连接后就开始执行的acl
    matchMode = firstMatch;
    dst_ip = 127.0.0.3;
}
//默认连接到TUNNEL代理，降低延迟
tcpAcl::firstConnect {
    matchMode = firstMatch;
    tcpProxy = tunnel_proxy;
    //CONNECT跟POST请求，不能经过核心加一层CONNECT代理
    reMatch = http_POST https_CONNECT;

    dst_port != 8090:8091;
}
//QQ浏览器的8090 8091只改变IP
tcpAcl::token_8091 {
    tcpProxy = QQBrowse_8091;
    continue: dst_port = 8091;
    hdr_key(Q-TOKEN) = .;
}
tcpAcl::token_8090 {
    tcpProxy = QQBrowse_8090;
    continue: dst_port = 8090;
    hdr_key(Q-TOKEN) = .;
}
tcpAcl::http_POST {
    tcpProxy = http_POST_proxy;
    method = POST;
}
tcpAcl::https_CONNECT {
    tcpProxy = CONNECT_tunnel_proxy;
    method = CONNECT;
}



//用于接收socks5请求
socks5::recv_socks5 {
    socks5_listen = 0.0.0.0:1081;
    socks5_dns = 127.0.0.1:6653;
    handshake_timeout = 60;
}