HEX
Server: Apache
System: Linux ecres233.servconfig.com 4.18.0-553.94.1.lve.el8.x86_64 #1 SMP Thu Jan 22 12:37:22 UTC 2026 x86_64
User: gonnelllaw (9952)
PHP: 7.2.34
Disabled: NONE
Upload Files
File: //opt/tier1adv/bin/checkip
#!/opt/support/venv/bin/python3
"""Checks if an IP is blocked in the firewall"""

import os
from argparse import ArgumentParser
import sys
import subprocess
import json
import netaddr
import rads

sys.path.insert(0, '/opt/support/lib')
import arg_types
from output import header, print_listed, warn
import firewall_tools as fw


def parse_args():
    """Parse IPs from commandline args"""
    parser = ArgumentParser(description=__doc__)
    parser.add_argument(
        'ips',
        metavar='IP_ADDRESS',
        nargs='+',
        type=arg_types.ipaddress,
        help='IP to check (may be either IPv4 or IPv6)',
    )
    yes_group = parser.add_mutually_exclusive_group()
    yes_group.add_argument(
        '--yes',
        '-y',
        action='store_true',
        help='Auto-YES to the confirmation prompt to check ping and traceroute',
    )
    yes_group.add_argument(
        '--no',
        '-n',
        action='store_true',
        help="Auto-NO to the confirmation prompt to check ping and traceroute",
    )
    args = parser.parse_args()
    for addr in args.ips:
        addr: netaddr.IPAddress
        if not addr.is_global():
            warn(
                f'Warning: {addr} is a private IP and therefore cannot route '
                'over the internet.'
            )
        if str(addr).endswith('.255'):
            warn(
                f'Warning: {addr} ends in .255 and therefore may be rejected '
                'as a "bogon" by some routers, even if this is a valid IP.'
            )
    return args


def check_firewall(ips: list[netaddr.IPAddress]):
    header('Checking firewall...')
    fw_name, _, fw_data = fw.fw_info()
    print('This server is using', fw_name)
    for ipaddr in ips:
        if fw_name == 'ipset+fail2ban':
            # this function handles printing already
            fw.ipset_fail2ban_check(fw_data, ipaddr)
        else:  # APF or CSF
            listed = str(ipaddr) in fw_data
            print_listed(ipaddr, listed, f'the {fw_name} deny list')


def check_cphulk_logs(ips: list[netaddr.IPAddress]):
    if os.path.exists("/usr/local/cpanel/logs/cphulkd.log"):
        cph_log = "/usr/local/cpanel/logs/cphulkd.log"
        try:
            cmd = ["whmapi1", "--output=jsonpretty", "cphulk_status"]
            result = subprocess.run(
                cmd, capture_output=True, text=True, check=False
            )
            if (
                json.loads(result.stdout)
                .get('data', {})
                .get('is_enabled', False)
                == 1
            ):
                with open(cph_log, encoding="utf-8") as logfile:
                    for ip in ips:
                        if str(ip) in logfile.read():
                            print(f'{ip} was found in cphulk logs')

        except Exception:
            print(
                f'''
                An error occured while checking CPHulk status.
                If this is a VPS or dedicated server confirm
                that CPHulk is enabled.
                Confirm the path to CPHulk logs:
                {cph_log}
                '''
            )
    else:
        print(
            '''
              Log file for CPHulk is missing.
              Is CPHulk enabled?
              '''
        )


def ping(ips: dict[netaddr.IPAddress, bool]):
    header('Running ping tests...')
    for addr, is_v6 in ips.items():
        cmd = ['ping6'] if is_v6 else ['ping']
        cmd.extend(['-c2', str(addr)])
        subprocess.call(cmd)


def trace(ips: dict[netaddr.IPAddress, bool]):
    header('Running traceroute tests...')
    for addr, is_v6 in ips.items():
        cmd = ['traceroute6'] if is_v6 else ['traceroute']
        cmd.append(str(addr))
        subprocess.call(cmd)


def main():
    """Parse args, check firewall"""
    args = parse_args()
    check_firewall(args.ips)
    check_cphulk_logs(args.ips)
    if args.no:
        sys.exit(0)
    if not args.yes and not rads.prompt_y_n(
        'Would you like to proceed with ping and traceroute tests?'
    ):
        sys.exit(0)
    ips: dict[netaddr.IPAddress, bool] = {
        x: netaddr.valid_ipv6(str(x)) for x in args.ips
    }
    try:
        ping(ips)
        trace(ips)
    except KeyboardInterrupt:
        sys.exit(0)


if __name__ == '__main__':
    main()