Несколько разных мест (например, http://wiki.wireshark.org/CaptureSetup/NFLOG) рекомендуют использовать модуль межсетевого экрана Linux «NFLOG» для захвата пакетов, сгенерированных определенным UID, например:
# iptables -A OUTPUT -m owner --uid-owner 1000 -j CONNMARK --set-mark 1
# iptables -A INPUT -m connmark --mark 1 -j NFLOG --nflog-group 30
# iptables -A OUTPUT -m connmark --mark 1 -j NFLOG --nflog-group 30
# dumpcap -i nflog:30 -w uid-1000.pcap
Мне не удалось найти никакой документации о том, как именно это работает (в частности, netfilter.org
имеет много плохо написанной документации API библиотеки и, насколько я могу судить, ничего не говорит о семантике фактических правил брандмауэра на уровне ядра), поэтому у меня есть несколько вопросов:
Является там какая блин документация и где она прячется?
Действительно ли необходима вещь CONNMARK? То есть будет ли это работать так же хорошо?
# iptables -A INPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30
# iptables -A OUTPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30
Обязательно ли запускать "ulogd", чтобы это работало?
Есть ли способ указать ядру выбрать для меня нераспределенный номер группы и сообщить мне, что это такое?
Есть ли способ сообщить ядру, что эти правила фильтрации должны автоматически удаляться при завершении процесса X? (Процесс X будет не работать как uid 1000.)
Предположительно iptables
команда делает некоторые особенные ioctl
звонки или что-то настроить брандмауэр. Есть ли библиотека C, которую можно использовать для того же самого из программы (а именно, «процесс X» из Q4)?
Есть какая-то блин документация и где она прячется?
На сайте netfilter есть примеры, которые помогают объяснить функциональность. Вот функция, которую я написал в собственном коде, которая устанавливает сетевой фильтр NFLOG.
Вот примеры, которые они предоставляют: http://www.netfilter.org/projects/libnetfilter_log/doxygen/files.html
void setup_netlogger_loop(
int groupnum,
queue_t queue)
{
int sz;
int fd = -1;
char buf[BUFSZ];
/* Setup handle */
struct nflog_handle *handle = NULL;
struct nflog_g_handle *group = NULL;
memset(buf, 0, sizeof(buf));
/* This opens the relevent netlink socket of the relevent type */
if ((handle = nflog_open()) == NULL){
sd_journal_perror("Could not get netlink handle");
exit(EX_OSERR);
}
/* We tell the kernel that we want ipv4 tables not ipv6 */
if (nflog_bind_pf(handle, AF_INET) < 0) {
sd_journal_perror("Could not bind netlink handle");
exit(EX_OSERR);
}
/* Setup groups, this binds to the group specified */
if ((group = nflog_bind_group(handle, groupnum)) == NULL) {
sd_journal_perror("Could not bind to group");
exit(EX_OSERR);
}
if (nflog_set_mode(group, NFULNL_COPY_PACKET, 0xffff) < 0) {
sd_journal_perror("Could not set group mode");
exit(EX_OSERR);
}
if (nflog_set_nlbufsiz(group, BUFSZ) < 0) {
sd_journal_perror("Could not set group buffer size");
exit(EX_OSERR);
}
if (nflog_set_timeout(group, 1500) < 0) {
sd_journal_perror("Could not set the group timeout");
}
/* Register the callback */
nflog_callback_register(group, &queue_push, (void *)queue);
/* Get the actual FD for the netlogger entry */
fd = nflog_fd(handle);
/* We continually read from the loop and push the contents into
nflog_handle_packet (which seperates one entry from the other),
which will eventually invoke our callback (queue_push) */
for (;;) {
sz = recv(fd, buf, BUFSZ, 0);
if (sz < 0 && errno == EINTR)
continue;
else if (sz < 0)
break;
nflog_handle_packet(handle, buf, sz);
}
}
Действительно ли необходима вещь CONNMARK? То есть будет ли это работать так же хорошо?
В этом нет необходимости.
Обязательно ли запускать "ulogd", чтобы это работало?
Нет - вообще-то я не использую его в этом приложении.
Есть ли способ указать ядру выбрать для меня нераспределенный номер группы и сообщить мне, что это такое?
Не то, чтобы я знаю. В любом случае это будет бесполезно, если у вас настроены целевые объекты NFLOG для HTTP, один для регистрации отброшенных пакетов, которые были FTP, и один, который сканировал строки SMTP. В этом сценарии вы не можете определить, какое правило привязано к какой группе, и, следовательно, какую группу следует прослушивать.
Есть ли способ сообщить ядру, что эти правила фильтрации должны автоматически удаляться при завершении процесса X? (Процесс X не будет работать с uid 1000.)
Нет, но ядро заполняет буфер только до максимального размера, после чего данные отбрасываются. Это не влияет на производительность с точки зрения использования слишком большого количества памяти из-за того, что правила не соблюдаются.
Предположительно команда iptables выполняет какие-то специальные вызовы ioctl или что-то еще для настройки брандмауэра. Есть ли библиотека C, которую можно использовать для того же самого из программы (а именно, «процесс X» из Q4)?
Насколько мне известно, нет библиотеки netfilter, которая помогает вам управлять правилами. Однако вместо этого используется внутренняя библиотека.
IPtables наследует довольно архаичный метод общения с пользовательским пространством - вы открываете IP-сокет SOCK_RAW для связи с ним. Это будет полностью удалено (поскольку в этом нет смысла) с помощью nftables, который будет говорить по netlink, чтобы делать то же самое.
Конкретно отвечая на эту часть:
Действительно ли необходима вещь CONNMARK? То есть будет ли это работать так же хорошо?
# iptables -A INPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30 # iptables -A OUTPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30
да, Это необходимо. Нет, ваше предложение не соответствует ни одному входящему пакету (возможно, оно соответствует трафику на локальном компьютере, но определенно не соответствует внешнему сетевому трафику).
Только локальные исходящие пакеты имеют связанного владельца. В начале цепочки INPUT информация о владельце недоступна, поскольку пакет все еще маршрутизируется. Чтобы сопоставить входящие пакеты, относящиеся к исходящему потоку, необходимо отметить «соединение» в цепочке OUTPUT, которое впоследствии может быть сопоставлено в цепочке INPUT.
См. Также iptables-extensions
страница руководства:
владелец
В
owner
модуль соответствует только исходным сокетам. Это означаетЭтот модуль пытается сопоставить различные характеристики создателя пакетов для локально сгенерированных пакетов. Это совпадение действительно только в цепочках OUTPUT и POSTROUTING. Перенаправленные пакеты не имеют связанных с ними сокетов. Пакеты из потоков ядра имеют сокет, но обычно не имеют владельца.
(То же самое относится и к nftables.)