Configuring nflog documentation in Linux using C programming language

I have inquiries regarding Linux groups. Is there a maximum number of groups that a user can establish? Additionally, would considerable amounts of groups and users impact the system’s performance?


Numerous sources, including, suggest utilizing the “NFLOG” firewall module in Linux to capture packets produced by a specific 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

Despite my efforts, I couldn’t find any clear documentation on the precise operation of this (specifically, the poorly-drafted library API documentation of

provides no insight into the semantics of the kernel-level firewall rules). As a result, I have a number of inquiries.

  1. Is

    there any **** documentation and where is it hiding?

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

    # 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. Is it necessary to have ”
    ” running for this to work?

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

  5. Is there a way to tell the kernel that these filter rules should be automatically deleted when process X
    terminates? (Process
    X would


    be running as
    uid 1000

  6. Presumably the


    command makes some special


    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)?

Solution 1:

Where can I find documentation regarding this?

The netfilter site offers explanatory examples of its functionality. Additionally, in my own code, I have written a function that configures the netfilter NFLOG.

The following link contains the examples provided:

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");
  /* 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");
  /* Setup groups, this binds to the group specified */
  if ((group = nflog_bind_group(handle, groupnum)) == NULL) {
    sd_journal_perror("Could not bind to group");
  if (nflog_set_mode(group, NFULNL_COPY_PACKET, 0xffff) < 0) {
    sd_journal_perror("Could not set group mode");
  if (nflog_set_nlbufsiz(group, BUFSZ) < 0) {
    sd_journal_perror("Could not set group buffer size");
  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)
    else if (sz < 0)
    nflog_handle_packet(handle, buf, sz);

Is the usage of CONNMARK indispensable? In other words, could this function equally without it?

It is unnecessary.

Does the functionality require the presence of “ulogd”?

Actually, I don’t utilize it for this particular purpose.

Can the kernel be instructed to select an unassigned group number and inform me of its value?

To my knowledge, it would be pointless to do so if NFLOG targets are configured for HTTP and separate ones for logging dropped FTP packets and detecting SMTP strings. This situation makes it impossible to identify which rule belongs to which group and which group needs to be monitored.

Is it possible to inform the kernel to automatically remove the filter rules upon the termination of process X, which would operate under a different user ID than 1000?

The kernel has a maximum buffer size, and once filled, it will discard any additional data. However, this does not affect performance or memory usage when rules are not being listened to.

It is assumed that the
iptables command
utilizes specific ioctl calls to set up the firewall. Is there a C library available to enable programmatic configuration of the firewall, specifically for “process X” mentioned in Q4?

To my knowledge, there isn’t any netfilter library available that facilitates the modification of rules. However, an alternative library with internal functionality is used as a substitute.

The communication method used by IPtables to interact with userspace is outdated. It involves opening a SOCK_RAW IP socket, which will be replaced by a more modern approach with nftables. The new method will involve speaking over netlink to achieve the same result.

Solution 2:

Specifically answering this part:

Is the utilization of CONNMARK really essential or can this alternative approach suffice?

# 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

It is indeed required, but your suggestion wouldn’t correspond to any inbound packets. It might work for traffic within the device, but it wouldn’t apply to external network traffic.

local, outgoing
packets are linked to an owner. During the initial phase of the INPUT chain, the owner details are not yet accessible as the packet is still in the process of being routed. To identify incoming packets that correspond to an outgoing flow, it becomes imperative to label the “connection” in the OUTPUT chain. This labeling can later be used to match the packets in the INPUT chain.

Additionally, refer to the manual page for




The sockets that originate
module matches
can only use


. Therefore, other sockets cannot use



The purpose of this module is to identify the characteristics of the packet creator for locally generated packets. It only applies to the OUTPUT and POSTROUTING chains. Forwarded packets lack a socket association, while packets from kernel threads usually have no owner but do possess a socket.

The aforementioned caution also pertains to nftables.

Frequently Asked Questions