Linux NFLOG - documentação, configuração de C

5

Vários locais diferentes (por exemplo, link ) recomendam o uso do módulo de firewall "NFLOG" do Linux para capturar pacotes gerados por um determinado UID assim:

# 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

Eu não consegui encontrar nenhuma documentação de como isso funciona exatamente (em particular, netfilter.org tem um monte de documentação de API de biblioteca mal escrita e, até onde eu sei, nada na semântica das regras reais de firewall no nível do kernel), então eu tenho várias perguntas:

  1. Existe alguma documentação maldita e onde ela está escondida?

  2. A coisa CONNMARK é realmente necessária? Ou seja, isso funcionaria tão bem?

    # 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
    
  3. É necessário ter o "ulogd" em execução para que isso funcione?

  4. Existe uma maneira de dizer ao kernel para escolher um número de grupo não alocado para mim e me dizer o que é?

  5. Existe uma maneira de dizer ao kernel que essas regras de filtragem devem ser excluídas automaticamente quando o processo X terminar? (O processo X não será executado como o uid 1000.)

  6. Presumivelmente, o comando iptables faz algumas chamadas ioctl especiais ou algo para configurar o firewall. Existe uma biblioteca C que pode ser usada para fazer o mesmo de dentro de um programa (ou seja, "processo X" de Q4)?

por zwol 08.07.2014 / 17:53

1 resposta

5

Is there any damn documentation and where is it hiding?

Existem exemplos no site netfilter que ajudam a explicar a funcionalidade. Aqui está uma função que escrevi no meu próprio código que configura o netfilter NFLOG.

Aqui estão os exemplos que eles fornecem: link

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);
  }
}

Is the CONNMARK thing actually necessary? That is, would this work just as well?

É desnecessário.

Is it necessary to have "ulogd" running for this to work?

Não - na verdade eu não uso este aplicativo.

Is there a way to tell the kernel to pick an unallocated group number for me and tell me what it is?

Não que eu saiba. Em qualquer caso, isso seria inútil se você tivesse a configuração de destinos NFLOG para HTTP, um para registrar pacotes descartados que eram FTP e um que estava verificando sequências SMTP. Nesse cenário, você não pode determinar qual regra está vinculada a qual grupo e, portanto, qual grupo deve ser ouvido.

Is there a way to tell the kernel that these filter rules should be automatically deleted when process X terminates? (Process X would not be running as uid 1000.)

Não, mas o kernel preenche um buffer apenas até o tamanho máximo e, em seguida, descarta os dados. Não representa um impacto no desempenho em termos de usar muita memória com regras não escutadas.

Presumably the iptables command makes some special ioctl calls or something to configure the firewall. Is there a C library that can be used to do the same from within a program (namely, "process X" from Q4)?

Não há biblioteca de netfilters que eu saiba que ajude a manipular as regras. Existe uma biblioteca controlada internamente que é usada em seu lugar.

IPtables herda um método bastante arcaico de falar com userspace - você abre um soquete de IP SOCK_RAW para se comunicar com ele. Isso será totalmente removido (como não faz sentido) com nftables que falarão sobre o netlink para fazer a mesma coisa.

    
por 08.07.2014 / 18:25