我不确定我的netfilter是否正常工作

时间:2016-12-24 14:35:55

标签: sockets tcp linux-kernel kernel-module procfs

我正在尝试制作一个LKM netfilter,如果到达的数据包数超过某个限制,它会丢弃传入的数据包。

数据包通过五个端口,并为每个端口完成netfiltering。

这是我的LKM netfilter的一部分(它使用procfs从用户程序写入):

#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,
};

在我的钩子函数中,似乎正确地返回了NF_DROP。

但是,我的用户空间程序中的结果显示它不是。

接下来是我的用户空间计划;这会在txt文件中产生结果。

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

在thread_recv函数中,创建一个txt文件,其名称为匹配的端口号。

我期待的是,一旦丢弃数据包,生成的txt文件将不再更新。

例如,如果限制为10,则只有10个套接字信息将写入文件。

但即使端口达到了限制,他们也会不断更新生成的txt文件。

这是否意味着数据包没有正确删除?

0 个答案:

没有答案