Allow pinned self-signed TLS for private IPv4 ranges on iOS 17+

This commit is contained in:
2026-09-12 15:33:17 +03:00
parent f8de824752
commit a17a7f8027
5 changed files with 55 additions and 9 deletions
+8 -2
View File
@@ -61,7 +61,7 @@ for name, sources, is_test in [("MusicBridge", app_sources, False), ("MusicBridg
proxy = add("test-proxy", "PBXContainerItemProxy", containerPortal=uid("project"), proxyType=1, remoteGlobalIDString=uid("MusicBridgetarget"), remoteInfo="MusicBridge")
deps = [add("test-dependency", "PBXTargetDependency", target=uid("MusicBridgetarget"), targetProxy=proxy)]
else:
settings.update(INFOPLIST_FILE="MusicBridge/Info.plist", CURRENT_PROJECT_VERSION="1", MARKETING_VERSION="0.1.0")
settings.update(INFOPLIST_FILE="MusicBridge/Info.plist", CURRENT_PROJECT_VERSION="2", MARKETING_VERSION="0.1.1")
targets.append(add(name + "target", "PBXNativeTarget", name=name, productName=name, productReference=product,
productType="com.apple.product-type.bundle.unit-test" if is_test else "com.apple.product-type.application",
buildConfigurationList=configurations(name, settings), buildPhases=phases, buildRules=[], dependencies=deps))
@@ -106,6 +106,12 @@ info = dict(CFBundleDevelopmentRegion="ru", CFBundleDisplayName="MusicBridge", C
LSRequiresIPhoneOS=True, UILaunchScreen={},
UISupportedInterfaceOrientations=["UIInterfaceOrientationPortrait"],
NSLocalNetworkUsageDescription="MusicBridge подключается к вашему ПК, чтобы показывать музыку и управлять воспроизведением.",
NSAppTransportSecurity=dict(NSAllowsLocalNetworking=True))
# iOS 17+ requires explicit IP exceptions for custom self-signed trust.
# BridgeClient still requires HTTPS, an exact SHA-256 pin and valid dates.
# Never disable ATS globally or include public IP ranges.
NSAppTransportSecurity=dict(NSAllowsLocalNetworking=True, NSExceptionDomains={
network: dict(NSExceptionAllowsInsecureHTTPLoads=True)
for network in ("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")
}))
(ROOT / "MusicBridge" / "Info.plist").write_bytes(plistlib.dumps(info, sort_keys=False))
print("Generated Xcode project, shared scheme and Info.plist.")
+5 -1
View File
@@ -25,7 +25,11 @@ referenced = set(re.findall(r'"([A-F0-9]{24})"', project))
assert defined == referenced, "Project has dangling object references."
info = plistlib.loads(generated[2].read_bytes())
assert info["NSLocalNetworkUsageDescription"]
assert info["NSAppTransportSecurity"] == {"NSAllowsLocalNetworking": True}
assert info["NSAppTransportSecurity"] == {
"NSAllowsLocalNetworking": True,
"NSExceptionDomains": {network: {"NSExceptionAllowsInsecureHTTPLoads": True}
for network in ("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")},
}
ET.parse(generated[1])
fixture = json.loads((root / "MusicBridgeTests/state-v1.json").read_text(encoding="utf-8"))
assert fixture["protocolVersion"] == 1 and fixture["positionSeconds"] == 42.5