I'm not sure if my netfilter is working or not

352 views Asked by At

I'm trying to make a LKM netfilter that drops incoming packets if the number of packets arrived exceeds a certain limit.

There are five ports that the packets comes through, and netfiltering is done for each of those ports.

Here's part of my LKM netfilter (it uses procfs to write from user program):

#define MAX_PORT 5

static unsigned short int port[MAX_PORT];
static unsigned long limit;
static char char_limit[256];
static unsigned long data_count[MAX_PORT];

bool check_port(unsigned short int);

static unsigned int my_hook_fn( void *priv,
                struct sk_buff *skb,
                const struct nf_hook_state *state)
{
    struct iphdr *ip = ip_hdr(skb);
    struct tcphdr *th = tcp_hdr(skb);
    unsigned int source, dest;

    if(!skb) return NF_ACCEPT;

    if(ip->protocol==IPPROTO_TCP)
    {
        source = htons((unsigned short int) th->source);
        dest = htons((unsigned short int) th->dest);
        printk(KERN_ALERT "source: %u, destination: %u\n", source, dest);
        if(!check_port(source))
        {
            printk(KERN_ALERT "packet dropped!\n");
            return NF_DROP;
        }
    }
    return NF_ACCEPT;
}

bool check_port(unsigned short int source)
{
    int i = 0;
    bool found = false;
    while(!found && i < MAX_PORT)
    {
        if(port[i] == source)
            found = true;
        else if(port[i] == 0)
        {
            port[i] = source;
            found = true;
        }
        i++;
    }

    i--;
    data_count[i]++;

    if(data_count[i] >= limit)
    {
        data_count[i] = limit;
        printk(KERN_ALERT "port %hu has reached the limit!\n", port[i]);
        return false;
    }    
    return true;
}

static struct nf_hook_ops my_nf_ops = {
    .hook       = my_hook_fn,
    .pf         = PF_INET,
    .hooknum    = NF_INET_PRE_ROUTING,
    .priority   = NF_IP_PRI_FIRST,
};

In my hook function, the NF_DROP seems to be correctly returned.

However, the result in my user space program shows that it's not.

Next is my user space program; this produces results in txt files.

void *thread_recv(void *arg);

#define MAX_CON 5
#define BUF_SIZE 200

int port[MAX_CON];
char ip[20];
int sock[MAX_CON];

void error_handling(char *msg);  

void main(){
    int i;
    unsigned long limit;
    char char_limit[256];
    FILE *fp;
    printf("packet limit : ");
    scanf("%lu", &limit);
    sprintf(char_limit, "%lu", limit);
    fp = fopen("/proc/myproc/myproc", "w");

    if(fp == NULL)
        printf("unable to open myproc\n");
    else
        fprintf(fp, "%s", char_limit);

    fclose(fp);

    struct sockaddr_in serv_adr;  
    pthread_t thread_id[MAX_CON];
    printf("ip :\n");
    scanf("%s",ip);
    printf("<port> <port> <port> <port> <port>\n");

    scanf("%d %d %d %d %d", &(port[0]), &(port[1]), &(port[2]), &(port[3]), &(port[4]));
    printf("%s %d\n", ip, port[0]);

    for(i=0;i<5;i++){
        sock[i]=socket(PF_INET, SOCK_STREAM, 0);
        if(sock[i]==-1)
            error_handling("socket() error");
        memset(&serv_adr, 0, sizeof(serv_adr));
        serv_adr.sin_family=AF_INET;
        serv_adr.sin_addr.s_addr=inet_addr(ip);
        serv_adr.sin_port=htons(port[i]);

        if(connect(sock[i], (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
            error_handling("connect() error");
        else 
            printf("port %d connected\n", port[i]);

        pthread_create(&(thread_id[i]),NULL, thread_recv,(void*)&(sock[i]));    
    }
    while(1);   // do infinitely, so user should end by their own. Ctrl + C
}

void *thread_recv(void *arg){
    int clnt_sock= *(int*)arg;  // get socketnumber from main
    int str_len=0, i;       // recv byte length
    int tport=0;            // portnumber matching socketnumber
    char msg[BUF_SIZE];
    time_t timer;
    struct tm *t;
    struct timespec spec;
    unsigned long ms;
    FILE *fp;
    char filename[20]={NULL};

    for(i=0;i<5;i++)
        if(sock[i]==clnt_sock)
            tport=port[i];

    sprintf(filename,"%d.txt",tport);
    fp=fopen(filename,"w+");
    printf("%d port thread run\n", tport);

    while((str_len=read(clnt_sock, msg, sizeof(msg)))){
        msg[str_len]=NULL;
        timer= time(NULL);
        t= localtime(&timer);
        clock_gettime(CLOCK_REALTIME, &spec);
        ms = round(spec.tv_nsec / 1.0e6);
        fprintf(fp,"%d:%d:%d.%lu %d %s\n",t->tm_hour,t->tm_min,t->tm_sec,ms,str_len,msg);
    }
    fclose(fp);
}
void error_handling(char *msg){
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}

Within the thread_recv function, a txt file is created with its name as the matching port number.

What I was expecting from this was that once packet is dropped, the resulting txt file will stop being updated.

For example, if the limit is 10, then only 10 socket information will be written to the file.

But even when the ports have reached the limit, they keep updating the resulting txt files.

Does that mean that the packets have not been dropped properly?

0

There are 0 answers