iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
DevOps

《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》系列 第 15 篇

Day 15 - 解釋 WinRM、PSSession、Invoke-Command

  • 分享至 

  • xImage
  •  

對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。

今天將書中介紹的 WinRM 概覽及個人使用筆記做整理,也將昨天沒有講完的 PSSession 及 Invoke-Command 做個結尾。


一、WinRM(Windows 遠端管理)

1. 什麼是 WinRM?

WinRM(Windows Remote Management)是 Microsoft 基於 WS-Management 通訊協定的實作,用於遠端管理 Windows 系統。它允許你透過網路與遠端電腦通訊,執行指令、存取資料,並進行系統管理。

WinRM 不是僅限於 PowerShell 使用。Microsoft 正逐漸將其應用到更多通訊管理方面,甚至包括目前使用其他協定的事物。基於這個理念,Microsoft 讓 WinRM 能夠把流量導引到多種管理應用程式,而不是只有 PowerShell。WinRM 扮演著調度者的角色:當流量導入時,WinRM 會決定哪個應用程式需要處理這些流量。所有的 WinRM 流量都會被標記上「接收的應用程式( recipient application )的名稱」,而這些應用程式必須向 WinRM 註冊為端點( endpoint ),讓 WinRM 能夠代替它們監聽「傳入的流量」。這意味著你需要在啟用 WinRM 的同時,還要指示 PowerShell 向 WinRM 註冊為一個端點。

你的系統上可能有數十個甚至數百個 WinRM 端點( PowerShell 將他們稱為會話組態,session configuration )。每個端點都能指向不同的應用程式,你甚至可以有多個端點指向同一個應用程式,但是提供不同的權限和功能。

概念示意圖

https://ithelp.ithome.com.tw/upload/images/20240929/20168708itdvrB8tL5.png

Client config

在 Client 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/client 確認 WinRM client 的設定。

  • TrustedHosts:顯示所有設定的受信主機。
  • AllowUnencrypted:確認是否允許未加密的連接,通常應設為 false。
  • 身份驗證設定(Auth):檢查是否啟用了適當的身份驗證方式,如 Negotiate、Kerberos。
PS C:\Users\kanglin> winrm get winrm/config/client
Client
    NetworkDelayms = 5000
    URLPrefix = wsman
    AllowUnencrypted = false
    Auth
        Basic = true
        Digest = true
        Kerberos = true
        Negotiate = true
        Certificate = true
        CredSSP = false
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    TrustedHosts

Server config - service

在 Server 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/service 確認 WinRM Server 端 service 的設定。

PS C:\Users\kanglinserver> winrm get winrm/config/service
Service
    RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
    MaxConcurrentOperations = 4294967295
    MaxConcurrentOperationsPerUser = 1500
    EnumerationTimeoutms = 240000
    MaxConnections = 300
    MaxPacketRetrievalTimeSeconds = 120
    AllowUnencrypted = false
    Auth
        Basic = false
        Kerberos = true
        Negotiate = true
        Certificate = false
        CredSSP = false
        CbtHardeningLevel = Relaxed
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    IPv4Filter = *
    IPv6Filter = *
    EnableCompatibilityHttpListener = false
    EnableCompatibilityHttpsListener = false
    CertificateThumbprint
    AllowRemoteAccess = true

Server config - listener

查看所有 WinRM Listener 的詳細信息

PS C:\Users\kanglinserver> winrm enumerate winrm/config/listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 10.1.1.127, 127.0.0.1, ::1

2. 如何在 Client 端及 Server 端啟用和設定 WinRM?

Client 端(發起連線的電腦)需要設定:

1. 啟用 WinRM:

執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。

Enable-PSRemoting -Force

2. 設定信任的主機 (TrustedHosts):

當 Client 端連接到非同網域的 Server(或工作組環境)時,需要在 Client 端設定 TrustedHosts 允許與指定的遠端電腦進行通訊。

Set-Item WSMan:\localhost\Client\TrustedHosts "遠端電腦的IP或主機名"

