BlackDemonZyT / BotSentry

Official repository for Bot-Sentry issues, information, etc..
5 stars 0 forks source link

Adding whitelist shell commands (on par with blacklist shell commands) #75

Open Hegezcc opened 2 years ago

Hegezcc commented 2 years ago

As we currently have a configuration option (blacklist.firewall) to run shell commands on blacklisting IP addresses, could we also have an option for running shell commands when user is added to whitelist?

That would allow me to do complicated stuff with whitelisting on my firewall: normal user logging in and getting kicked due to not being in whitelist does not actually send so much traffic for very long, so it would allow me to set more flexible traffic limits for a whitelisted address (and the relaxation would happen in real-time, as usually players just reconnect after reading the initial whitelist addition message). Currently the whitelist/blacklist file only updates the freshly-added IP addresses on plugin reload/disable, so we could not even use inotify-tools to read updates.

Moreover, I'd very much like to alter the configuration to do my own logic with firewalling (e.g. adding blacklisted addresses to a HAProxy ACL blacklist file to redirect non-attacking blacklisted IPs to a standalone kicker proxy backend telling them how to unblacklist themselves, while still rate-limiting attacking IP addresses on iptables level), and letting the whitelisted and not-seen players to the main network backend.

Just for brevity as iptables can be hard: A helpful rate-limit configuration for the layman: https://making.pusher.com/per-ip-rate-limiting-with-iptables/ A good image about how the packets flow in a Netfilter-based system (and about same on most other *nixes): https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

As for the rate limits, a single ping seems to do a burst of 9 packets upstream (2 for client-started SYN, 6 packets of PSHs and ACKs for actual data, 1 for server-started FIN) and double that with SRV DNS record (client tries to ping with both the original domain and the SRV'd address). By a single packet capture, a login flow sends 125 packets on 5 seconds, and of those 71 packets during a single second. Mid-gaming, on one occurrence of 100 seconds there were total 4739 packets sent upstream, but those would be already whitelisted and thus would not be tracked by conntrack.

Example iptables-based configuration could look like this (untested):

  1. Whitelisted IP address starts connection, they are ACCEPTed straight away through on raw PREROUTING
  2. Blacklisted IP address starts connection, they are DROPped straight away through on raw PREROUTING
  3. An IP address that does not belong on any of those starts connection, they are screened on RATE-LIMIT and allowed standard login, which would kick them and add to white/blacklist.
  4. A rogue IP address sends junk data, this is up to the proxy/server to handle. Theoretically we could read if the first PSHed packet would parse as valid Minecraft packet data and if not, add it to blacklist early before the attack makes the proxy/server be any more unstable.
firewall:   # All the commands that will execute for internal whitelist additions, we assume blacklist commands run first or just refactor the config to have common startup rules
  enabled: true # Should host firewall be enabled?
  unix:
    on-enable: # These command will be executed one by one on BotSentry enable
    - "apt-get --yes install ipset" # Make sure ipset is installed
    - "ipset create -! whitelist hash:ip hashsize 4096" # Add a whitelist table constisting of IP address hashes
    - "ipset create -! blacklist hash:ip hashsize 4096" # Add a blacklist table constisting of IP address hashes
    - "ipset restore -file /etc/ipset.conf" # Restore previous lists if applicable
    - "iptables -N MC-RATE-LIMIT" # Create a chain for unknown IP addresses
    - "iptables -t raw -A PREROUTING -p tcp --dport 25565:25600 -m set --match-set blacklist src -j DROP" # Drop connections from blacklisted IP addresses
    - "iptables -t nat -A INPUT -p tcp --dport 25565:25600 -m conntrack --ctstate NEW -j MC-RATE-LIMIT" # Add new connections to the stricter rate limit chain
    - "iptables -A MC-RATE-LIMIT -m set --match-set whitelist src -j RETURN" # Return whitelisted addresses back to the previous chain
    - "iptables -A MC-RATE-LIMIT -m hashlimit --hashlimit-mode srcip --hashlimit-upto 50/sec --hashlimit-burst 200 --hashlimit-name conn_rate_limit -j ACCEPT" # Set up a bucket of 50 packets per second per IP, with allowance for burst peak of 200 packets
    - "iptables -A MC-RATE-LIMIT -j DROP" # Drop any overflowing packets
    on-disable: 
    - "ipset save > /etc/ipset.conf" # Save ipset lists
    - "iptables -t raw -D PREROUTING -p tcp --dport 25565:25600 -m set --match-set blacklist src -j DROP"  # Remove previously added raw PREROUTING chain rules
    - "iptables -t nat -D INPUT -p tcp --dport 25565:25600 -m conntrack --ctstate NEW -j MC-RATE-LIMIT" # Remove previously added nat INPUT chain rules
    - "iptables -D MC-RATE-LIMIT -m set --match-set whitelist src -j RETURN" # Remove rules from ratelimit chain
    - "iptables -D MC-RATE-LIMIT -m hashlimit --hashlimit-mode srcip --hashlimit-upto 50/sec --hashlimit-burst 200 --hashlimit-name conn_rate_limit -j ACCEPT" # Remove rules from ratelimit chain
    - "iptables -D MC-RATE-LIMIT -j DROP" # Remove rules from ratelimit chain
    - "iptables -X MC-RATE-LIMIT" # Remove the ratelimit chain
  blacklist:
    add: # These command will be executed with the detected IP when it gets blacklisted
    - "ipset -! -D whitelist %1$s"
    - "ipset -! -A blacklist %1$s"
    remove: # These command will be executed with the IP when it gets Un-Blacklisted
    - "ipset -! -D blacklist %1$s"
    flush: "ipset flush blacklist" # This command will be executed when doing the command /bs blacklist clear. When setting to: '' it will run each ip through the remove command (in case there is no flush)
  whitelist:
    add: # These command will be executed with the detected IP when it gets whitelisted
    - "ipset -! -D blacklist %1$s"
    - "ipset -! -A whitelist %1$s"
    remove: # This command will be executed with the IP when it gets Un-Whitelisted
    - "ipset -! -D whitelist %1$s"
    flush: "ipset flush whitelist" # This command will be executed when doing the command /bs whitelist clear. When setting to: '' it will run each ip through the remove command (in case there is no flush)
Laurenshup commented 2 years ago

Sorry for the very late response. I can definetely look into this, but this looks like a bit like #81. Here the API would be more useful.