You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

103 lines
2.3 KiB

/*****************************************************
* This code was compiled and tested on Ubuntu 18.04.1
* with kernel version 4.15.0
*****************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
static struct nf_hook_ops *nfho = NULL;
struct last_dns_reply {
int last_port;
int match_count;
};
struct last_dns_reply dns_info;
int response_thresh = 10;
static int handle_dns_resp(int cli_port, struct sock *sk) {
int safe_resp = 1;
printk(KERN_INFO "response headed for client port: %d, lp: %d, mc: %d\n", cli_port, dns_info.last_port, dns_info.match_count);
if (cli_port == dns_info.last_port) {
dns_info.match_count = dns_info.match_count + 1;
if (dns_info.match_count > response_thresh) {
printk(KERN_INFO "got dns port match count over thresh, so dropping response..\n");
safe_resp = 0;
}
} else {
dns_info.match_count = 0;
}
dns_info.last_port = cli_port;
return safe_resp;
}
static unsigned int hfunc(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
struct iphdr *iph;
struct udphdr *udph;
int safe_resp;
if (!skb)
return NF_ACCEPT;
iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_UDP) {
udph = udp_hdr(skb);
if (ntohs(udph->source) == 53) {
printk(KERN_INFO "handle dns response packet info..\n");
safe_resp = handle_dns_resp(udph->dest, skb->sk);
if (safe_resp) {
return NF_ACCEPT;
} else {
printk(KERN_INFO "dropping unsafe dns resp for client port: %d\n", udph->dest);
return NF_DROP;
}
}
}
else if (iph->protocol == IPPROTO_TCP) {
return NF_ACCEPT;
}
return NF_DROP;
}
static int __init LKM_init(void)
{
nfho = (struct nf_hook_ops*)kcalloc(1, sizeof(struct nf_hook_ops), GFP_KERNEL);
/* Initialize netfilter hook */
nfho->hook = (nf_hookfn*)hfunc; /* hook function */
nfho->hooknum = NF_INET_PRE_ROUTING; /* received packets */
nfho->pf = PF_INET; /* IPv4 */
nfho->priority = NF_IP_PRI_FIRST; /* max hook priority */
nf_register_net_hook(&init_net, nfho);
return 1;
}
static void __exit LKM_exit(void)
{
nf_unregister_net_hook(&init_net, nfho);
kfree(nfho);
}
module_init(LKM_init);
module_exit(LKM_exit);