3. 檢查連線狀態:

在設定完成後,您可以使用 Test-WsMan 命令來確認是否可以與目標 Server 成功連接。

Test-WsMan -ComputerName 遠端電腦的IP或主機名

Server 端(接受連線的電腦)需要設定:

1. 啟用 WinRM:

執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。

Enable-PSRemoting -Force

2. 確保 WinRM Listener 正常運行:

  • 查看所有 WinRM Listener 的詳細信息
winrm enumerate winrm/config/listener
  • 創建 HTTP Listener
winrm create winrm/config/listener?Address=*+Transport=HTTP
  • 創建 HTTPS Listener (需要 SSL 憑證)
winrm create winrm/config/listener?Address=*+Transport=HTTPS

3. 帳號密碼及權限配置:

確保連接 Server 的帳號有足夠的權限執行所需的遠端命令。通常需要管理員權限,特別是對於執行特定的管理任務。然而 Client 若需要使用不同的帳號來連接 Server,可以使用 -Credential 參數來指定憑證。

範例:使用 Invoke-Command 提供憑證

該範例會跳出輸入帳號密碼的提示字窗

# 取得使用者憑證
$cred = Get-Credential

# 執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }
範例:建立 PSSession 時提供憑證

該範例會跳出輸入帳號密碼的提示字窗

# 取得使用者憑證
$cred = Get-Credential

# 建立 PSSession
$session = New-PSSession -ComputerName "遠端電腦名或IP" -Credential $cred

# 在 PSSession 中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }

# 關閉 PSSession
Remove-PSSession -Session $session
範例:指定使用者名稱和密碼

直接在腳本中指定使用者名稱和密碼,但需要注意安全性。

# 建立安全的密碼字串
$securePassword = ConvertTo-SecureString "您的密碼" -AsPlainText -Force

# 建立憑證物件
$cred = New-Object System.Management.Automation.PSCredential("使用者名稱", $securePassword)

# 使用憑證執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }

二、PSSession(PowerShell 會話)

1. 什麼是 PSSession?

PSSession 是一個與遠端電腦建立的持久連線,允許您在該連線中執行多個指令,而不必每次都重新建立連線。這在需要執行多個指令時可以提高效率。

Client 與 Server 透過 PSSession 的交互過程

https://ithelp.ithome.com.tw/upload/images/20240929/20168708UArs38dpOW.png

  1. Initiate PSSession( 發起 PSSession ):
    Client 端的 PowerShell 發出建立 PSSession 的請求,例如 New-PSSession 或 Invoke-Command,在這一步,Client 開始嘗試與 Server 端建立連結,並準備進行驗證。
  2. TCP 連接初始化:
    • TCP Connection SYN:Client 向 Server 發送一個 SYN(同步)請求( 標準的 TCP 三項交握第一步)。
    • TCP Connection SYN ACK:Server 收到 SYN 請求後,回應一個 SYN ACK(同步應答)消息,表示它已經準備好接受連接。
    • TCP Connection ACK:Client 端再次發送一個 ACK(確認)消息,最終完成三次握手,並正式建立 TCP 連接。
  3. 身份驗證請求:
    • Authentication HTTP POST:TCP 連接建立後,Client 端會發送一個身份驗證請求( HTTP POST )。這一步通常涉及使用 WinRM 協議進行身份驗證,例如 Kerberos、NTLM 或其他協商身份驗證方式。
    • Authentication POST Response:Server 收到身份驗證請求後,會對其進行驗證,然後回應驗證結果。如果身份驗證成功,Client 端即可與 Server 建立會話。
  4. PSSession Initiated(PSSession 建立):
    驗證成功後,PSSession 正式建立,這個會話允許 Client 端向 Server 端傳送 PowerShell 命令並接收回應。
  5. PowerShell Command(發送 PowerShell 指令):
    一旦 PSSession 建立,Client 端可以發送遠端 PowerShell 指令,這些指令會透過已建立的 PSSession 來執行。
  6. PowerShell Command Output(返回 PowerShell 指令輸出):
    Server 端執行完指令後,會將執行結果通過 PSSession 回傳給 Client 端,並在 Client 的 PowerShell 中顯示結果。

