#Copyright (C) © 2024 Philipp Wagner #This program comes with ABSOLUTELY NO WARRANTY. #This is free software, and you are welcome to redistribute it #under certain conditions; type 'show c' for details. import socket import threading import time import argparse import hashlib # Konfigurationsparameter LOOPBACK_TIMEOUT = 1 # Zeit in Sekunden, um Loopback zu verhindern # Speichert gesendete Nachrichten-Hashes für eine kurze Zeit, um Loopback zu verhindern recent_messages = {} def create_socket(port, bind_ip=''): """Erstellt und konfiguriert den UDP-Socket zum Lauschen auf Broadcast-Nachrichten.""" sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.bind((bind_ip, port)) return sock def hash_message(message): """Erzeugt einen Hash-Wert für eine Nachricht.""" return hashlib.sha256(message).hexdigest() def should_forward_message(message): """Überprüft, ob eine Nachricht innerhalb des Zeitlimits bereits gesendet wurde.""" current_time = time.time() message_hash = hash_message(message) # Entferne alte Nachrichten for msg_hash in list(recent_messages): if current_time - recent_messages[msg_hash] > LOOPBACK_TIMEOUT: del recent_messages[msg_hash] if message_hash in recent_messages: print(f"Message already forwarded recently: {message}") return False recent_messages[message_hash] = current_time return True def relay_messages(listen_ip, listen_port, relay_ip, relay_port): sock = create_socket(listen_port, listen_ip) print(f"Listening for UDP broadcasts on {listen_ip}:{listen_port}...") while True: data, addr = sock.recvfrom(1024) # Puffergröße 1024 Bytes print(f"Received message on {listen_ip}:{listen_port} from {addr}: {data}") # Prüfen, ob die Nachricht mit "RCVDPKT: \"TELNET\" \"\" \"DX de", "GAB:" oder "SpotUdp" beginnt if (data.startswith(b'RCVDPKT: "TELNET" "" "DX de') or data.startswith(b'GAB:') or data.startswith(b'SpotUdp')): if should_forward_message(data): print(f"Forwarding message to {relay_ip}:{relay_port}") relay_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) relay_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) relay_socket.sendto(data, (relay_ip, relay_port)) relay_socket.close() else: print(f"Skipped forwarding message due to recent forwarding: {data}") def main(): parser = argparse.ArgumentParser(description="Bidirektionales UDP-Relay mit zeitbasierter Loopback-Prüfung") parser.add_argument('--ip1', type=str, required=True, help='Erste IP-Adresse') parser.add_argument('--port1', type=int, required=True, help='Erster Port') parser.add_argument('--ip2', type=str, required=True, help='Zweite IP-Adresse') parser.add_argument('--port2', type=int, required=True, help='Zweiter Port') args = parser.parse_args() ip1 = args.ip1 port1 = args.port1 ip2 = args.ip2 port2 = args.port2 # Starten von zwei Threads für bidirektionales Relay mit zeitbasierter Loopback-Prüfung thread1 = threading.Thread(target=relay_messages, args=(ip1, port1, ip2, port2)) thread2 = threading.Thread(target=relay_messages, args=(ip2, port2, ip1, port1)) thread1.start() thread2.start() thread1.join() thread2.join() if __name__ == "__main__": main()