Фильтр сокета NKE (MacOS): не может правильно повторно ввести выходные пакеты - PullRequest
0 голосов
/ 02 июля 2018

У меня проблема в MacOS при использовании расширения ядра, которое должно фильтровать сетевой трафик.

  • Kext (через sftl_filter) начинает фильтровать все пакеты, и отправляет их процессу в пользовательском пространстве
  • Клиент выполняет некоторые операции (в этом случае он просто отправляет пакетные данные обратно в драйвер без изменений)
  • Драйвер повторно вводит модифицированный пакет обратно в сетевой поток

Входящие данные отлично работают. Однако загрузка данных размером более 500 КБ приводит к внезапно закрытому соединению. Небольшие файлы могут быть загружены без проблем. Это через любой протокол, протестированный на ftp, http, https и т. Д.

Упрощенный код драйвера:

errno_t tl_data_fn(void *cookie, socket_t so, const struct sockaddr *addr, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags, FilterSocketDataDirection direction) {     
    if (check_tag(data, gidtag, FILTER_TAG_TYPE, direction == FilterSocketDataDirectionIn ? IN_DONE : OUT_DONE)) {  
        return 0;  
    }  

    if (!cookie) return result;  

    filter_cookie *f_cookie = get_filter_cookie(cookie);  

    FilterNotification notification;   
    if (direction == FilterSocketDataDirectionIn) {  
        notification.event = FilterEventDataIn;  
    } else {  
        notification.event = FilterEventDataOut;  
    }  
    notification.socketId = (uint64_t)so;  
    notification.inputoutput.dataSize = (uint32_t)mbuf_pkthdr_len(*data);  

    mbuf_copydata(*data, offset, notification.inputoutput.dataSize, notification.inputoutput.data);  

    ctl_enqueuedata(f_cookie->ctl_ref, f_cookie->ctl_unit, &notification, sizeof(FilterNotification), CTL_DATA_EOR);  

    mbuf_freem(*data);  

    if (control != NULL && *control != NULL)  
        mbuf_freem(*control);  

    return EJUSTRETURN;  
}  

errno_t tl_data_in_fn(void *cookie, socket_t so, const struct sockaddr *from, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags) {  
    return tl_data_fn(cookie, so, from, data, control, flags, FilterSocketDataDirectionIn);  
}  

errno_t tl_data_out_fn(void *cookie, socket_t so, const struct sockaddr *to, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags) {  
    return tl_data_fn(cookie, so, to, data, control, flags, FilterSocketDataDirectionOut);  
}  



errno_t ctl_send(kern_ctl_ref ctl_ref, u_int32_t unit, void *unitinfo, mbuf_t m, int flags) {      
    FilterClientResponse response;  
    mbuf_copydata(m, 0, sizeof(response), &response);  

    mbuf_t data;  
    mbuf_allocpacket(MBUF_WAITOK, response.dataSize, NULL, &data);  
    mbuf_copyback(data, 0, response.dataSize, response.data, MBUF_WAITOK);  
    set_tag(&data, gidtag, FILTER_TAG_TYPE, response.direction == FilterSocketDataDirectionIn ? IN_DONE : OUT_DONE);  

    if (response.direction == FilterSocketDataDirectionIn) {  
        sock_inject_data_in((socket_t)response.socketId, NULL, data, NULL, 0);  
    } else {  
        sock_inject_data_out((socket_t)response.socketId, NULL, data, NULL, 0);  
    }  

    mbuf_freem(m);  
    return 0;  
}  
Функции

tl_data_in_fn и tl_data_out_fn используются в sftl_filter. ctl_send используется в kern_ctl_reg как ctl_send_func.

Код процесса упрощенного пользовательского пространства:

int s = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);  

//connect to driver  

FilterNotification notification;  
while (recv(s, &notification, sizeof(FilterNotification), 0) == sizeof(FilterNotification)) {  
    FilterClientResponse response;  
    response.socketId = notification.socketId;  
    response.direction = (notification.event == FilterEventDataIn) ? FilterSocketDataDirectionIn : FilterSocketDataDirectionOut;  
    response.dataSize = notification.inputoutput.dataSize;  
    memcpy(response.data, notification.inputoutput.data, notification.inputoutput.dataSize);  
    send(s, &response, sizeof(response), 0);  
}  

Буду признателен за любую помощь / совет. Kext и пользовательский репозиторий процессов .

Спасибо

...