#!/usr/bin/env python3 import argparse from ipaddress import ip_network from subprocess import run def parse_arguments(): parser = argparse.ArgumentParser( description='👾 ExclusionEnforcer: Your all-in-one tool for scope grinding and firewall rule manipulation. ✨', epilog='''Example usage: python3 scopegrinder.py scope.txt deny.txt output.txt RuleName python3 scopegrinder.py -r RuleName''') parser.add_argument('-s', '--scope', help='Path to the file containing the scope IP ranges. Each IP or IP range should be on a new line. Required unless -r is set.') parser.add_argument('-d', '--deny', help='Path to the file containing the deny list IP ranges. Each IP or IP range should be on a new line. Required unless -r is set.') parser.add_argument('-o', '--output', help='Path to the file where to write the valid IPs. The file will be created if it does not exist. Required unless -r is set.') parser.add_argument('-n', '--rule_name', help='Name to be used when creating or removing firewall rules. This will be used in the comment field of the iptables rules.') parser.add_argument('-r', '--remove', help='If set with rule name, the script will remove the specified iptables rules instead of adding them. When this is set, scope, deny and output parameters can be omitted.') args = parser.parse_args() if args.remove: if any([args.scope, args.deny, args.output]): parser.error("--remove should not be used with scope, deny, or output parameters.") else: if not all([args.scope, args.deny, args.output, args.rule_name]): parser.error("When not using --remove, the scope, deny, output and rule_name parameters are required.") return args def expand_ip_ranges(ip_ranges): for ip_range in ip_ranges: for ip in ip_network(ip_range): yield str(ip) def write_valid_ips(scope_file, deny_file, output_file): with open(scope_file) as f: scope_ips = set(expand_ip_ranges(line.strip() for line in f)) with open(deny_file) as f: deny_ips = set(expand_ip_ranges(line.strip() for line in f)) valid_ips = scope_ips - deny_ips with open(output_file, 'w') as f: for ip in valid_ips: print(ip, file=f) return valid_ips def update_firewall_rules(valid_ips, rule_name, remove): for ip in valid_ips: if remove: cmd = ['iptables', '-D', 'OUTPUT', '-d', ip, '-j', 'DROP', '-m', 'comment', '--comment', rule_name] else: cmd = ['iptables', '-A', 'OUTPUT', '-d', ip, '-j', 'DROP', '-m', 'comment', '--comment', rule_name] run(cmd) def main(): args = parse_arguments() if args.remove: update_firewall_rules([], args.remove, True) else: valid_ips = write_valid_ips(args.scope, args.deny, args.output) update_firewall_rules(valid_ips, args.rule_name, False) print("💥 ExclusionEnforcer has done its job. Check your scope and firewall rules. 💥") if __name__ == '__main__': main()