2. 如何建立和管理 PSSession?

建立一個新的 PSSession:

$session = New-PSSession -ComputerName 遠端電腦的IP或主機名

查看當前的 PSSession:

Get-PSSession

在 PSSession 中執行指令:

Invoke-Command -Session $session -ScriptBlock { Get-Process }

進入 PSSession(互動式):

Enter-PSSession -Session $session

退出 PSSession:

在互動式會話中,輸入 Exit-PSSession 或簡寫 Exit。

關閉 PSSession:

Remove-PSSession -Session $session

3. 範例

範例:在遠端電腦上獲取服務列表

# 建立 PSSession
$session = New-PSSession -ComputerName 192.168.1.100

# 在遠端會話中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }

# 關閉 PSSession
Remove-PSSession -Session $session

三、Invoke-Command

1. 什麼是 Invoke-Command?

  • Invoke-Command cmdlet 用於在本地或遠端電腦上執行命令,並返回命令的所有輸出,包含錯誤訊息。
  • 可以使用一條 Invoke-Command 命令對多台電腦執行指令。
PS /Users/kanglin/code/30days> get-help Invoke-Command | more

NAME
    Invoke-Command

SYNOPSIS
    Runs commands on local and remote computers.

主要應用場景:

  • 遠端執行單一命令:
    使用 -ComputerName 在一台遠端電腦上運行單個命令。
  • 多次命令的遠端會話:
    使用 New-PSSession 建立持久會話,然後使用 -Session 在會話中多次執行命令,適合多命令操作。
  • 跨多平台的遠端管理:
    通過 SSH 進行跨平台(Windows、Linux、macOS)的遠端管理操作。

2. 如何使用 Invoke-Command?

在遠端電腦上執行指令:

Invoke-Command -ComputerName 遠端電腦的IP或主機名 -ScriptBlock { 指令或腳本區塊 }

使用 PSSession:

Invoke-Command -Session $session -ScriptBlock { 指令或腳本區塊 }

對多台電腦執行指令:

Invoke-Command -ComputerName PC1,PC2,PC3 -ScriptBlock { 指令或腳本區塊 }

3. 範例

範例:在多台遠端電腦上重啟服務

$computers = @("Server1", "Server2", "Server3")

Invoke-Command -ComputerName $computers -ScriptBlock { Restart-Service -Name "Spooler" }

範例:從本地腳本執行遠端指令

假設有一個本地腳本 C:\Scripts\Task.ps1,需要在遠端電腦上執行。

Invoke-Command -ComputerName 192.168.1.100 -FilePath "C:\Scripts\Task.ps1"

四、遠端命令與本機命令的差異

在遠端執行命令時,存在一些與本地執行的差異,需要特別注意。

反序列化物件

遠端命令返回的物件是「反序列化」的,這意味著它們僅包含屬性值,而沒有方法。這可能影響您對物件的操作,例如無法調用方法或修改屬性。

本機處理 vs. 遠端處理

為了提高效率,應盡量在遠端完成資料處理,減少傳輸到本地的數據量。例如,以下做法更有效:

遠端處理:

Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System | Where-Object { $_.EventID -eq 100 } }

本地處理(效率較低):

$events = Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System }
$filteredEvents = $events | Where-Object { $_.EventID -eq 100 }

在遠端進行過濾可以減少網路流量,提高執行速度。


參考文章

對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。
WinRM - setup and test on Windows laptop
Windows Remote Management Architecture
Powershell tricks—Powershell Remoting
about_PSSessions
PowerShell Remoting (PSRemoting) Explained: Ultimate Guide


明日主題

Day 16 - 利用背景作業進行多工處理


上一篇
Day 14 - 關於 PowerShell 遠端控制
下一篇
Day 16 - 利用背景作業進行多工處理
系列文
《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言