# Session Log — 2026-05-22

## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
- **Session span:** ~14:00–17:50 MST

---

## Session Summary

This session was dedicated to deploying a working L2TP/IPsec VPN for Peaceful Spirit client home computers (MaraHomeNew, Maras-HP-Laptop, PST-SURFACE, BridgettePSHomeComputer). The goal was a VPN that works at the Windows pre-login screen, uses domain credentials, requires minimal user intervention, and persists saved credentials across reconnects.

The session began with an earlier approach using the UCG (UniFi Cloud Gateway) as the VPN termination point with strongSwan/xl2tpd. After repeated authentication and routing failures, Mike made the architectural decision to abandon UCG-hosted VPN entirely and pivot: delete VPN from UCG, add DNAT port-forward rules on UCG to pass UDP 500/4500 through to PST-SERVER (Windows Server 2016 Essentials), and configure RRAS on PST-SERVER as the VPN endpoint. This proved the correct path.

RRAS was configured on PST-SERVER with the L2TP PSK, NAT-T registry key (AssumeUDPEncapsulationContextOnSendRule=2), and AD user pst-admin was given dial-in permission. VPN profiles were deployed to all client machines via a PowerShell script run through GuruRMM, creating AllUserConnection entries in rasphone.pbk with CacheCredentials=1, split tunneling with a 192.168.0.0/24 route, NRPT rule for .peacefulspirit.local DNS, and machine-level cmdkey credential storage. The critical limitation discovered: Set-VpnConnection -L2tpPsk fails when run as SYSTEM (RMM context) — it must be run interactively by an admin. Mike ran this command manually on each machine while physically present at Mara's house.

Two blocking issues were resolved on-site. First, a stale hosts file entry on MaraHomeNew (and potentially other machines) mapped PST-SERVER to 72.194.62.5 (Mara's router's bogus DNS response from before VPN was connected), causing name resolution to fail even with VPN up. After Mike identified the hosts entry, a GuruRMM script was deployed to all four PST machines to remove any pst-server/peacefulspirit entries and flush DNS. Second, the PSK had not been set interactively on Maras-HP-Laptop and PST-SURFACE — Mike ran Set-VpnConnection -L2tpPsk on each machine while on-site. By end of session, all three of Mara's machines (MaraHomeNew, Maras-HP-Laptop, PST-SURFACE) were confirmed working. BridgettePSHomeComputer remains pending — it was offline during the session.

---

## Key Decisions

- **Abandon UCG VPN, use RRAS on PST-SERVER**: UCG strongSwan/xl2tpd produced repeated phase 2 / PPP auth failures. Routing through PST-SERVER (already a DC with AD and NPS) gave cleaner auth and eliminated separate VPN server management.
- **DNAT on UCG rather than VPN endpoint**: UCG iptables DNAT rules (UDP 500, 4500, ESP) forward VPN traffic to 192.168.0.2. UniFi Traffic Rules are firewall-allow only — NOT DNAT. Persistent via /data/on_boot.d/10-vpn-portforward.sh.
- **AllUserConnection phonebook**: Ensures VPN is available at the Windows pre-login screen, not just per-user. Required for the "connect before login" use case.
- **NRPT over VPN DNS suffix push**: Add-VpnConnectionTriggerDnsConfiguration fails for AllUserConnection profiles. NRPT (Add-DnsClientNrptRule) routes .peacefulspirit.local queries to 192.168.0.2 regardless of connection state.
- **cmdkey as SYSTEM for credential persistence**: cmdkey run in SYSTEM context stores credentials in the machine credential store, accessible pre-login. Per-user cmdkey would not be available at the login screen.
- **Set-VpnConnection -L2tpPsk must be interactive**: Running as SYSTEM (RMM) throws "NonInteractive mode" error. PSK must be registered by an admin in an interactive session. This is a Windows security constraint, not a bug.
- **pst-admin password**: Password had been changed earlier in the session (to SpiritWalk26!). Both pst-admin and mara accounts were reset; mara had an expired password from November 2021.

---

## Problems Encountered

- **Error 789 (IKE auth failed)**: PSK not registered on client — Set-VpnConnection -L2tpPsk needed to be run interactively. Resolved: Mike ran it manually on MaraHomeNew while on-site.
- **Error 800 (remote server not responding)**: UCG Traffic Rules added by Mike were firewall-allow rules, not DNAT. No iptables DNAT existed — packets never reached PST-SERVER. Resolved: Added iptables DNAT rules manually and created /data/on_boot.d/10-vpn-portforward.sh for persistence.
- **Error 691 / RRAS event 20271 (PPP auth denied)**: pst-admin password had been changed to SpiritWalk26! earlier in the session; stale credentials in use. Also required confirming AD msNPAllowDialin and RRAS authorization. Resolved: Used correct password; RRAS/NPS permitted the connection.
- **Stale hosts file entry**: MaraHomeNew (and other machines) had a hosts entry mapping PST-SERVER to 72.194.62.5 (Mara's router's answer when DC was unreachable). ping pst-server and net view pst-server failed even with VPN up. Resolved: Mike identified the hosts entry; GuruRMM script deployed to all four machines to remove it and flush DNS.
- **NRPT namespace empty via registry**: Manual registry write to HKLM:\...\DnsPolicyConfig set the wrong value name — Namespace field was blank. Resolved: Switched to Add-DnsClientNrptRule cmdlet.
- **GuruRMM PowerShell agent invocation issue**: Running shell type "powershell" in RMM failed on PST machines with "-OutputEncoding is not recognized" — agent was not prefixing powershell.exe. Resolved: Used shell type "cmd" and called powershell.exe explicitly in script body.
- **Script body newline encoding**: cmd script body passed with literal \r\n string (not actual CRLF) caused entire script to execute as one line. Resolved: Used printf with actual newlines and jq --arg to properly encode the body.
- **mara account password expired**: Password not changed since November 2021. Resolved: Reset to SpiritWalk26! with PasswordNeverExpires=$true.
- **UCG SSH not accessible from WAN**: SSH to 98.190.129.150 timed out from office. Accessed PST-SERVER and client machines via GuruRMM API instead.

