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

2 years ago
  1. /*****************************************************
  2. * This code was compiled and tested on Ubuntu 18.04.1
  3. * with kernel version 4.15.0
  4. *****************************************************/
  5. #include <linux/init.h>
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/netfilter.h>
  9. #include <linux/netfilter_ipv4.h>
  10. #include <linux/ip.h>
  11. #include <linux/tcp.h>
  12. #include <linux/udp.h>
  13. static struct nf_hook_ops *nfho = NULL;
  14. struct last_dns_reply {
  15. int last_port;
  16. int match_count;
  17. };
  18. struct last_dns_reply dns_info;
  19. int response_thresh = 10;
  20. static int handle_dns_resp(int cli_port, struct sock *sk) {
  21. int safe_resp = 1;
  22. printk(KERN_INFO "response headed for client port: %d, lp: %d, mc: %d\n", cli_port, dns_info.last_port, dns_info.match_count);
  23. if (cli_port == dns_info.last_port) {
  24. dns_info.match_count = dns_info.match_count + 1;
  25. if (dns_info.match_count > response_thresh) {
  26. printk(KERN_INFO "got dns port match count over thresh, so dropping response..\n");
  27. safe_resp = 0;
  28. }
  29. } else {
  30. dns_info.match_count = 0;
  31. }
  32. dns_info.last_port = cli_port;
  33. return safe_resp;
  34. }
  35. static unsigned int hfunc(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
  36. {
  37. struct iphdr *iph;
  38. struct udphdr *udph;
  39. int safe_resp;
  40. if (!skb)
  41. return NF_ACCEPT;
  42. iph = ip_hdr(skb);
  43. if (iph->protocol == IPPROTO_UDP) {
  44. udph = udp_hdr(skb);
  45. if (ntohs(udph->source) == 53) {
  46. printk(KERN_INFO "handle dns response packet info..\n");
  47. safe_resp = handle_dns_resp(udph->dest, skb->sk);
  48. if (safe_resp) {
  49. return NF_ACCEPT;
  50. } else {
  51. printk(KERN_INFO "dropping unsafe dns resp for client port: %d\n", udph->dest);
  52. return NF_DROP;
  53. }
  54. }
  55. }
  56. else if (iph->protocol == IPPROTO_TCP) {
  57. return NF_ACCEPT;
  58. }
  59. return NF_DROP;
  60. }
  61. static int __init LKM_init(void)
  62. {
  63. nfho = (struct nf_hook_ops*)kcalloc(1, sizeof(struct nf_hook_ops), GFP_KERNEL);
  64. /* Initialize netfilter hook */
  65. nfho->hook = (nf_hookfn*)hfunc; /* hook function */
  66. nfho->hooknum = NF_INET_PRE_ROUTING; /* received packets */
  67. nfho->pf = PF_INET; /* IPv4 */
  68. nfho->priority = NF_IP_PRI_FIRST; /* max hook priority */
  69. nf_register_net_hook(&init_net, nfho);
  70. return 1;
  71. }
  72. static void __exit LKM_exit(void)
  73. {
  74. nf_unregister_net_hook(&init_net, nfho);
  75. kfree(nfho);
  76. }
  77. module_init(LKM_init);
  78. module_exit(LKM_exit);