import subprocess def detect_rt_tables_path(): return "/etc/iproute2/rt_tables" def list_connections(): output = subprocess.check_output(["nmcli", "-t", "-f", "uuid,name,type,device", "connection", "show"]).decode() print("\n[DEBUG] Surowe dane z nmcli:") print(output) conns = [] for line in output.strip().splitlines(): parts = line.strip().split(":", 3) if len(parts) < 4: continue uuid, name, typ, dev = parts if typ.strip() in ["ethernet", "802-3-ethernet"]: dev = dev.strip() if dev.strip() else "" conns.append({"uuid": uuid, "name": name, "device": dev}) return conns def prompt_config(conn): default_iface = conn['device'] if not default_iface: default_iface = input(f"Podaj nazwę interfejsu dla połączenia '{conn['name']}' ({conn['uuid']}): ").strip() print(f"\n--- Konfiguracja dla interfejsu: {default_iface} ({conn['name']}) ---") ip = input("Adres IP/maska (np. 10.87.2.121/24): ").strip() # domyślna brama z IP ip_parts = ip.split(".") default_gw = f"{ip_parts[0]}.{ip_parts[1]}.{ip_parts[2]}.1" if len(ip_parts) >= 4 else "" gw_input = input(f"Brama (enter = brak, d = {default_gw}): ").strip().lower() if gw_input == "d": gw = default_gw elif gw_input == "": gw = None else: gw = gw_input third_octet = ip_parts[2] if len(ip_parts) >= 3 else "100" default_table = third_octet default_prio = third_octet table = input(f"Numer tablicy routingu [domyślnie {default_table}]: ").strip() or default_table prio = input(f"Priorytet dla rule [domyślnie {default_prio}]: ").strip() or default_prio return { "uuid": conn["uuid"], "iface": default_iface, "ip": ip, "gateway": gw, "table": table, "priority": prio } def ask_disable_ipv6(devices): choice = input("\nWyłączyć IPv6? (tak/wszystkie/nie/[lista interfejsów oddzielona spacją]): ").strip().lower() if choice in ["tak", "yes", "y", "wszystkie"]: return set(devices) elif choice in ["nie", "no", "n"]: return set() else: return set(choice.split()) def ask_main_gateway_iface(devices): print("\nDostępne interfejsy: " + ", ".join(devices)) main_iface = input("Podaj nazwę interfejsu, który ma mieć bramę główną (main), enter jeśli żaden: ").strip() return main_iface if main_iface in devices else None def generate_commands(configs, disable_ipv6_ifaces, main_iface): lines = [] rt_tables = set() for c in configs: uuid = c["uuid"] iface = c["iface"] ip = c["ip"] gateway = c["gateway"] table = c["table"] priority = c["priority"] lines.append(f"# Konfiguracja: {iface} ({uuid}) → {ip} gw {gateway or '-'} table {table}") # Ustawienia podstawowe lines.append(f"nmcli con modify {uuid} connection.interface-name {iface}") lines.append(f"nmcli con modify {uuid} ipv4.addresses {ip} ipv4.method manual") lines.append(f"nmcli con modify {uuid} ipv4.never-default yes") # IPv6 wyłączony jeśli wskazano if iface in disable_ipv6_ifaces: lines.append(f"nmcli con modify {uuid} ipv6.method ignore") # Parsowanie adresu IP bez maski ip_only = ip.split("/")[0] # Obsługa tras i reguł tylko jeśli podano bramę if gateway: if iface == main_iface: # tylko tu ustawiamy bramę domyślną lines.append(f"nmcli con modify {uuid} ipv4.gateway {gateway}") else: # trasa i reguła do osobnej tablicy lines.append(f"nmcli con modify {uuid} +ipv4.routes \"0.0.0.0/0 {gateway} table={table}\"") lines.append(f"nmcli con modify {uuid} ipv4.routing-rules \"priority {priority} from {ip_only}/32 table {table}\"") rt_tables.add(f"{table} rt{table}") lines.append("") # pusta linia dla czytelności # Restart połączeń lines.append("# Restart połączeń") for c in configs: lines.append(f"nmcli con down {c['uuid']} || true") lines.append(f"nmcli con up {c['uuid']}") # Dodaj wpisy do rt_tables tylko dla użytych tablic rt_path = detect_rt_tables_path() lines.append(f"\n# Wpisy do {rt_path}") if "rt_tables.d" in rt_path: lines.append("mkdir -p /etc/iproute2/rt_tables.d") for rt in sorted(rt_tables): lines.append(f"echo \"{rt}\" | sudo tee -a {rt_path} > /dev/null") return "\n".join(lines) def main(): connections = list_connections() print("\n[DEBUG] Wykryto połączenia:") for c in connections: print(f"- {c['name']} ({c['uuid']}) → {c['device']}") if len(connections) == 0: print("Brak połączeń ethernet.") return devices = [c["device"] for c in connections] disable_ipv6_ifaces = ask_disable_ipv6(devices) main_iface = ask_main_gateway_iface(devices) configs = [prompt_config(c) for c in connections] result = generate_commands(configs, disable_ipv6_ifaces, main_iface) print("\n=== Wygenerowane polecenia ===\n") print(result) with open("nmcli_setup.sh", "w") as f: f.write(result) print("\nZapisano do pliku: nmcli_setup.sh") if __name__ == "__main__": main()