---

## Configuration Changes

### UCG (98.190.129.150 / 192.168.0.10)
- Removed: UCG-hosted VPN (strongSwan/xl2tpd) via UniFi UI
- Created: `/data/on_boot.d/10-vpn-portforward.sh` — persistent iptables DNAT for UDP 500, UDP 4500, ESP to 192.168.0.2
- Added live iptables rules (same as boot script)

### PST-SERVER (192.168.0.2)
- Registry: `HKLM:\SYSTEM\CurrentControlSet\Services\PolicyAgent` — AssumeUDPEncapsulationContextOnSendRule = 2 (DWORD)
- Registry: `HKLM:\SYSTEM\CurrentControlSet\Services\RemoteAccess\Parameters\L2TP` — DefaultPSK = z5zkNBds2V9eIkdey09Zm6Khil3DAZs8
- RRAS: Configured for L2TP/IPsec with PSK; IP pool likely 192.168.0.240+ (observed client got 192.168.0.241)
- AD: pst-admin msNPAllowDialin = allowed; password reset to SpiritWalk26!
- AD: mara password reset to SpiritWalk26!, PasswordNeverExpires = true

### Client machines (MaraHomeNew, Maras-HP-Laptop, PST-SURFACE)
- Created/updated: `C:\ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk` — AllUserConnection "Peaceful Spirit VPN"
  - ServerAddress: 98.190.129.150, TunnelType: L2tp, AuthMethod: MSChapv2, SplitTunneling: true
  - CacheCredentials=1, SaveCredentials=1
- Created: VPN route 192.168.0.0/24 via VPN gateway
- Created: NRPT rule — Namespace: .peacefulspirit.local → NameServers: 192.168.0.2
- Created: Machine credential store entry via cmdkey — target: 98.190.129.150, user: pst-admin, pass: SpiritWalk26!
- Set: L2TP PSK via Set-VpnConnection -L2tpPsk (run interactively by Mike on each machine)
- Removed: hosts file entries for pst-server/peacefulspirit (GuruRMM script); DNS flushed

---

## Credentials & Secrets

| Item | Value |
|------|-------|
| VPN PSK (L2TP) | z5zkNBds2V9eIkdey09Zm6Khil3DAZs8 |
| VPN server (WAN) | 98.190.129.150 |
| VPN user | pst-admin |
| pst-admin password | SpiritWalk26! |
| mara password | SpiritWalk26! |
| UCG LAN | 192.168.0.10 |
| UCG SSH password | Gptf*77ttb123!@ |
| PST-SERVER SSH user | sysadmin |
| PST-SERVER SSH password | r3tr0gradE99! |
| GuruRMM API | http://172.16.3.30:3001 — claude-api@azcomputerguru.com / ClaudeAPI2026!@# |

---

## Infrastructure & Servers

| Host | IP | Role |
|------|----|------|
| UCG-PST-CC | 192.168.0.10 (LAN) / 98.190.129.150 (WAN) | UniFi Cloud Gateway, DNAT for VPN |
| PST-SERVER | 192.168.0.2 | Windows Server 2016 Essentials, DC, RRAS VPN endpoint |
| MaraHomeNew | DHCP (192.168.16.x observed) | Domain workstation, VPN client |
| Maras-HP-Laptop | DHCP | Domain workstation, VPN client |
| PST-SURFACE | DHCP | Domain workstation, VPN client |
| BridgettePSHomeComputer | offline | Domain workstation, VPN pending |
| GuruRMM API | 172.16.3.30:3001 | Remote script execution for PST agents |

VPN IP pool: PST-SERVER assigns from ~192.168.0.240 (observed 192.168.0.241 on MaraHomeNew)
Domain: PEACEFULSPIRIT.local
DC/DNS: 192.168.0.2

---

## Commands & Outputs

