Thursday, November 21, 2024

Mac loses web connection after reconnecting to iPhone’s Private Hotspot—how can I repair this?

The answer beneath may appear over-complicated, however each single line is essential to completely restore community connectivity. Even then, there are some edge instances the place the script does not work and I’ve to reboot my machine. If you recognize of a greater resolution, please let me know.

1. Export working community settings

Reboot the machine, connect with the hotspot, after which persist the right community configuration utilizing the next Python script. You’ll be able to change the WIFI_DEVICE_NAME to ‘iPhone USB’ to persist (and later restore) USB tethering community settings.

import subprocess
import re
import json

WIFI_DEVICE_NAME = "Wi-Fi"

def get_network_info():
    hardware_ports = subprocess.check_output(
        ["networksetup", "-listallhardwareports"], 
        textual content=True
    )

    wifi_match = re.search(
        f"{Hardware} Port: {WIFI_DEVICE_NAME}nDevice: (w+)", 
        hardware_ports
    )
    if not wifi_match:
        increase Exception("No Wi-Fi interface discovered")
    interface = wifi_match.group(1)

    ifconfig_output = subprocess.check_output(
        f"ifconfig {interface}", 
        shell=True
    ).decode().splitlines()

    ipv4_address = None
    ipv6_addresses = []
    for line in ifconfig_output:
        if "inet " in line:
            ipv4_address = line.cut up()[1]
        elif "inet6 " in line:
            ipv6_addresses.append(line.cut up()[1].cut up("%")[0])

    netstat_output = subprocess.check_output(
        f"netstat -nr | grep default | grep {interface}", 
        shell=True
    ).decode().splitlines()

    ipv4_router = ipv6_router = None
    for line in netstat_output:
        elements = line.cut up()
        if len(elements) > 1:
            if ":" not in elements[1]:
                ipv4_router = elements[1]
            else:
                ipv6_router = elements[1].cut up("%")[0]

    config = {
        "network_service_name": WIFI_DEVICE_NAME,
        "network_interface_id": interface,
        "ipv4_address": ipv4_address or "Unknown",
        "ipv4_subnet_mask": "255.255.255.0",
        "ipv4_router": ipv4_router or "Unknown",
        "ipv6_primary_address": ipv6_addresses[0] if ipv6_addresses else "Unknown",
        "ipv6_temporary_address": ipv6_addresses[1] if ipv6_addresses[1:] else "Unknown",
        "ipv6_clat46_address": ipv6_addresses[2] if ipv6_addresses[2:] else "Unknown",
        "ipv6_prefix_length": "64",
        "ipv6_router": ipv6_router or "Unknown",
    }

    config_filename = f"network_settings_{interface}.json"
    with open(config_filename, "w") as f:
        json.dump(config, f, indent=2)
    
    print(f"Saved config for {WIFI_DEVICE_NAME} ({interface}) to {config_filename}")

if __name__ == "__main__":
    get_network_info()

The Python script will generate a JSON file with working IPv4 and IPv6 settings inside the identical folder.

2. Restore community settings from the config file, then flip auto/DHCP routing again on

Create one other Python script. Word that working it requires sudo entry, as a result of altering most community settings on Mac can’t be accomplished with out sudo privileges.

import subprocess
import json
import time

def run_cmd(cmd, ignore_errors=False):
    strive:
        subprocess.run(cmd, test=True)
        print(f"Success: {' '.be part of(cmd)}")
        return True
    besides subprocess.CalledProcessError as e:
        if not ignore_errors:
            print(f"Failed: {' '.be part of(cmd)}: {e}")
        return False

def test_network(config_file):
    # Load configuration
    with open(config_file) as f:
        config = json.load(f)

    print("nSetting handbook IP configuration...")
    
    # Configure IPv4 settings
    run_cmd([
        "sudo", "networksetup", "-setmanual",
        config["network_service_name"],
        config["ipv4_address"],
        config["ipv4_subnet_mask"],
        config["ipv4_router"]
    ])

    # Replace IPv4 routing
    run_cmd(["sudo", "route", "delete", "default"])
    run_cmd(["sudo", "route", "add", "default", config["ipv4_router"]])

    # Configure IPv6 settings
    run_cmd([
        "sudo", "networksetup", "-setv6manual",
        config["network_service_name"],
        config["ipv6_primary_address"],
        config["ipv6_prefix_length"],
        config["ipv6_router"]
    ])
    
    # Add further IPv6 addresses
    run_cmd([
        "sudo", "ifconfig", config["network_interface_id"],
        "inet6", "add", config["ipv6_temporary_address"],
        "prefixlen", config["ipv6_prefix_length"]
    ])
    run_cmd([
        "sudo", "ifconfig", config["network_interface_id"],
        "inet6", "add", config["ipv6_clat46_address"],
        "prefixlen", config["ipv6_prefix_length"]
    ])

    # Replace IPv6 routing
    run_cmd(["sudo", "route", "delete", "-inet6", "default"], ignore_errors=True)
    run_cmd([
        "sudo", "route", "add", "-inet6", "default",
        f"{config['ipv6_router']}%{config['network_interface_id']}"
    ])

    print("nWait for 1 second earlier than resetting again to auto/DHCP community configuration...n")
    time.sleep(1)

    print("Resetting to automated configuration...")
    
    # Take away all configured IP addresses
    output = subprocess.check_output(
        f"ifconfig {config['network_interface_id']}", 
        shell=True
    ).decode().splitlines()

    for line in output:
        if "inet " in line:
            run_cmd([
                "sudo", "ifconfig", config["network_interface_id"],
                "inet", line.cut up()[1], "take away"
            ])
        elif "inet6 " in line:
            run_cmd([
                "sudo", "ifconfig", config["network_interface_id"],
                "inet6", "del", line.cut up()[1]
            ])

    # Reset to automated configuration
    run_cmd(["sudo", "networksetup", "-setdhcp", config["network_service_name"]])
    run_cmd(["sudo", "networksetup", "-setv6automatic", config["network_service_name"]])

if __name__ == "__main__":
    import sys
    test_network(sys.argv[1])

When tethering stops working, execute the script, passing the generated config file title into it:

python3 load_working_network_settings.py network_settings_en0.json

Voila! Your web entry ought to (hopefully) be restored now.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles