#!/usr/bin/env python3 import time import argparse import sys import subprocess from scapy.all import * PAYLOAD = bytes.fromhex("6e7961617e5f6e6f5f6c6f6f707321") def is_iface_up(iface): try: out = subprocess.check_output(["ip", "link", "show", iface], text=True) return "state UP" in out or "UP" in out.splitlines()[0] except Exception: return False def send_lbd(iface): dst = "01:80:C2:00:00:0A" packet = Ether(dst=dst, src=get_if_hwaddr(iface), type=0x9000) / Raw(load=PAYLOAD) sendp(packet, iface=iface, verbose=False) def loop_detected(pkt, iface): if pkt[Ether].type != 0x9000 or pkt[Ether].src != get_if_hwaddr(iface): return False if Raw not in pkt: return False return pkt[Raw].load == PAYLOAD def sniff_for_loop(iface, timeout=2): found = False def _detect(pkt): nonlocal found if loop_detected(pkt, iface): found = True sniff(iface=iface, filter="ether proto 0x9000", prn=_detect, timeout=timeout, store=False) return found def run_once(iface): if not is_iface_up(iface): print(f"[!] Interface {iface} is DOWN. Connect cable or check interface.") return send_lbd(iface) if sniff_for_loop(iface): print(f"[!] Loop detected on {iface} (payload matched)") else: print(f"[+] No loop detected on {iface}") def run_watch(iface, interval): print(f"[*] Watching {iface} for loops every {interval}s...") while True: if not is_iface_up(iface): print(f"[!] Interface {iface} is DOWN. Waiting...") time.sleep(interval) continue send_lbd(iface) if sniff_for_loop(iface): print(f"[!] Loop detected on {iface} (payload matched)") time.sleep(interval) def main(): parser = argparse.ArgumentParser( description="Loopback Detection Tool", usage="%(prog)s --iface IFACE [--watch] [--interval N]" ) parser.add_argument("--iface", required=True, help="Network interface to use (e.g., enp3s0 or igb0)") parser.add_argument("--watch", action="store_true", help="Enable continuous monitoring mode") parser.add_argument("--interval", type=int, default=2, help="Interval between checks in watch mode in seconds (default: 2)") if len(sys.argv) == 1: parser.print_help(sys.stderr) sys.exit(1) args = parser.parse_args() if args.watch: run_watch(args.iface, args.interval) else: run_once(args.iface) if __name__ == "__main__": main()