SDK 1.1.1-beta.1 → main: WireGuard + IKEv2 hardening + GRDSGWServer + wifi-loss fix + CJ PR review (all-inclusive)#224
Merged
Conversation
…Response DTO Tier 1: collapse the negotiate dispatch in ConnectVpnWithConfiguredCredentials so BOTH protocols route through ConnectVpnWithNewUserCredentialsForProtocol(protocol). Delete NegotiateAndStartWireGuard (its host-pick was duplicate, its negotiate is the gateway dispatcher, its dial is StartWireGuardFromStoredCreds). Port the two WG-only host-pick behaviors (PreferredRegion region-snap + host-selection error check) into the now-shared CreateStandaloneCredentialsForTransportProtocol host-pick. Tier 2: introduce VPNDeviceResponse, a nullable superset DTO for the POST /api/v1.3/device reply for both protocols. RegisterDeviceForTransportProtocol deserializes the reply into it for IKEv2 and WireGuard alike; retire WireGuardRegistrationResponse + its JSON context. A single GRDCredential.CreateFromDeviceResponse(protocol, ...) factory plucks per protocol (replaces the two inline build sites and the dead, stuffing InitWithTransportProtocol). The credential carries the DTO verbatim on GRDCredential.Device; usage points (WireGuardQuickConfigForCredential, StartIKEv2Connection, ActiveConnectionPossible) pluck from Device. The WG device keypair stays on the flat fields (client-side, not in the host reply). Correctness: drop the UserName/Password field-stuffing on WG creds. ActiveConnectionPossible predicates now read disjoint subsets of Device by construction, so an IKEv2 check is false on a WG cred without any stuffing (removes the latent RasDial-645 coupling). Persistence/migration: flat fields are kept and still serialized so existing DPAPI-encrypted keychain blobs load unchanged; GRDCredentialManager backfills Device from the flat fields on read (EnsureDeviceFromLegacyFields, protocol-scoped so legacy WG stuffing is not surfaced as EAP fields). VPNDeviceResponse added to the source-gen GRDCredentialJsonContext for AOT. Service IPC contract (VPNCallParameters) unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uild Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… suite dwEncryptionType ET_Optional -> ET_RequireMax, and replace the CustomIPSecPolicies blob (ROUTER_CUSTOM_IKEv2_POLICY_0) with 3,4,8,5,5,5 = SHA-384 / AES-256 (IKE), AES-256-GCM ESP, ECP-384 PFS+DH. Prior blob's ESP cipher decoded to 3DES with an inconsistent/uncertain policy. Adds ET_RequireMax to the CsWin32 NativeMethods.txt request list. Gateway must offer this suite or the dial fails (by design) -- verify negotiated SA with Get-NetIPsecQuickModeSA before shipping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…8 (was 8/5) wg-poc.1 used the MS-RRASM server enum (GCM-256 cipher=8/auth=5); the client phonebook is the opposite (5/8), so RasDial failed with FWP_E_INVALID_ENUMERATOR (0x8032001D). Corrected hex matches Set-VpnConnectionIPsecConfiguration output. Bump to wg-poc.2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Carries the i196 WireGuard negotiate-consolidation work forward onto a fresh branch with main's 0.46.0->0.46.2 cleanup merged in. Conflicts resolved keeping the consolidated single connect-flow path (HEAD) while adopting main's key-exchange terminology, explicit VPNCallParameters .Transport, GRDTransportProtocol move to Shared, and related cleanups. Version: 0.46.2-wg-alpha.43. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… consolidation-and-cleanup # Conflicts: # GuardianConnectSDK/Directory.Build.Props
Closes the EAP user-auth gap: the entry required EAP (RASEO_RequireEAP +
EAP type 26) but creds were only fed the legacy RasSetCredentials way, which
a non-interactive SYSTEM service can't use to answer the EAP-MSCHAPv2
challenge -> looked like an MSCHAPv2/server failure.
Two auto-chained paths in ConfigureEapMschapV2UserData:
1. RasGetEapUserIdentity (NonInteractive) -> RasSetEapUserData
2. fallback: EapHostConfig XML (type 26) -> EapHostPeerConfigXml2Blob ->
RasSetCustomAuthData
Gateway-cert validation (iOS serverCertificateCommonName) is already handled
at the IKEv2 layer (dialed hostname + machine Trusted Root). UNTESTED against
a live gateway; verify eappcfg.dll export host + a Quick-Mode SA.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…6.3-alpha.2 RegisterDeviceForTransportProtocol discarded the server's error body on a non-success status (e.g. 400 'staff access restricted node'), surfacing only the HTTP reason phrase. Now logs status+body and returns it in the error message, mirroring the WireGuard branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…onPossible - ActiveConnectionPossible: single method with optional TransportProtocol? defaulting to the user's preferred protocol (GetPreferred); removed the duplicate no-arg overload. - Rename public entry points to clean parameterless API for app/partners: ConnectVpnWithConfiguredCredentials -> ConnectVPNTunnel, DisconnectVPN -> DisconnectVPNTunnel. Protocol resolved internally; both protocol paths stay merged from the entry down to the tunnel split. - Bump to 0.46.3-alpha.3 (breaking rename; new version required to publish). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- SelectGuardianHostWithCompletion returns the RegionalHostRecord (the GRDSGWServer analog) instead of flattening to (hostname, display) strings; connect flow carries the server object and reads fields at point of use. - RegionalHostRecord gains SmartProxyRoutingEnabled (wire key 'smart-routing-enabled') and a Region back-ref. Region binds from the nested 'region' object in servers/all-hostnames responses (GetAllHostnamesAsync); GetHostsForRegion stamps it (??=) for the per-region endpoint that omits it. Registered GRDRegion in RegionalHostRecordJsonContext (+ IncludeFields). - Scrub SDK comments referencing the app's developer window/tab. - Bump to 0.46.3-alpha.4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Server rename IKEv2 power-suspend gap (CJ's connect-after-sleep lockout): - StartVPNConnection guard is now OS-authoritative: decides 'is a tunnel up?' from IsAnyConnectionActive (IKEv2/RAS) rather than the static _activeTransport, which goes stale when the power-suspend path tears the tunnel down outside DisconnectVPNConnection (and is null-but-up after a resume reconnect). Stale references are reclaimed instead of blocking the next connect. - New GuardianNPCommandDispatcher.NotifyTransportTornDownExternally(), called from ServicePowerEventsHandler after PowerSuspendVPNConnection, so the dispatcher's reference doesn't dangle across sleep. Consolidation (since alpha.4): - Rename RegionalHostRecord -> GRDSGWServer (cross-platform parity w/ iOS/Android), incl. GRDSGWServerJsonContext. - CreateStandaloneCredentialsForTransportProtocol(..., GRDSGWServer server). - Delete dead ConfigureFirstTimeUserPostCredential. - Bump to 0.46.3-alpha.5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prototype (ConfigureEapMschapV2UserData) fails in the AOT/SYSTEM service anyway (RasGetEapUserIdentity -> ERROR_INTERACTIVE_MODE; XML fallback -> COM unsupported under AOT). This build dials EAP-MSCHAPv2 purely from the RAS-entry config (RASEO_RequireEAP + dwCustomAuthKey=26) + RasSetCredentials. Test: if IKEv2 EAP-MSCHAPv2 still authenticates (no RasDial 645), the explicit EAP user-data is NOT needed; if it fails, the prototype is needed and must be reworked to run in a service. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build A proved EAP-MSCHAPv2 authenticates from the RAS-entry config (RASEO_RequireEAP + dwCustomAuthKey=26) + RasSetCredentials alone — the RasSetEapUserData prototype was never needed and couldn't run in the AOT/SYSTEM service anyway. Removes ConfigureEapMschapV2UserData / ConfigureEapViaXmlConfig / BuildEapMschapV2ConfigXml, the eappcfg + RasGetEapUserIdentity/RasSetEapUserData/RasSetCustomAuthData P/Invokes, and RASEAPUSERIDENTITYW. The IKEv2 entry config + cipher suite (df2de66) are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…alpha.8) On an unplanned RAS drop (e.g. wifi deadspot), PollConnectionState only set suspend state and never removed the DNS-leak WFP filters. Those PermitQueriesFromTAP filters permit DNS only on the tunnel LUID and block all else; once the tunnel is dead the machine can't resolve ANY hostname, so every reconnect's GetServerStatus fails 'host unknown' and reboot is the only recovery (confirmed in CJ's 06-22 logs). Adds ConnectionRoutines.RemoveDnsFiltersAfterUnplannedDisconnect(), invoked from the !WasDisconnectPlanned branch; reuses VpnDnsFilteringHandler.UpdateFiltersState which removes filters when it sees the connection DISCONNECTED (same mechanism the planned path uses). WireGuard unaffected. Reset Configuration intentionally unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move SDK to 1.1.0 with VersionSuffix beta.N. New policy: bump the PATCH digit per fix/build so MSI/consumers can actually upgrade (MSI ProductVersion ignores the 4th .9999 field). No code change — version/policy only. Carries the full consolidation + DNS-filter-fix line. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tzeejay
reviewed
Jun 26, 2026
…connect overload - GRDVPNHelper: replace `!` null-deny on mainCredential/subCred with sanity null-checks that return a graceful errorResponse instead of NRE. - Remove the string host-override mechanism entirely: drop Common.kGuardianPreferredHost, GRDVPNHelper.HostOverrideMismatchAgainst, and the host-override-mismatch teardown in ConnectVPNTunnel(). The SDK no longer reads any host override — that logic moves wholly to the app Dev window. - Add overload ConnectVpnWithNewUserCredentialsForProtocol(TransportProtocol, GRDSGWServer?) so a caller can drive a specific server explicitly. - VPNDeviceResponse: regroup client-id under the Shared fields. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tzeejay
approved these changes
Jun 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SDK 1.1.1-beta.1 →
main. All-inclusive consolidation line: WireGuard transport consolidation, IKEv2 encryption hardening, GRDSGWServer parity, stability fixes, the wifi-loss DNS-filter fix, and CJ's PR-review changes. 18 commits;GRDVPNHelper.csis the bulk of the diff.WireGuard transport consolidation
VPNDeviceResponseDTO.ActiveConnectionPossibleinto one protocol-aware path.IKEv2 encryption hardening
CustomIPSecPoliciescipher blob: client GCM-256 = cipher 5 / auth 8 (was 8/5) — the real EAP-MSCHAPv2 fix.GRDSGWServer parity (iOS / Android)
RegionalHostRecord→GRDSGWServerand thread it through the connect flow; addGRDSGWServer+ source-gen JSON context, remove the oldRegionalHostRecord*.Stability fixes
_activeTransportlockout (IKEv2 power-suspend gap).CJ PR review
!null-deny onmainCredential/subCredwith graceful null-checks that return anerrorResponseinstead of throwing.Common.kGuardianPreferredHost,HostOverrideMismatchAgainst, and itsConnectVPNTunnel()teardown) — the SDK no longer reads any host override; that logic now lives in the app Dev window.ConnectVpnWithNewUserCredentialsForProtocol(TransportProtocol, GRDSGWServer?)so a caller can drive a specific server explicitly.Versioning
beta.Nprerelease suffix; current cut 1.1.1-beta.1.Notes
mainas GA, drop thebeta.1suffix → 1.1.1.