FetchBannedIPs.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "FetchBannedIPs.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include "Debug.h"
  7. #include "IPTables.h"
  8. #include "DatabaseStuff.h"
  9. // Run this if the user sent in one parameter.
  10. void FetchBannedIPs::ProcessOneParameter(const char *argv1,bool useIpset)
  11. {
  12. if (strcasecmp(argv1,"LIST")==0) {
  13. ListCurrent(useIpset);
  14. return;
  15. }
  16. if (strcasecmp(argv1,"CLEAR")==0) {
  17. IPTables::ClearCurrent(useIpset);
  18. printf("Cleared.\n");
  19. return;
  20. }
  21. printf("Here's a list of IPs that need to be banned:\n");
  22. FetchAndBan(argv1,nullptr,false,0,useIpset);
  23. return;
  24. }
  25. // Run this if the user sent in two parameters.
  26. void FetchBannedIPs::ProcessTwoParameters(const char *argv1,const char *argv2,bool useIpset)
  27. {
  28. Tree<IPAddress> current_ips;
  29. do { // Loop only once
  30. if (strcasecmp(argv2,"LAST")==0) {
  31. ShowLastBannedTime(argv1);
  32. break;
  33. }
  34. if (strcasecmp(argv2,"IPSET")==0) {
  35. ProcessOneParameter(argv1,true);
  36. break;
  37. }
  38. if (strcasecmp(argv2,"BAN")==0) {
  39. if (!IPTables::ReadFromIptables(current_ips,useIpset,false)) {
  40. printf("Out of memory reading the list of IP addresses from %s\n",useIpset ? "ipset" : "iptables");
  41. break;
  42. }
  43. //current_ips = IPTables::ReadFromIptables(true,&duplicates,useIpset,false);
  44. FetchAndBan(argv1,&current_ips,true,0,useIpset);
  45. break;
  46. }
  47. if (strcasecmp(argv2,"BAN200")==0) {
  48. if (!IPTables::ReadFromIptables(current_ips,useIpset,false)) {
  49. printf("Out of memory reading the list of IP addresses from %s\n",useIpset ? "ipset" : "iptables");
  50. break;
  51. }
  52. //current_ips = IPTables::ReadFromIptables(true,&duplicates,useIpset,false);
  53. FetchAndBan(argv1,&current_ips,true,200,useIpset);
  54. //Node::FreeNodes(&current_ips);
  55. break;
  56. }
  57. printf("Argument 2 %s was not understood.\n",argv2);
  58. } while (false);
  59. return;
  60. }
  61. // Runs if the user sent three parameters.
  62. void FetchBannedIPs::ProcessThreeParameters(const char *argv1,const char *argv2,const char *argv3)
  63. {
  64. if (strcasecmp(argv3,"IPSET")==0) {
  65. ProcessTwoParameters(argv1,argv2,true);
  66. } else {
  67. printf("Argument 3 %s was not understood.\n",argv3);
  68. }
  69. return;
  70. }
  71. // Show a message telling the user how to use this program.
  72. void FetchBannedIPs::ShowHelpMessage()
  73. {
  74. printf("FetchBannedIPs V 1.8 reads banned IPs from a database and bans them on this server.\n");
  75. printf("It uses iptables, but if you add the IPSET parameter,it will use ipset.\n");
  76. printf("Examples:\n");
  77. printf("List banned IPs from the database: FetchBannedIPs 192.168.0.204\n");
  78. printf("Read the banned IPs from the database and ban them here:\n");
  79. printf("FetchBannedIPs 192.168.0.204 BAN\n");
  80. printf("Read the banned IPs from the database and ban them with ipset:\n");
  81. printf("FetchBannedIPs 192.168.0.204 BAN IPSET\n");
  82. printf("Read the banned IPs from the database and ban up to 200 of them here:\n");
  83. printf("FetchBannedIPs 192.168.0.204 BAN200\n");
  84. printf("Read the banned IPs from the database and ban up to 200 of them here with ipset:");
  85. printf("FetchBannedIPs 192.168.0.204 BAN200 IPSET\n");
  86. printf("List all the IPs banned in iptables: FetchBannedIPs LIST\n");
  87. printf("List the banned IPs from ipset: FetchBannedIPs LIST IPSET\n");
  88. printf("Clear all banned IPs from iptables: FetchBannedIPs CLEAR\n");
  89. printf("Clear the banned IPs from ipset: FetchBannedIPs CLEAR IPSET\n");
  90. printf("The iptables and ipset rules for the set name \"evil_hackers\" are automatically created if you use ipset.\n");
  91. printf("If you delete an ip from the database, ban will remove it from iptables/ipset.\n");
  92. printf("Calls banned.sp_get_new_banned(0) to get the list of IPs: [BannedID int,IP VARCHAR(20)]\n");
  93. printf("You can use an http or https url for the database IP.\n");
  94. printf("Last last modified date: FetchBannedIPs database LAST\n");
  95. return;
  96. }
  97. // List the current banned IPs from iptables.
  98. void FetchBannedIPs::ListCurrent(bool useIpset)
  99. {
  100. Tree<IPAddress> ipList;
  101. if (!IPTables::ReadFromIptables(ipList,useIpset,false)) {
  102. printf("Out of memory reading the list of IPs from %s.\n",useIpset ? "ipset" : "iptables");
  103. } else {
  104. for(auto loop = ipList.List.begin();loop != ipList.List.end();++loop) {
  105. printf("%s\n",(*loop)->IP);
  106. }
  107. }
  108. return;
  109. }
  110. void FetchBannedIPs::ShowLastBannedTime(const char *server)
  111. {
  112. const unsigned long BufferSize = 1024;
  113. char lastModified[BufferSize];
  114. lastModified[0] = 0;
  115. DatabaseStuff::GetLastBannedTime(server,lastModified,BufferSize);
  116. printf("%s\n",lastModified);
  117. }
  118. // Fetch banned IPs from the database and ban them.
  119. // server = database server
  120. // current_ips is the list of IPs from ipset or iptables.
  121. // actually_ban is to either display or actually ban them.
  122. // stop_count is to stop at a certain number if bans. 0 = unlimited.
  123. // If useIpset is true then ipset is used in addition to iptables.
  124. // if actually_ban is true and stop_count is 0 and useIpset is true then try to add the IPs all at once using ipset restore.
  125. void FetchBannedIPs::FetchAndBan(const char *server,Tree<IPAddress> *current_ips,bool actually_ban,int stop_count,bool useIpset)
  126. {
  127. int numberofsaves;
  128. Tree<IPAddress> ipsFromDatabase;
  129. std::forward_list<IPAddress*> difference;
  130. std::forward_list<IPAddress*> *ipsToBan; // current_ips == nullptr ? ipsFromDatabase.List : difference
  131. bool found;
  132. try
  133. {
  134. numberofsaves = 0;
  135. DatabaseStuff::GetIPsToBan(ipsFromDatabase,server);
  136. // Look for IPs to unban because they're not in the database any more.
  137. if ((!ipsFromDatabase.List.empty()) && (current_ips != nullptr) && (!current_ips->List.empty())) {
  138. // Only do this comparison if both lists have IP addresses.
  139. current_ips->Subtract(ipsFromDatabase,difference,IPAddress::Compare);
  140. if (!difference.empty()) {
  141. IPTables::ClearIPList(&difference,useIpset); // Clears a list of IPs from iptables or ipset.
  142. difference.clear();
  143. }
  144. }
  145. // Look for IPs to ban and ban them.
  146. if ((current_ips == nullptr) || (current_ips->List.empty())) {
  147. // Currently, nothing is banned. Ban all the IPs from the database.
  148. ipsToBan = &(ipsFromDatabase.List);
  149. } else {
  150. // Figure out which IPs are not already banned.
  151. if (!ipsFromDatabase.List.empty()) {
  152. ipsFromDatabase.Subtract(*current_ips,difference,IPAddress::Compare);
  153. }
  154. ipsToBan = &difference;
  155. }
  156. if (actually_ban && (stop_count == 0) && useIpset) {
  157. // Use faster shortcut.
  158. IPTables::BanIPsUsingRestore(*ipsToBan,true);
  159. } else {
  160. for(auto loop = ipsToBan->begin();loop != ipsToBan->end();++loop) {
  161. if (actually_ban) {
  162. IPTables::BanThisIP(**loop,useIpset);
  163. numberofsaves++;
  164. printf("Added %s\n",(*loop)->IP);
  165. {
  166. DEBUG;
  167. if ((stop_count > 0) && (numberofsaves > stop_count)) {
  168. // Run for a little over 3 minutes, then exit.
  169. printf("Stopped at %d.\n",stop_count);
  170. break;
  171. }
  172. if (stop_count > 0) {
  173. sleep(1); // Sleep 1 second.
  174. }
  175. }
  176. } else {
  177. printf("%s\n",(*loop)->IP);
  178. }
  179. }
  180. }
  181. } catch(const char *error) {
  182. printf(error);
  183. }
  184. }