fix:修改默认网路只有5G模组问题
This commit is contained in:
@@ -76,6 +76,24 @@ def format_shell_cmd(cmd):
|
||||
return " ".join(shlex.quote(part) for part in cmd)
|
||||
|
||||
|
||||
def parse_ipv4_address(value):
|
||||
try:
|
||||
return str(ipaddress.IPv4Address(value))
|
||||
except ipaddress.AddressValueError as exc:
|
||||
raise argparse.ArgumentTypeError(f"无效的 IPv4 地址: {value}") from exc
|
||||
|
||||
|
||||
def dedupe_keep_order(values):
|
||||
seen = set()
|
||||
result = []
|
||||
for value in values:
|
||||
if value in seen:
|
||||
continue
|
||||
seen.add(value)
|
||||
result.append(value)
|
||||
return result
|
||||
|
||||
|
||||
def require_root():
|
||||
if os.geteuid() != 0:
|
||||
print("[FAIL] 请使用 sudo 运行此脚本")
|
||||
@@ -513,6 +531,70 @@ def renew_dhcp(iface):
|
||||
return False, "系统中未找到 dhclient 或 udhcpc"
|
||||
|
||||
|
||||
def get_default_routes(iface):
|
||||
code, output = run_cmd(["ip", "-o", "route", "show", "default", "dev", iface], timeout=10)
|
||||
if code != 0:
|
||||
return []
|
||||
return [line.strip() for line in output.splitlines() if line.strip()]
|
||||
|
||||
|
||||
def resolve_gateway(iface, fallback_gateway):
|
||||
for route in get_default_routes(iface):
|
||||
tokens = route.split()
|
||||
for index, token in enumerate(tokens[:-1]):
|
||||
if token == "via":
|
||||
gateway = tokens[index + 1]
|
||||
print(f"[INFO] 从默认路由检测到 {iface} 网关: {gateway}")
|
||||
return gateway
|
||||
|
||||
print(f"[INFO] 未从默认路由检测到 {iface} 网关,回退到 {fallback_gateway}")
|
||||
return fallback_gateway
|
||||
|
||||
|
||||
def delete_default_routes(iface):
|
||||
removed = 0
|
||||
|
||||
while True:
|
||||
routes = get_default_routes(iface)
|
||||
if not routes:
|
||||
return removed
|
||||
|
||||
deleted_this_round = False
|
||||
for route in routes:
|
||||
cmd = ["ip", "route", "del", *route.split()]
|
||||
code, output = run_cmd(cmd, timeout=10)
|
||||
if code != 0:
|
||||
code, output = run_cmd(["ip", "route", "del", "default", "dev", iface], timeout=10)
|
||||
if code != 0:
|
||||
raise RuntimeError(f"删除默认路由失败: {iface}\n{output}")
|
||||
removed += 1
|
||||
deleted_this_round = True
|
||||
|
||||
if not deleted_this_round:
|
||||
raise RuntimeError(f"未能删除 {iface} 的默认路由")
|
||||
|
||||
|
||||
def install_host_routes(iface, gateway, targets):
|
||||
for target in dedupe_keep_order(targets):
|
||||
cmd = ["ip", "route", "replace", f"{target}/32", "via", gateway, "dev", iface]
|
||||
code, output = run_cmd(cmd, timeout=10)
|
||||
if code != 0:
|
||||
raise RuntimeError(f"添加主机路由失败: {target} via {gateway} dev {iface}\n{output}")
|
||||
|
||||
print(f"[OK] 已添加主机路由: {target}/32 via {gateway} dev {iface}")
|
||||
|
||||
|
||||
def enforce_route_policy(iface, fallback_gateway, route_targets):
|
||||
gateway = resolve_gateway(iface, fallback_gateway)
|
||||
removed = delete_default_routes(iface)
|
||||
print(f"[OK] 已删除 {iface} 上的 {removed} 条默认路由")
|
||||
|
||||
if route_targets:
|
||||
install_host_routes(iface, gateway, route_targets)
|
||||
else:
|
||||
print(f"[WARN] {iface} 未配置任何主机路由目标,5G 将不再承载公网流量")
|
||||
|
||||
|
||||
def ensure_ipv4(iface):
|
||||
"""为指定接口申请 IPv4 地址。"""
|
||||
ipv4_addrs = get_ipv4_addrs().get(iface, [])
|
||||
@@ -659,11 +741,29 @@ def parse_args():
|
||||
default=DEFAULT_MODEM_SUBNET,
|
||||
help=f"拨号成功后用于识别模组接口的 IPv4 网段,默认 {DEFAULT_MODEM_SUBNET}",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--gateway",
|
||||
type=parse_ipv4_address,
|
||||
default=DEFAULT_MODEM_GATEWAY,
|
||||
help=f"5G 模组网关地址,默认 {DEFAULT_MODEM_GATEWAY}",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--skip-dhcp",
|
||||
action="store_true",
|
||||
help="只等待 USB 网卡出现,不主动申请 IPv4",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--remove-default-route",
|
||||
action="store_true",
|
||||
help="拨号成功后删除 5G 接口上的默认路由,只保留显式主机路由",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--route-target",
|
||||
action="append",
|
||||
default=[],
|
||||
type=parse_ipv4_address,
|
||||
help="拨号完成后通过 5G 接口保留的 IPv4 主机路由目标,可重复传入",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -733,7 +833,12 @@ def main():
|
||||
for addr in ipv4_addrs:
|
||||
print(f"[OK] {iface} 已获取 IPv4: {addr}")
|
||||
save_interface_info(iface)
|
||||
ping_via_interface(iface)
|
||||
route_targets = dedupe_keep_order(args.route_target)
|
||||
if args.remove_default_route:
|
||||
enforce_route_policy(iface, args.gateway, route_targets)
|
||||
|
||||
connectivity_targets = route_targets or list(DEFAULT_PUBLIC_TARGETS)
|
||||
ping_via_interface(iface, targets=connectivity_targets)
|
||||
print(f"[DONE] RNDIS 拨号完成,可执行: sudo python3 speed_test.py {iface}")
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user