Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve DoS Protection with Lua Script for Efficient IP Blocking #27

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ChanThien3101
Copy link

@ChanThien3101 ChanThien3101 commented Nov 26, 2024

This version utilizes a Lua Script to write IP addresses into the blockListIP.txt file, ensuring that IP blocking functions effectively across all ModSecurity threads when mitigating denial-of-service (DoS) attacks. This approach optimizes protection and minimizes delays in applying new IP blocking rules.
I have modified this rule based on your original implementation. The addition of writing IP addresses to the blocklist was made because I noticed that the previous rule did not effectively block IPs when they changed their port. With my implementation, this issue has been fully resolved. However, as my work builds upon your original rule, feel free to contact me if there are any questions or further requirements.

This version utilizes a Lua Script to write IP addresses into the blockListIP.txt file, ensuring that IP blocking functions effectively across all ModSecurity threads when mitigating denial-of-service (DoS) attacks. This approach optimizes protection and minimizes delays in applying new IP blocking rules.
@ChanThien3101 ChanThien3101 changed the title Improve DoS Protection with Lua Script for Dynamic IP Blocking Improve DoS Protection with Lua Script for Efficient IP Blocking Nov 26, 2024
@theseion
Copy link
Contributor

Thanks @ChanThien3101. We'll review your plugin.
@azurit, could I get your Lua eyes to take a peek as well?

@theseion theseion self-assigned this Nov 27, 2024
@azurit
Copy link
Member

azurit commented Nov 27, 2024

@ChanThien3101 First of all, you have put all rules into file dos-protection-config.conf. This is not how plugins should be written. File ending with -config.conf is only for configuration rules. Please fix this and split rules info files -config.conf, -before.conf and -after.conf. Then i will look at it again. Thanks.

@dune73
Copy link
Member

dune73 commented Nov 27, 2024

Thanks for contributing a plugin. This is very welcome. Especially in this area where CRS has removed functionality for CRS4.

Yet I have a few question marks around your implementation. Namely how it behaves under heavy load (-> DDoS).

I do not see any write-lock functionality on the code level and I would be interested to see how thousands of threads behave when they want to write into your txt file at the same time.

Also the read loop over the file implemented via 9514910 is likely to slow down non-attacking requests and bringing the server down in a DDoS situation.

This will need some real world testing (or very good simulation of DDoS).

@ChanThien3101
Copy link
Author

Apologies for the delayed response. I had received your feedback earlier, but I have had the chance to reply until now because I've been tied up with some work at my university. To be honest, I am currently a final-year student and working on my graduation project, which is related to yours ModSecurity.
Thank you very much for your valuable feedback. I am in the process of addressing the points you raised, and I will notify you once I have successfully implemented the changes in the shortest time possible.

@dune73
Copy link
Member

dune73 commented Nov 29, 2024

Thank you for the update!

@ChanThien3101
Copy link
Author

Hello!
I have made some modifications to my code for use with rule 9514910, incorporating two write-locking methods: save_ip_to_blocklist.lua (which may not be fully optimized for performance) and save_ip_to_blocklist_flock.lua, which uses flock for file locking. Additionally, I use get_blocklist_ip.lua to read IPs from the blocklistip.txt file. The reason for this is that when ModSecurity starts, new IPs are only added to the file if detected as DDoS. To block an IP, it must be read from the file, as this is the only way to ensure that newly added IPs are processed.

Since ModSecurity operates in a multithreaded environment, it’s quite challenging to load all IPs into memory for optimal performance. While this approach may not be the most efficient for DDoS protection, my plugin can still contribute to DDoS mitigation if someone wishes to try it and combine it with ModSecurity for small-scale implementations.

Additionally, if you prefer not to use the blocklist method for IP blocking, I have implemented a second approach that combines ModSecurity with iptables and utilizes ipset to block IPs at the network level. With this method, once ModSecurity detects an IP involved in a DDoS attack, it will immediately call add_ip_to_ipset.lua to add the IP to ipset (see rules 9514151 or 9514153). For more details on the implementation, please refer to the readme.md.

