Last active
September 22, 2023 22:29
-
-
Save archmangler/1de3be6a95400bce427008e04e53e26f to your computer and use it in GitHub Desktop.
PowerShell Remoting from Linux to Windows (DNS Server Configuration)
This file contains 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
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