A userspace application that filters DHCP floods to protect a DHCP server. It uses the Netfilter userspace packet queuing API.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <arpa/inet.h>
  4. #include <errno.h>
  5. #include "dp_nfqueue.h"
  6. #include "dp_accounting.h"
  7. #include "dp_blacklist.h"
  8. #include "dp_helpers.h"
  9. #include "dp_dhcpv4.h"
  10. #include "dp_dhcpv6.h"
  11. // start netfilter queue
  12. void dp_nfq_start(dp_conf *conf) {
  13. struct nfq_handle *h;
  14. struct nfq_q_handle *qh;
  15. int fd;
  16. if ( ( h = nfq_open() ) == NULL ) {
  17. fprintf(stderr,"error during nfq_open() %s\n", strerror(errno));
  18. return;
  19. }
  20. if ( ( qh = nfq_create_queue(h, conf->queue, &dp_callback, conf) ) == NULL ) {
  21. fprintf(stderr, "error during nfq_create_queue() %s\n", strerror(errno));
  22. return;
  23. }
  24. if ( nfq_set_mode(qh, NFQNL_COPY_PACKET, 1500) < 0 ) {
  25. fprintf(stderr,"error during nfq_set_mode() %s\n", strerror(errno));
  26. return;
  27. }
  28. if ( nfq_set_queue_flags(qh, NFQA_CFG_F_FAIL_OPEN, NFQA_CFG_F_FAIL_OPEN) < 0 ) {
  29. fprintf(stderr,"error during nfq_set_queue_flags() %s\n", strerror(errno));
  30. return;
  31. }
  32. fd = nfq_fd(h);
  33. while(1) {
  34. static char buf[65536];
  35. int rv;
  36. rv = recv(fd, buf, sizeof(buf), 0);
  37. switch(rv) {
  38. case -1:
  39. fprintf(stderr, "recv() error: %s\n", strerror(errno));
  40. return;
  41. case 0:
  42. fprintf(stderr,"socket is closed!?\n");
  43. return;
  44. default:
  45. // send packet to callback
  46. nfq_handle_packet(h, buf, rv);
  47. break;
  48. }
  49. }
  50. }
  51. // decode dhcp packet
  52. int dp_dhcp_check(struct nfq_data *nfa, dp_conf *conf) {
  53. unsigned char *pkt;
  54. int pktlen;
  55. int offset = 0;
  56. unsigned char *remoteid = NULL;
  57. int remoteidlen = 0;
  58. int rv = NF_ACCEPT;
  59. pktlen = nfq_get_payload(nfa, &pkt);
  60. if ( conf->debug ) printf("got a packet, len = %i\n", pktlen);
  61. // can we read the IP proto and IP header length ?
  62. if ( pktlen > 0 ) {
  63. uint8_t ipver;
  64. uint8_t ihl;
  65. ipver = pkt[offset];
  66. ipver >>= 4;
  67. ihl = pkt[offset];
  68. ihl &= 0x0f;
  69. if ( ipver == 4 ) {
  70. // jump to DHCPv4
  71. offset += ( ihl * 4 ) + 8;
  72. dp_dhcpv4_check(conf, pkt, pktlen, offset, &remoteid, &remoteidlen);
  73. }
  74. else if ( ipver == 6 ) {
  75. // jump to DHCPv6
  76. offset += 40 + 8;
  77. dp_dhcpv6_check(conf, pkt, pktlen, offset, &remoteid, &remoteidlen);
  78. }
  79. else {
  80. if ( conf->debug ) printf("not an IPv4 packet\n");
  81. goto end;
  82. }
  83. }
  84. if ( conf->debug ) printf("remoteidlen=%i\n",remoteidlen);
  85. if ( remoteidlen>0 ) {
  86. if ( conf->debug ) {
  87. int i;
  88. printf("remoteid: ");
  89. for(i=0; i<remoteidlen; i++)
  90. printf("%02x", remoteid[i]);
  91. printf("\n");
  92. }
  93. // count the packet, even when blacklisted.
  94. dp_accounting_add(conf, remoteid, remoteidlen);
  95. // check if already in the blacklist
  96. if ( dp_blacklist_check(conf, remoteid, remoteidlen) == NF_DROP )
  97. rv = NF_DROP;
  98. // check if it must be added to the blacklist
  99. else if ( dp_accounting_check(conf, remoteid, remoteidlen) == NF_DROP ) {
  100. dp_blacklist_add(conf, remoteid, remoteidlen);
  101. rv = NF_DROP;
  102. }
  103. }
  104. end:
  105. dp_accounting_cleanup(conf);
  106. dp_blacklist_cleanup(conf);
  107. return rv;
  108. }
  109. // netfilter queue callback
  110. int dp_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) {
  111. struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
  112. dp_conf *conf = (dp_conf*)data;
  113. int id = -1;
  114. int verdict;
  115. if ( ph ) {
  116. id = ntohl (ph->packet_id);
  117. if ( conf->debug ) printf ("received packet with id %d\n", id);
  118. }
  119. verdict = dp_dhcp_check(nfa, conf); /* Treat packet */
  120. // override decision for dryrun
  121. if ( conf->dryrun )
  122. verdict = NF_ACCEPT;
  123. return nfq_set_verdict(qh, id, verdict, 0, NULL); /* Verdict packet */
  124. }