### UCG boot persistence script
```sh
#!/bin/sh
iptables -t nat -I PREROUTING -p udp --dport 500 -j DNAT --to-destination 192.168.0.2:500
iptables -t nat -I PREROUTING -p udp --dport 4500 -j DNAT --to-destination 192.168.0.2:4500
iptables -I FORWARD -p udp -d 192.168.0.2 --dport 500 -j ACCEPT
iptables -I FORWARD -p udp -d 192.168.0.2 --dport 4500 -j ACCEPT
iptables -I FORWARD -p esp -d 192.168.0.2 -j ACCEPT
```

### Client VPN deployment script (run via RMM as SYSTEM)
```powershell
Remove-VpnConnection -Name "Peaceful Spirit VPN" -AllUserConnection -Force -ErrorAction SilentlyContinue
Start-Sleep 1
Get-DnsClientNrptRule | Where-Object { $_.Namespace -like "*peacefulspirit*" } | ForEach-Object { Remove-DnsClientNrptRule -Name $_.Name -Force -ErrorAction SilentlyContinue }
Add-VpnConnection -Name "Peaceful Spirit VPN" -ServerAddress "98.190.129.150" -TunnelType L2tp -AuthenticationMethod MSChapv2 -EncryptionLevel Optional -AllUserConnection -SplitTunneling
Add-VpnConnectionRoute -ConnectionName "Peaceful Spirit VPN" -DestinationPrefix "192.168.0.0/24" -AllUserConnection
Set-VpnConnection -Name "Peaceful Spirit VPN" -DnsSuffix "peacefulspirit.local" -AllUserConnection
Add-DnsClientNrptRule -Namespace ".peacefulspirit.local" -NameServers "192.168.0.2"
$pbk = "C:\ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk"
$c = Get-Content $pbk -Raw
$c = $c -replace "CacheCredentials=0", "CacheCredentials=1"
if ($c -notmatch "SaveCredentials=1") { $c = $c -replace "MEDIA=rastapi", "SaveCredentials=1`r`nMEDIA=rastapi" }
Set-Content -Path $pbk -Value $c -NoNewline
& cmdkey /add:98.190.129.150 /user:pst-admin /pass:SpiritWalk26!
```

### PSK registration (MUST run interactively as admin — NOT via RMM)
```powershell
Set-VpnConnection -Name "Peaceful Spirit VPN" -L2tpPsk "z5zkNBds2V9eIkdey09Zm6Khil3DAZs8" -AllUserConnection -Force
```

### PST-SERVER NAT-T registry
```powershell
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\PolicyAgent" -Name "AssumeUDPEncapsulationContextOnSendRule" -Value 2 -Type DWord
```

### GuruRMM agent IDs (PST machines)
| Machine | Agent ID |
|---------|----------|
| PST-SERVER | 6b6106a7-8515-4b6b-857d-0dc6ede53f35 |
| MaraHomeNew | c778b6a3-c646-4454-a065-8c8bdcb1578e |
| Maras-HP-Laptop | 13cb3629-5043-4bd6-b977-6968eeccf804 |
| PST-SURFACE | 4a993b61-59b3-42f4-bdb5-d4362941f7d6 |

### Confirmed working output (MaraHomeNew with VPN connected)
```
PPP adapter Peaceful Spirit VPN:
   IPv4 Address: 192.168.0.241
   DNS Servers: 192.168.0.2, 8.8.8.8
   DNS Suffix: peacefulspirit.local

ping 192.168.0.2: Reply from 192.168.0.2: bytes=32 time=16ms TTL=127
net view 192.168.0.2: [shares listed successfully]
```

---

## Pending / Incomplete Tasks

- **BridgettePSHomeComputer**: Was offline during session. When online:
  1. Run full deployment script via RMM (create VPN profile, routes, NRPT, cmdkey)
  2. Admin must run `Set-VpnConnection -Name "Peaceful Spirit VPN" -L2tpPsk "z5zkNBds2V9eIkdey09Zm6Khil3DAZs8" -AllUserConnection -Force` interactively
  3. Verify ping 192.168.0.2 and name resolution work
- **Pre-login VPN verification**: Confirm VPN auto-connects at Windows login screen on Maras-HP-Laptop and PST-SURFACE (observed working on MaraHomeNew)
- **GuruRMM hosts cleanup script result**: Script ran on all 4 machines but path encoding issue (`driverstc` instead of `drivers\etc`) caused Get-Content to error. DNS was still flushed. Verify no residual hosts entries remain if name resolution issues recur.

---

## Reference Information

- UCG WAN: 98.190.129.150
- UCG SSH: root@98.190.129.150 (key: ~/.ssh/pst-cc-ucg, pass: Gptf*77ttb123!@#) — NOTE: SSH not accessible from office WAN; use GuruRMM or on-site access
- PST-SERVER SSH: sysadmin@192.168.0.2 via ProxyJump root@98.190.129.150 (key: ~/.ssh/pst-cc-ucg)
- GuruRMM API base: http://172.16.3.30:3001
- GuruRMM auth: POST /api/auth/login `{"email":"claude-api@azcomputerguru.com","password":"ClaudeAPI2026!@#"}`
- GuruRMM script run: POST /api/scripts/{script_id}/run `{"agent_id":"<uuid>"}`
- GuruRMM script run results: GET /api/agents/{agent_id}/script-runs?limit=1
- VPN phonebook: C:\ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk
