Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # After a few weeks "unsupervised," one of my servers had 130k+ IPs blocked by fail2ban
- # To process this "humongous" number of entries, the machine was often slow and non-responsive
- # I was locked outside of the machine because my IP was not being "authorized" - but it was
- # not blocked, too. Even adding the IP to the pool of authorized sources, the number of entries
- # was too large for the firewall to process.
- # I thought about a Python script to check all entries from my iptables, and if any CIDR had
- # more than 15 unique IPs blocked, the entire /24 would be blocked.
- # To further reduce the number of iptables entries, if possible, will join separate /24 into a larger
- # netblock.
- # Last, the script will create a bash shell script to add the blacklisted CIDRs into the iptables using UFW
- # Quick explanation:
- # Dump the iptables into a plain text file
- # If curious, check the number of lines for the iptables file ("wc -l iptables.banned_ips.txt")
- # Flush fail2ban ("fail2ban-client unban --all")
- # Double check the new number of iptables lines after flushing fail2ban ("iptables -L -n | wc -l")
- # Run the script to analyze the iptables dump and generate the CIDR file
- # Run the script to add the CIDR into iptables
- # STEPS:
- # Save your iptables output using "iptables -L -n > /tmp/iptables.banned_ips.txt"
- # After saving your iptables output, remember to flush your fail2ban --> "fail2ban-client unban --all"
- # You should have a CLEAN firewall
- import sys
- import re
- from ipaddress import ip_network, ip_address, collapse_addresses
- from collections import defaultdict
- THRESHOLD = 15 # Minimum number of bad IPs in a /24 to block
- def extract_and_convert(input_file, output_file, ufw_script):
- blocked_ips = defaultdict(set) # Stores individual bad IPs per /24 CIDR
- whitelisted_networks = set() # Stores unique /24 subnets to be whitelisted
- whitelisted_ips = set() # Stores individual whitelisted IPs (as IPv4Address objects)
- # Step 1: Identify whitelisted IPs and CIDRs
- with open(input_file, 'r') as f:
- for line in f:
- if line.startswith("ACCEPT"): # Process "ACCEPT" lines
- match = re.search(r'(\d+\.\d+\.\d+\.\d+)', line)
- if match:
- ip = ip_address(match.group(1))
- cidr = ip_network(f"{ip}/24", strict=False)
- whitelisted_networks.add(cidr)
- whitelisted_ips.add(ip)
- print(f"Whitelisted CIDR: {cidr} (from IP {ip})")
- # Step 2: Process "REJECT" lines while avoiding whitelisted networks
- with open(input_file, 'r') as f:
- for line in f:
- if line.startswith("REJECT"):
- match = re.search(r'(\d+\.\d+\.\d+\.\d+)', line)
- if match:
- ip = ip_address(match.group(1))
- cidr = ip_network(f"{ip}/24", strict=False)
- if cidr not in whitelisted_networks and ip not in whitelisted_ips:
- blocked_ips[cidr].add(ip)
- # Step 3: Filter CIDRs based on threshold
- filtered_cidrs = {cidr for cidr, ips in blocked_ips.items() if len(ips) >= THRESHOLD}
- # Step 4: Aggregate CIDRs while respecting whitelist constraints
- aggregated_networks = []
- for cidr in sorted(collapse_addresses(filtered_cidrs)):
- if not any(ip in cidr for ip in whitelisted_ips):
- aggregated_networks.append(cidr)
- # print(f"Optimized CIDR: {cidr}")
- # Step 5: Write optimized CIDR blocks to output file
- with open(output_file, 'w') as out_f:
- for cidr in aggregated_networks:
- out_f.write(str(cidr) + "\n")
- # Step 6: Generate a UFW script
- with open(ufw_script, 'w') as ufw_f:
- ufw_f.write("#!/bin/bash\n")
- ufw_f.write("# Auto-generated script to block bad actors using UFW\n\n")
- ufw_f.write("UFW=/usr/sbin/ufw\n\n")
- for cidr in aggregated_networks:
- ufw_f.write(f"$UFW deny from {cidr} to any\n")
- ufw_f.write("\n# Reload UFW rules\n")
- ufw_f.write("$UFW reload\n")
- print(f"UFW blocking script saved as: {ufw_script}")
- print("Make sure to run: chmod +x", ufw_script)
- # Check for correct usage
- if len(sys.argv) != 4:
- print("Usage: python script.py <input_file> <output_cidr_file> <ufw_script>")
- sys.exit(1)
- # Get file paths from command-line arguments
- input_file = sys.argv[1]
- output_cidr_file = sys.argv[2]
- ufw_script = sys.argv[3]
- extract_and_convert(input_file, output_cidr_file, ufw_script)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement