Tuesday, February 22, 2022

[SOLVED] Set CONNMARK in netfilter module

Issue

I have a netfilter module which hooks into NF_INET_LOCAL_OUT. In the hook function, I set the mark as follows:

if (tcp_header->syn && dport == 80) {
    skb->mark = 0x1;
}

However, this seems to set the mark only for this packet and not the connection mark.

  1. How do I set the connmark to 0x1 so that all packets in this flow have this mark?
  2. How do I access connmark for a packet in the hook function?

Thanks for your help.


Solution

NB: I am not a kernel network guru; I'm just good at reading the network code itself :)

Cribbing entirely from net/netfilter/xt_connmark.c in the latest version (4.15.8), try the following code:

if (tcp_header->syn && dport == 80) {
    skb->mark = 0x1;

    enum ip_conntrack_info ctinfo;
    struct nf_conn *ct;

    ct = nf_ct_get(skb, &ctinfo);
    if (ct != NULL) {
        u_int32_t newmark;

        newmark = 0x01;
        if (ct->mark != newmark) {
            ct->mark = newmark;
            nf_conntrack_event_cache(IPCT_MARK, ct);
        }
    }
}

Basically, in order to set the CONNMARK itself, you need to first get the actual conntrack entry for the flow. Once you've done that, you see if the current mark is already set to your new mark of 0x01. If it isn't, you set the mark and fire an event that the mark has been set.

You may want to look a bit more into connmark_tg, which is where this snippet is modified from; it may give you a bit more insight than just this code block alone.

Best of luck!



Answered By - Joel C
Answer Checked By - Terry (WPSolving Volunteer)