Фильтр сокета NKE (MacOS): не может правильно повторно ввести выходные пакеты

У меня проблема в 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 и репозиторий пользовательских процессов.

Спасибо

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]