PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /opt/maint/bin/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //opt/maint/bin/fix_etc_ips.py |
#!/opt/imh-python/bin/python3 """Scans /etc/ips for IPs with incorrect or missing subnet masks/broadcasts. Also searches for IPs in the file which are not from the correct network""" from argparse import ArgumentParser from configparser import ConfigParser import logging import os import sys import json from collections import Counter import subprocess from netaddr import IPNetwork, IPAddress from netaddr.core import AddrFormatError import rads def iter_v4_prefixes(): """Yield subnet (IPNetwork) and zone (str) for each net in imh/whh""" with open('/opt/maint/etc/netbox.json', encoding='utf-8') as file: data: dict[str, dict] = json.load(file)['ipv4']['prefixes'] for tenant, site_ips in data.items(): if tenant not in ('imh', 'whh'): continue for site, nets in site_ips.items(): for net in nets: try: ipnet = IPNetwork(net) except AddrFormatError: logging.error('Could not parse subnet: %r', net) continue yield ipnet, site def get_zone() -> str: """Return the value of salt[imh.zone]() which is saved to maint.ini""" conf = ConfigParser(strict=True) if not conf.read('/opt/maint/etc/maint.ini'): raise FileNotFoundError('/opt/maint/etc/maint.ini') return conf.get('net', 'zone') def find(v4_prefixes: dict[IPNetwork, str], addr: str) -> tuple[IPNetwork, str]: """Find the subnet and zone an IP is from""" try: ipaddr = IPAddress(addr) except AddrFormatError as exc: raise ValueError(f'Could not parse IP: {addr!r}') from exc matches = {} for net, site in v4_prefixes.items(): if ipaddr in net: matches[net] = site if not matches: raise KeyError(f'Could not find subnet for {addr!r}') smallest_net = sorted(matches, key=len)[0] return smallest_net, matches[smallest_net] def send_str(bad_ips): """Send an STR ticket for an IP assigned from the wrong block""" logging.info('Sending STR for bad IPs: %r', bad_ips) body = """ The following IP(s) on this server appear to be assigned from the wrong datacenter's IP blocks. For each, * clear the IP from IMHSC * check if it has a customer on it and fix / contact as necessary * remove the IP from the server IP(s): """.strip() rads.send_email( to_addr='str@imhadmin.net', subject='Bad IP(s) in /etc/ips', body='{}\n\n{}'.format(body, '\n'.join(bad_ips)), ) def parse_args(): """Parse sys.argv""" parser = ArgumentParser(description=__doc__) parser.add_argument('--noop', action='store_true') return parser.parse_args() def main(): """Main program logic: Find errors in /etc/ips""" noop: bool = parse_args().noop # cron config appends stdout/err to /var/log/maint/fix_etc_ips.log rads.setup_logging(path=None, loglevel=logging.INFO, print_out='stdout') v4_prefixes = dict(iter_v4_prefixes()) local_zone = get_zone() with open('/etc/ips', encoding='ascii') as handle: etc_ips = handle.read().split() fixed = False # whether we changed /etc/ips wrong_zone = [] # any IPs we found asigned from the wrong block for index, ip_row in enumerate(etc_ips.copy()): if ip_row.startswith('169.'): continue addr = ip_row.split(':', 1)[0] try: net, site = find(v4_prefixes, addr) except (KeyError, ValueError) as exc: logging.error(exc) continue if site != local_zone: # this IP was assigned from the wrong block logging.warning( '%s was assigned from the wrong zone (%s)', addr, site ) wrong_zone.append(addr) # Don't proceed to editing its mask - it's already likely causing # routing problems for this server. Don't risk making it worse. continue correct = f"{addr}:{net.netmask}:{net.broadcast}" if correct != ip_row: # either the netmask or broadcast was wrong logging.info('Fixing %r -> %r', ip_row, correct) fixed = True etc_ips[index] = correct if dupes := [k for k, v in Counter(etc_ips).items() if v > 1]: logging.info('Removing duplicates: %r', dupes) etc_ips = list(set(etc_ips)) fixed = True if noop: return if fixed: # we fixed at least one line in /etc/ips write_etc_ips(etc_ips) restart_ipaliases() if wrong_zone: # at least one IP was assigned from the wrong zone in IMHSC send_str(wrong_zone) def write_etc_ips(etc_ips): """Safely write to /etc/ips""" with open('/etc/ips.fixing', 'w', encoding='ascii') as handle: handle.write('\n'.join(etc_ips)) handle.write('\n') os.rename('/etc/ips.fixing', '/etc/ips') def restart_ipaliases(): """Restart ipaliases to load subinterfaces from the IPs in /etc/ips""" cmd = ['/usr/local/cpanel/scripts/restartsrv_ipaliases'] try: subprocess.check_call(cmd) except (subprocess.CalledProcessError, OSError): logging.critical('error restarting ipaliases') sys.exit(2) if __name__ == '__main__': main()