@ChanThien3101
Copy link
Author

This may be my final update for now. If you believe my plugin can be successfully implemented, please accept the pull request on GitHub, and I will continue developing it in the future. Thank you!

README.md Outdated
@@ -26,6 +26,7 @@ maps the regular CRS IDs from 900K for each rule to the range 9,900,000 - 9,999,
| phpbb-rule-exclusions | 9,512,000 - 9,512,999 | [coreruleset/phpbb-rule-exclusions-plugin](https://github.com/coreruleset/phpbb-rule-exclusions-plugin) | official | ✅ tested | ![Integration tests](https://github.com/coreruleset/phpbb-rule-exclusions-plugin/actions/workflows/integration.yml/badge.svg) |
| phpmyadmin-rule-exclusions | 9,513,000 - 9,513,999 | [coreruleset/phpmyadmin-rule-exclusions-plugin](https://github.com/coreruleset/phpmyadmin-rule-exclusions-plugin) | official | ✅ tested | ![Integration tests](https://github.com/coreruleset/phpmyadmin-rule-exclusions-plugin/actions/workflows/integration.yml/badge.svg) |
| dos-protection-modsecurity | 9,514,000 - 9,514,999 | [coreruleset/dos-protection-plugin-modsecurity](https://github.com/coreruleset/dos-protection-plugin-modsecurity) | official | untested | |
| dos-protection-modsecurity-vr2 | 9,514,000 - 9,514,999 | [ChanThien3101/plugin-dos-protection-modsecurity](https://github.com/ChanThien3101/plugin-dos-protection-modsecurity.git)| 3rd party | | |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use an unused range. The next range would be 9,523,000 - 9523,999.

@ChanThien3101
Copy link
Author

Hello @theseion
Thank you for your feedback. I have made the requested changes regarding the rule ID range and updated the code accordingly. The new range now follows the suggested 9,523,000 - 9,523,999 range.
Please review the updated pull request, and feel free to let me know if further modifications are needed.

@azurit
Copy link
Member

azurit commented Dec 4, 2024

@ChanThien3101 Sending my initial comments:

  • Remove .git suffix from URL.
  • None of your current rules in dos-protection-config.conf should be there. This file is supposed to contain only configuration rules which are intended for users to do a plugin configuration. See other plugins for inspiration.
  • Rules 9523920 and 9523930 looks like a configuration rules. If so, move them into file dos-protection-config.conf.
  • Make lua variable blocklist_file configurable using configuration rule in dos-protection-config.conf.
  • Do a flock inside lua and not using os.execute(), see here.
  • Rewrite comments into english language.
  • For IPset, run sudo ipset command directly, that 'proxy' bash script is not needed.

Also, consider using SQLite instead of a simple txt file - this will also resolve the locking problem.

@ChanThien3101
Copy link
Author

@azurit
Thank you for your detailed feedback! I have addressed the points as follows:

  • Removed .git suffix from the URL: The unnecessary .git suffix has been removed.
  • Updated dos-protection-config.conf: All unrelated rules have been removed. The configuration file now contains only configuration rules intended for user plugin configuration, as per the guidelines.
  • Made blocklist_file configurable: The Lua variable blocklist_file is now configurable using a rule in dos-protection-config.conf.
  • Implemented flock within Lua: Replaced the os.execute() method with native flock implementation directly in the Lua script for better performance and security.
  • Translated comments into English: All comments in the codebase have been rewritten in English to maintain consistency and clarity.
  • Simplified IPset command: Removed the 'proxy' bash script. The script now runs the sudo ipset command directly as recommended.
    Regarding the suggestion to use SQLite as a replacement, I plan to implement it in a future update.
    If there are any further improvements or additional suggestions, please feel free to let me know. Thank you for helping enhance the project!

@ChanThien3101
Copy link
Author

@theseion What do you all think of my plugin? Please provide me with your feedback.

README.md Outdated Show resolved Hide resolved
@theseion
Copy link
Contributor

theseion commented Jan 3, 2025

Ping @azurit

Co-authored-by: Max Leske <250711+theseion@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants