WS 2016對WS 2016的PSRemoting的Access is denied錯誤

WS 2016對WS 2016的PSRemoting的Access is denied錯誤

在導入 Docker for Windows 之後,使用 PowerShell 的比重越來越高,而且在 CD(持續發布)的過程,也相當依賴 PowerShell 來進行作業。平常,可以透過 Docker CLI 來直接對 Docker Host 來下達指令(docker -H host command)。但今天如果是要直接對 Windows Server 下達 PowerShell 指令,也就是,我在 A 電腦直接透過指令視窗對 B 電腦下 PowerShell 指令,而非使用遠端桌面,那麼可以使用 PSRemoting。

PSRemoting

PowerShell 要讓其他電腦可以連線下達指令的功能稱 PSRemoting,一般而言,在接收指令的主機執行 Enable-PSRemoting 之後,在下指令的電腦就可以用 Enter-PSSession -Computer computerName -Credential $cred 來進行連線。(其他 Firewall、User Group 設定細節,請參考微軟文件。)

WS2016 ⇆ WS2016 PSRemoting 無法連線

在啟用與測試的過程,我們發現一個好玩的現象,Windows 10、Windows Server 2012、Windows Server 2016 互相進行 PSRemoting 連線時,特定的 WS2016 → WS2016 無法互連,方向只有單方,例如,兩台都已經 Enable-PSRemoting 的 WS2016 主機,A → PSRemoting → B 正常,但 B → PSRemoting → A 無法連線。

Get-PSSession : The remote session query failed for hostname with the following error message: Access is denied.
At line:1 char:1
+ Get-PSSession -ComputerName hostname
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Manageme...nConnectionInfo:WSManConnectionInfo) [Get-PSSession], RuntimeException
    + FullyQualifiedErrorId : AccessDenied,RemotePSSessionQueryFailed,Microsoft.PowerShell.Commands.GetPSSessionCommand

微軟官方有一篇 About Remote Troubleshooting 寫的算是詳細(另有一篇 如何執行遠端 PowerShell Script 也寫的不錯),不過,用盡網路上找得到的方式,還是解不了是 B to A 無法連線的問題。由於關係到工作,最後選擇開 Microsoft Support Case 請求幫助。

Microsoft Support

以下記錄一下尋找問題點的步驟與工具:

  1. 使用 WebEx 連線,查明問題點。

用以連入公司內網,驗證兩台主機的 PSRemoting 的問題。

  1. 使用 Network Monitor 3.4 取得封包資訊

A to B 當然不會有問題。B to A 看不到正常身份驗證的封包。

  1. 使用 logman 取得 Trace 資訊

第一次取得:

  • ds_security.etl
  • net_netio.etl

第二次取得:

  • admin_wmi.etl
  1. 使用 Process Monitor 取得事件日誌

取得 PSRemoting 事件發生當下的資訊。

  1. TTTracer 取得 PID dump file

用來取得 PowerShell 的 PID 的 dump 資訊。

生也 Proxy、死也 Proxy

最後由 Process Monitor 找到的 B to A 的 PowerShell 在進行 PSRemoting 當下會先進行 Proxy 連線,而 A to B 則沒有。

powershell ProcMon

這是 B 主機虛擬資訊:

PS C:\> netsh winhttp show proxy

Current WinHTTP proxy settings:

    Proxy Server(s) :  proxy.example.com:80
    Bypass List     :  

A 主機虛擬資訊:

PS C:\> netsh winhttp show proxy

Current WinHTTP proxy settings:

    Direct access (no proxy server). 

趕快找一台有問題 WS2016 的 C 主機:

PS C:\> netsh winhttp show proxy

Current WinHTTP proxy settings:

    Proxy Server(s) :  proxy.example.com:80
    Bypass List     :  *.example.com
PSRemoting Proxy

這台 C 主機的設定與 B 主機有一點點差異,多了 Bypass,如果以短名稱進行 PSRemoting 就會取得 Access is denied 錯誤。如改為**完整網域名稱(FQDN)**進行連線,因為符合 Bypass 名稱就不會跑到 Proxy,就能完成正常的 PSRemoting 連線。

  • 在 Proxy 環境,要設定 Bypass List。
  • 連線需使用 FQDN。
  • 這個情況只有在 WS2016 ⇆ ws2016 會出現。

看似簡單的問題,由於不良的錯誤的訊息及難以得知 PowerShell 底層處理細節(PowerShell Core 有開源,但 PowerShell 沒有),追起來費工費時,還在最後在神器 Process Monitor 幫助下,查了近二個月的案子終於可以結案了。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。