Skip to content

Instantly share code, notes, and snippets.

@archmangler
Last active September 22, 2023 22:29
Show Gist options
  • Save archmangler/1de3be6a95400bce427008e04e53e26f to your computer and use it in GitHub Desktop.
Save archmangler/1de3be6a95400bce427008e04e53e26f to your computer and use it in GitHub Desktop.
PowerShell Remoting from Linux to Windows (DNS Server Configuration)
Overview
========
This is a set of notes I kept resulting in development of a terraform module wrapper to configure windows DNS.
(Original gist location: https://gist.github.com/1de3be6a95400bce427008e04e53e26f)
Objective:
=========
1. Configuration of DNS on Windows Server ("Windows DNS server")
2. From a Linux Server (CentOS or Ubuntu)
3. Using Powershell (Linux distribution of Powershell based on .Net Core)
4. Via PowerShell Remoting (SSH-based connection to MS Windows)
High Level Design
=================
```
- The current DNSServer PowerShell module that is in Windows is specific to managing Windows DNS Server and wouldn't work on Linux.
- If you want to manage Windows DNSServer using the PowerShell module from Linux, you can do this via PowerShell remoting.
- Using implicit remoting you can run scripts locally on Linux that actually execute remotely on the Windows target (after setting up the PSSession).
- If the ask is to manage Linux DNS servers, then that would need to be a completely different module that someone would have to author.
```
Design Issue List:
==================
1. https://github.com/PortOfPortland/terraform-provider-windns/issues/4
2. https://github.com/PowerShell/PowerShell/issues/8011
3. https://github.com/MicrosoftDocs/windows-powershell-docs/issues/318
4. https://github.com/PortOfPortland/terraform-provider-windns/issues/2
5. https://github.com/PortOfPortland/terraform-provider-windns/issues/3
6. https://github.com/Microsoft/PowerShell-DSC-for-Linux/issues/444
7. https://github.com/elliottsam/winrm-dns-client/issues/5
Questions:
==========
1. Does implicit remoting via SSH work Linux to Windows? (CONFIRMED)
1.1 can authentication be completed? (CONFIRMED)
1.2 can connection be established (CONFIRMED)
1.2 can commands be executed on remote system? (CONFIRMED)
2. Can the powershell script be copied from Linux to Windows to the Powershell env in Windows and executed in the Powershell environment? (TESTING)
3. Can the script be executed in the remote powershell environment? (TESTING)
Task Breakdown
==============
0. Determine if PSShell Remoting on Linux is possible
0.1 research validation:
[x] PowerShell Remoting: https://dejanstojanovic.net/powershell/2018/june/remote-powershell-core-session-to-a-linux-host-from-windows-machine/
[x] PowerShell Remoting: https://docs.microsoft.com/en-us/powershell/scripting/core-powershell/ssh-remoting-in-powershell-core?view=powershell-6
[x] Implicit Remoting: https://technet.microsoft.com/en-us/library/ff720181.aspx
[x] Implicit Remoting: https://4sysops.com/archives/using-powershell-implicit-remoting/
[x] Implicit Remoting Linux to Windows:
[x] https://4sysops.com/archives/powershell-remoting-between-windows-and-linux/
[x] https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-powershell-core-on-linux?view=powershell-6
[x] https://4sysops.com/archives/use-powershell-invoke-command-to-run-scripts-on-remote-computers/#executing-cmdlets-with-invoke-command
1. Deploy Windows DNS server
- For labbing the solution.
1.1 Options:
1.1.1 Automated: Obtain Packer / IAC method of deploying Windows DNS Server for virtualbox
1.1.2 Manual: Obtain ISO and install in VirtualBox lab
- turns out this demands a substantial amount of ram and decent disk IO, so best to use a cloud VM here instead of a 2012 model macbook pro!
1.2 setup and test DNS configuration on Windows DNS Server (create a default test zone)
- Powershell command sequence for setup and configuration (handy for a linux admin who knows nothing about windows :-) )
1) Rename computer : Rename-Computer -NewName "windns" -Restart
2) Install DNS features : Install-WindowsFeature -Name DNS -IncludeAllSubFeature -IncludeManagementTools
3) List Modules : Get-Command -Module DNSServer | Select-Object -Property Name
4) Add-DnsServerPrimaryZone -Name "engeneon.local" -ZoneFile "engeneon.local.dns" -DynamicUpdate None
5) Restart-Service -Name DNS -Force
6) Add an A records : Add-DnsServerResourceRecordA -Name "linux01" -ZoneName "engeneon.local" -AllowUpdateAny -IPv4Address "10.0.2.100" -TimeToLive 01:00:00
7) Validate what we create: Get-DnsServerResourceRecord -ZoneName 'engeneon.local' -Name 'linux01' | Format-Table -AutoSize
2. Install Powershell on Linux
2.1 Test setup of PSSession
- configured in /etc/ssh/sshd_config
3. Configure PowerShell Remoting
3.1 On Windows : Enable Powershell Remoting
3.1.1 Install OpenSSH On windows
- update links first:
```
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = 'https://github.com/PowerShell/Win32-OpenSSH/releases/latest/'
$request = [System.Net.WebRequest]::Create($url)
$request.AllowAutoRedirect=$false
$response=$request.GetResponse()
$([String]$response.GetResponseHeader("Location")).Replace('tag','download') + '/OpenSSH-Win64.zip'
$([String]$response.GetResponseHeader("Location")).Replace('tag','download') + '/OpenSSH-Win32.zip'
```
- Download the above 2 links as follows:
```
Invoke-WebRequest -Uri $url -OutFile $output
Expand-Archive file.zip -DestinationPath <whatever>
```
- Install:
(https://4sysops.com/archives/enable-powershell-core-6-remoting-with-ssh-transport/)
```
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
#Open the firewall for sshd.exe to allow inbound SSH connections
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
net start sshd
```
- IF YOUR POWERSHELL IS OUT OF DATe (5 and down): Upgrade or Install powershell 6.x
- https://github.com/PowerShell/PowerShell/releases/download/v6.1.0/PowerShell-6.1.0-win-x64.msi
But you'll run into this:
- https://www.theregister.co.uk/2016/08/23/your_wget_is_broken_and_should_die_powershellers_tell_microsoft/
- Configure Powershell Remoting on Windows:
```
Subsystem powershell pwsh -sshs -NoLogo -NoProfile
$env:Path="$env:Path;C:\Program Files\OpenSSH\"
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $env:Path
Subsystem powershell c:/program files/powershell/6.0.4/pwsh.exe -sshs -NoLogo -NoProfile
```
```
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = 'https://github.com/PowerShell/PowerShell/releases/download/v6.1.0/PowerShell-6.1.0-win-x64.msi'
$request = [System.Net.WebRequest]::Create($url)
$request.AllowAutoRedirect=$false
$response=$request.GetResponse()
```
```
PS C:\Program Files\OpenSSH> Enter-PSsession -HostName windns -SSHTransport
Administrator@WINDNS@windns's password:
Administrator@WINDNS@windns's password: Enter-PSsession : The background process reported an error with the following message: The SSH client session has ended with error message: Permission denied, please try again..
At line:1 char:1
+ Enter-PSsession -HostName windns -SSHTransport
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [Enter-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : System.Management.Automation.Remoting.PSRemotingDataStructureException,Microsoft.PowerShell.Commands.EnterPSSessionCommand
PS C:\Program Files\OpenSSH>
```
New-LocalUser "dnsadmin" -Password "#########" -FullName "ssh test user" -Description "ssh test account"
```
$session = New-PSSession -HostName windns -UserName dnsadmin ‑SSHTransport
Invoke-Command -Session $session -ScriptBlock {get-proc}
```
```
$pw = convertto-securestring -AsPlainText -Force -String Cr4ckWh0r##
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "Domain\User",$pw
$session = new-pssession -computername windns-credential $cred
```
```
$env:Path="$env:Path;C:\Program Files\OpenSSH\"
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $env:Path
New-NetFirewallRule -DisplayName 'SSH Inbound' -Profile @('Domain', 'Private', 'Public') -Direction Inbound -Action Allow -Protocol TCP ‑LocalPort 22
```
```
Invoke-Command -Session $session -ScriptBlock {get-process}
```
Issues:
1. Need to have access to the CIM server (at or near administrator level)
```
PS C:\Users\dnsadmin> Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.local" -AllowUpdateAny -IPv4Address "10.0.2.9" -TimeToLive 01:00:00
Add-DnsServerResourceRecordA : Cannot connect to CIM server. Access denied
At line:1 char:1
+ Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.loca ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (PS_DnsServerResourceRecordA:String) [Add-DnsServerResourceRecordA], CimJob
Exception
+ FullyQualifiedErrorId : CimJob_BrokenCimSession,Add-DnsServerResourceRecordA
```
2.
```
I've configured powershell implicit remoting using SSH on MS Windows 2016, with powershell 6 and OpenSSH.
I can ssh from the host to itself from the cmd shell, so it appears firewall rules and ssh configuration along with authentication and user permissions are correct:
- Login with test user:
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
dnsadmin@WINDNS C:\Users\dnsadmin>exitConnection to windns closed.
PS C:\Windows\system32> ssh dnsadmin@windns
dnsadmin@windns's password:
- Firewall configuration:
PS C:\Windows\system32> netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22
Ok.
However the session hangs indefinitely, without any information as to why:
PS C:\Users\Administrator> $session = New-PSSession -HostName windns -UserName dnsadmin -SSHTransport
dnsadmin@windns's password:
Is there any means of debugging this in more detail to understand how to fix this?
My sshd configuration looks like this:
Subsystem powershell c:/Program Files/PowerShell/6/pwsh.exe -sshs -NoLogo -NoProfile
Looking at the sshd logs I see the authentication was successful:
1312 2018-10-14 04:53:53.942 debug1: attempt 1 failures 0 [preauth]
1312 2018-10-14 04:53:53.942 debug1: keyboard-interactive devs [preauth]
1312 2018-10-14 04:53:53.942 debug1: auth2_challenge: user=dnsadmin devs= [preauth]
1312 2018-10-14 04:53:53.942 debug1: kbdint_alloc: devices '' [preauth]
1312 2018-10-14 04:54:06.412 debug1: userauth-request for user dnsadmin service ssh-connection method password [preauth]
1312 2018-10-14 04:54:06.412 debug1: attempt 2 failures 1 [preauth]
1312 2018-10-14 04:54:06.412 Accepted password for dnsadmin from fe80::d47b:fb40:76fd:3974%5 port 49689 ssh2
1312 2018-10-14 04:54:06.412 debug1: monitor_child_preauth: dnsadmin has been authenticated by privileged process
1312 2018-10-14 04:54:06.412 debug1: monitor_read_log: child log fd closed
1312 2018-10-14 04:54:06.522 User child is on pid 1552
1312 2018-10-14 04:54:06.632 debug1: do_cleanup
```
- On the client side:
```
PS /home/gmonkey> $session = New-PSSession -HostName windns -UserName dnsadmin -SSHTransport
The authenticity of host 'windns (10.0.2.9)' can't be established.
ECDSA key fingerprint is SHA256:WYqtWsFpvh4HzqJxwkn9686Np7ZUTIJkc4r2abUxmvo.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'windns,10.0.2.9' (ECDSA) to the list of known hosts.
dnsadmin@windns's password:
PS /home/gmonkey>
```
- Remote command:
```
PS /home/gmonkey> Invoke-Command -Session $session -ScriptBlock {get-process} | tail
19 8.72 13.25 0.00 2228 0 svchost windns
0 0.12 0.13 0.00 4 0 System windns
11 1.84 9.56 0.00 684 1 taskhostw windns
10 1.96 7.23 0.00 768 0 VBoxService windns
12 2.05 8.93 0.00 2032 1 VBoxTray windns
8 0.86 5.03 0.00 440 0 wininit windns
11 2.35 9.72 0.00 472 1 winlogon windns
4 0.57 3.21 0.00 1272 0 wlms windns
```
- Simple script:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> cat ./poc.ps1
$out = Get-Process | Get-Member -MemberType Method
echo $out
```
Run via PSSremote session:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> Invoke-Command -Session $session -FilePath ./poc.ps1
TypeName: System.Diagnostics.Process
Name MemberType Definition PSComputerName
---- ---------- ---------- --------------
BeginErrorReadLine Method void BeginErrorReadLine() windns
BeginOutputReadLine Method void BeginOutputReadLine() windns
CancelErrorRead Method void CancelErrorRead() windns
CancelOutputRead Method void CancelOutputRead() windns
Close Method void Close() windns
CloseMainWindow Method bool CloseMainWindow() windns
Dispose Method void Dispose(), void IDisposable.Dispose() windns
Equals Method bool Equals(System.Object obj) windns
GetHashCode Method int GetHashCode() windns
GetLifetimeService Method System.Object GetLifetimeService() windns
GetType Method type GetType() windns
InitializeLifetimeService Method System.Object InitializeLifetimeService() windns
Kill Method void Kill() windns
Refresh Method void Refresh() windns
Start Method bool Start() windns
ToString Method string ToString() windns
WaitForExit Method void WaitForExit(), bool WaitForExit(int milliseconds) windns
WaitForInputIdle Method bool WaitForInputIdle(), bool WaitForInputIdle(int milliseconds) windns
```
- Carry out DNS Operations
--- dns-config.ps1 ---
Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.local" -AllowUpdateAny -IPv4Address "10.0.2.9" -TimeToLive 01:00:00
----
```
1) authenticate and get session : $session = New-PSSession -HostName windns -UserName dnsadmin -SSHTransport
```
dnsadmin@windns's password: book/examples/windows-dns> $session = New-PSSession -HostName windns -UserName dnsadmin -SSHTransport
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns>
```
2) run local shell script on remote machine : Invoke-Command -Session $session -FilePath ./dns-config.ps1
Get current configuration:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns/scripts> Invoke-Command -Session $session -FilePath ./dns-getrecords.ps1
HostName RecordType Type Timestamp TimeToLive
-------- ---------- ---- --------- ----------
@ NS 2 0 01:00:00
@ SOA 6 0 01:00:00
linux01 A 1 0 01:00:00
```
3) Add DNS management commands:
(Reference: https://www.adamtheautomator.com/manage-dns-records-via-powershell-here-is-how/)
```
Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.local" -AllowUpdateAny -IPv4Address "10.0.2.9" -TimeToLive 01:00:00
```
- Enable remoting for WinRM (if necessary only!)
(You might need this: "Install-WindowsFeature -IncludeAllSubFeature RSAT" ... Then again, you might not)
```
PS C:\ProgramData\ssh> Enable-PSRemoting -Force
WinRM is already set up to receive requests on this computer.
WinRM has been updated for remote management.
Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users.
```
3.2 On Linux : Configure PS remoting in SSHD
[done]
3.3 On Linux : Create working PSSession
[done]
3.3 On Linux : Run dummy script on remote windows server via PSremote
[done]
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> Invoke-Command -Session $session -File ./poc.ps1| head
TypeName: System.Diagnostics.Process
Name MemberType Definition PSComputerName
---- ---------- ---------- --------------
BeginErrorReadLine Method void BeginErrorReadLine() windns
BeginOutputReadLine Method void BeginOutputReadLine() windns
CancelErrorRead Method void CancelErrorRead() windns
CancelOutputRead Method void CancelOutputRead() windns
```
4. Configure DNS Via PowerShell Remoting
4.0 Create default Zone and test manual creation/deletion
- Run a simple dns configuration command:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> Invoke-Command -Session $session -File ./dns-config.ps1
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> cat ./dns-config.ps1
powershell Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.local" -AllowUpdateAny -IPv4Address "10.0.2.9" -TimeToLive 01:00:00
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns>
```
Check Records:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> Invoke-Command -Session $session -File ./dns-getrecords.ps1
HostName RecordType Type Timestamp TimeToLive
-------- ---------- ---- --------- ----------
@ NS 2 0 01:00:00
@ SOA 6 0 01:00:00
linux01 A 1 0 01:00:00
```
- Confirm the created DNS record exists:
```
administrator@WINDNS C:\Users\Administrator>powershell Add-DnsServerResourceRecordA -Name "linux02" -ZoneName "engeneon.local" -
AllowUpdateAny -IPv4Address "10.0.2.9" -TimeToLive 01:00:00
Add-DnsServerResourceRecordA : Failed to create resource record linux02 in zone engeneon.local on server WINDNS.
At line:1 char:1
+ Add-DnsServerResourceRecordA -Name linux02 -ZoneName engeneon.local - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceExists: (linux02:root/Microsoft/...ResourceRecordA) [Add-DnsServerResourceRecordA], CimE
xception
+ FullyQualifiedErrorId : WIN32 9711,Add-DnsServerResourceRecordA
```
4.1 Deletion/Creation of A records (in existing zone)
- Remove the record:
Script:
```
powershell Remove-DnsServerResourceRecord -ZoneName "engeneon.local" -RRType "A" -Name "linux02" -Force
```
Execute:
```
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns> Invoke-Command -Session $session -File ./dns-remove.ps1
PS /home/gmonkey/Ship/tf4te-book/examples/windows-dns>
```
4.2 Deletion/Creation of CNAME records (in existing zone)
[done]
4.3 Creation/Deletion of PTR records
[done]
5. Wrap DNS Configuration in Terraform
5.1 Create a Provider for Windows 2016/2012/10
In Go: https://www.terraform.io/docs/extend/writing-custom-providers.html
5.2 Create module accepting parameters
5.3 Option B: Create a null provider based terraform module generating templated script to configure Terraform
6. Configure DNS idempotently via TerraForm
6.1 Deletion/Creation of A records (in existing zone)
6.2 Deletion/Creation of CNAME records (in existing zone)
6.3 Creation/Deletion of PTR records
Notes:
======
1. Automated setup of MS Windows DNS Server (Win 10? Server 2012 , 2016?)
1.1 Basic DNS Server setup (Windows 2016): https://www.businessnewsdaily.com/11019-set-up-configure-dns-on-windows-server-2016.html
1.2 Setup in virtualBox: https://blog.couchbase.com/windows-server-2016-using-virtualbox-getting-ready-docker/
Reference Materials
===================
1. Powershell field notes:
1.1 PowerShell in general : https://www.stuartellis.name/articles/powershell/
1.2 DNS Server setup on windows : https://www.microsoftpressstore.com/articles/article.aspx?p=2756482&seqNum=2
1.3 https://4sysops.com/archives/use-powershell-invoke-command-to-run-scripts-on-remote-computers/#executing-cmdlets-with-invoke-command
1.4 https://4sysops.com/archives/powershell-remoting-without-administrator-rights/
2. PS Remoting Test Script
```
$session = New-PSSession -HostName 10.0.2.9 -UserName Administrator -SSHTransport
Invoke-Command -Session $session -FilePath ./dns-getrecords.ps1
```
- with password non-interactive:
```
$pw = convertto-securestring -AsPlainText -Force -String Cr4ckWh0r##
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist Administrator,$pw
$session = New-PSSession -ComputerName windns -Credential $cred -SSHTransport
```
Enter-PSsession windns-UserName Administrator ‑SSHTransport
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment