Harden Windows Server compatibility and system-wide proxy.

Fix exit-IP checks for HTTP-only proxies, apply proxy via WinINet Connections blob and WinHTTP, improve VPN detection on legacy Server, add SOCKS5 host:port:user:pass exit parsing, and add win_compat probe for PowerShell 2.0 hosts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Indiana Holmes
2026-05-16 18:03:30 -07:00
parent 8bd8d4267f
commit 8f012402a6
10 changed files with 579 additions and 43 deletions

View File

@@ -16,7 +16,15 @@ _VPN_ADAPTER_HINTS = (
"tailscale", "zerotier", "cisco anyconnect", "fortinet", "pulse secure",
"globalprotect", "softether", "proton", "mullvad", "expressvpn",
"surfshark", "private internet", "pia ", "windscribe", "hotspot shield",
"tunnel", "vpn",
)
_NON_VPN_HINTS = (
"wan miniport",
"microsoft kernel debug",
"isatap",
"teredo",
"loopback",
"pseudo-interface",
)
# Executables to whitelist in kill-switch when present
@@ -97,10 +105,45 @@ def detect_vpn() -> VpnStatus:
"""Inspect up network adapters for VPN/tunnel interfaces."""
out = _run_ps(
"Get-NetAdapter | Where-Object { $_.Status -eq 'Up' } | "
"Select-Object -ExpandProperty Name"
"ForEach-Object { \"$($_.Name)|$($_.InterfaceDescription)\" }"
)
if not out:
# Fallback: netsh
# Fallback for PowerShell 2.0 / older Windows Server: parse "wmic nic"
# then "netsh interface show interface". Both are locale-tolerant.
try:
r = subprocess.run(
["wmic", "nic", "where", "NetEnabled=true",
"get", "NetConnectionID,Name", "/format:list"],
capture_output=True,
text=True,
timeout=12,
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
)
blob = (r.stdout or "")
names: list[str] = []
cur_id = ""
cur_name = ""
for ln in blob.splitlines():
ln = ln.strip()
if not ln:
if cur_id:
names.append(f"{cur_id}|{cur_name}")
cur_id, cur_name = "", ""
continue
if ln.startswith("NetConnectionID="):
cur_id = ln.split("=", 1)[1].strip()
elif ln.startswith("Name="):
cur_name = ln.split("=", 1)[1].strip()
if cur_id:
names.append(f"{cur_id}|{cur_name}")
out = "\n".join(names)
except Exception:
out = ""
if not out:
# Last-ditch: netsh. Locale-tolerant — match the connected/enabled state
# by extracting the interface name from the rightmost column. Older
# localized Server SKUs (es, de, fr, etc.) don't print literal "Enabled".
try:
r = subprocess.run(
["netsh", "interface", "show", "interface"],
@@ -109,25 +152,42 @@ def detect_vpn() -> VpnStatus:
timeout=10,
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
)
lines = (r.stdout or "").splitlines()
raw = (r.stdout or "")
names = []
for ln in lines[3:]:
parts = ln.split()
if len(parts) >= 4 and parts[0] == "Enabled":
names.append(" ".join(parts[3:]))
for ln in raw.splitlines():
s = ln.rstrip()
if not s or s.startswith("-") or ":" in s.split(" ")[0]:
continue
parts = re.split(r"\s{2,}", s.strip())
if len(parts) >= 4:
nm = parts[-1].strip()
if nm and nm.lower() not in ("interface name", "nombre de interfaz"):
names.append(f"{nm}|")
out = "\n".join(names)
except Exception:
return VpnStatus()
adapters: list[str] = []
adapter_blob: list[str] = []
for line in out.splitlines():
name = line.strip()
raw = line.strip()
if not raw:
continue
if "|" in raw:
name, desc = raw.split("|", 1)
else:
name, desc = raw, ""
name = name.strip()
desc = desc.strip()
if name:
adapters.append(name)
adapter_blob.append((name + " " + desc).strip())
hits: list[str] = []
for name in adapters:
low = name.lower()
for i, name in enumerate(adapters):
low = adapter_blob[i].lower()
if any(h in low for h in _NON_VPN_HINTS):
continue
if any(h in low for h in _VPN_ADAPTER_HINTS):
hits.append(name)