代码实现

1、修改配置文件读取流程,使之支持灰白名单配置。

2、增加灰白名单功能函数。

3、修改原有用户面代码,使之支持灰白名单配置。

1 修改配置文件读取流程,使之支持白名单配置:

1)、增加白名单配置文件,内容如下:

JSON EXAMPLE:

{
        "is_global": true,
        "dnn_binding_list": [
            "default",
            "internet"
        ],
        "domain_name_list": [
            "www.99cloud.net",
            "www.google.com"
        ],
        "enhanced_feature_list": [
            "header_enrichment"
        ]
}

XML EXAMPLE:

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <white_list_feature>
        <is_global>true</is_global>
        <dnn_binding_list>default</dnn_binding_list>
        <dnn_binding_list>internet</dnn_binding_list>
        <domain_name_list>www.99cloud.net</domain_name_list>
        <domain_name_list>www.google.com</domain_name_list>
        <enhanced_feature_list>header_enrichment</enhanced_feature_list>
    </white_list_feature>
</root>

2)、增加解析白名单配置的函数,该函数将解析配置并将内容存放到 upf_main_t um 全局变量中的 white_list_feature_type *white_list 成员中。

修改 upf_conf.h 文件:

// 解析白名单配置的函数

修改 upf_conf.c 文件:

//解析白名单配置的函数

2 在用户面增加白名单过滤处理:

1、增加白名单配置存放变量:

1)、修改 upf.h 文件中的 upf_main_t 结构体:

typedef struct
{
    /*……*/
    white_list_feature_type *white_list;
} upf_main_t;

2)、在 picohttpparser.h 文件中增加 white_list_feature 结构体:

#define WGLIST_HEADER_ENRICHMENT_FEATURE_STR "header_enrichment"
#define WGLIST_ANTI_CHEAT_FEATURE_STR "anti_cheat"

#define WGLIST_HEADER_ENRICHMENT_FEATURE_TYPE 1
#define WGLIST_ANTI_CHEAT_FEATURE_TYPE 2

typedef struct{
    u8     is_global;
    char * dnn_binding_list;
    char * domain_name_list;
    u8 * enhanced_feature_list;
}white_list_feature_type;

3)、增加 white_grey_list_features 函数,封装白名单检查步骤:

/*******************************************
* 函数功能   : 检查访问对象是否在灰/白名单中
* 函数参数   : dnn       - 访问目标网络
*             domain    - 访问目标域名
*             list_type - 灰名单/白名单
* 函数返回值 : 0         - 不在名单中
*             1         - 在名单中
*******************************************/
u8 check_white_grey_list (const char *dnn, const char *domain, const u8 list_type) {
    upf_main_t *um = &upf_main;
    u8 is_global = NULL;
    char * dnn_binding_list = NULL;
    char * domain_name_list = NULL;
    char * dnn_binding_str = NULL;
    char * domain_name_str = NULL;
    int hit = 0;

    switch (list_type) {
        case 1:
            is_global = um->grey_list_feature.is_global;
            dnn_binding_list = um->grey_list_feature.dnn_binding_list;
            domain_name_list = um->grey_list_feature.domain_name_list;
            enhanced_feature_list = um->grey_list_feature.enhanced_feature_list;
            break;
        case 2:
            is_global = um->white_list_feature.is_global;
            dnn_binding_list = um->white_list_feature.dnn_binding_list;
            domain_name_list = um->white_list_feature.domain_name_list;
            *enhanced_feature_list = 0x02;
            break;
        default:
            return 0;
    }

    if  ( !is_global && dnn ){ // 有配置指定 DNN
        vec_foreach(dnn_binding_str, dnn_binding_list){ // 遍历配置中的 DNN list
            if (strcmp(dnn, dnn_binding_str)){ // 有命中
                hit = 1;
                break;
            }
        }
    }

    if ( hit && domain ){ // DNN 命中,继续检查 domain 是否在名单中
        vec_foreach(domain_name_str, domain_name_list){ // domain list
            if (strcmp(domain, domain_name_str)){ // 有命中
                hit = 2;
                break;
            }
        }
        if (hit > 1){
            return 1;
        }
    }

    return 0;
}

2、修改 upf_process.c 文件中的 upf_process 函数,增加白名单功能实现流程:

image1

上图中红框部分修改为如下代码:

// 灰名单过滤
if ( um->grey_list ) {
    if ( upf_buffer_opaque (b)->upf.http ) {
        phr_parse_request (http, http_length, &method, &method_len, &path,&path_len, &minor_version, headers, &num_headers, 0);
        // 检查是否在灰名单中
        if ( check_grey_grey_list(dnn, domain, 1) ) {
            // 是否是欺诈包
            if ( upf_cheat_defense != -1) {
                next = DROP;
                goto trace;
            }
        }
    }else if ( upf_buffer_opaque (b)->upf.https_client_hello ) {
        // 检查是否在灰名单中
        if ( check_grey_grey_list(dnn, domain, 1) ) {
            // 是否是欺诈包
            if ( upf_cheat_defense != -1 ) {
                next = DROP;
                goto trace;
            }
        }
    }
}

// 白名单过滤
if ( um->white_list ) {
    if ( upf_buffer_opaque (b)->upf.http ) {
        // 检查是否在白名单中
        if ( check_grey_grey_list(dnn, domain, 2) ) {
            // 调用头增强功能
            upf_https_header_enrichment;
        }
    }else if ( upf_buffer_opaque (b)->upf.https_client_hello ) {
        // 检查是否在白名单中
        if ( check_grey_grey_list(dnn, domain, 2) ) {
            // 调用头增强功能
            upf_http_header_enrichment_pro;
        }
    }
}