顯示具有 ssh 標籤的文章。 顯示所有文章
顯示具有 ssh 標籤的文章。 顯示所有文章

2025年6月26日 星期四

在 pwsh 中使用 Remoting 連入 linux

在 pwsh 中使用 Remoting 連入 linux

用習慣 pwsh 有時候沒要幹嘛只是做一點點事情,直接用 pwsh 會比較快,真的要做比較複雜的事情還是切 bash 好,因為網上的教學是以 bash 為主的。



linux 端的設定1:: 安裝 pwsh

安裝 pwsh 可以參考微軟的網站有教學
Installing PowerShell on Ubuntu - PowerShell | Microsoft Learn


範例用從 github 下載的方式 (因為我是安裝在 pi5 上)

載點記得選 gihub 上自己合適的系統與版本,我的是 arm64 如果一般選 x64 即可

# 下載
wget https://github.com/PowerShell/PowerShell/releases/download/v7.5.2/powershell-7.5.2-linux-arm64.tar.gz

# 刪除舊內容
sudo rm -rf /opt/powershell/7/*

# 解壓縮
sudo tar -xzf ~/powershell-7.5.2-linux-arm64.tar.gz -C /opt/powershell/7

# 建立連結
sudo ln -sf /opt/powershell/7/pwsh /usr/local/bin/pwsh

# 賦予執行權
sudo chmod +x /opt/powershell/7/pwsh

# 執行
pwsh

到這邊就可以正常執行

手動安裝差在沒辦法透過 apt-get 自動升級版本,好處是可以裝到最新板的。



linux 端的設定1:: 設定 ssh 的子系統

在 linux 端打開 Subsystem 即可 (不用像 Win 需要啟動 WinRM)

先到SSH設定中

sudo nano /etc/ssh/sshd_config

拉到最下面找到 # override default of no subsystems 這個註解
下面可能有 sftp 範例但是不管手動加上這行就行

Subsystem powershell    /usr/local/bin/pwsh -sshs -NoLogo

存檔後就設定好了



pwsh 連接方法

在連接之前先確保 ssh 金鑰已經配置完畢,可以無密碼登入,然後使用下面的指令連接

Enter-PSSession -HostName 192.168.3.88 -UserName chg

連入之後會長這個樣子




2025年2月4日 星期二

PowerShell 使用 ssh 驗證本地與遠端檔案的 SHA256 是否一致

PowerShell 使用 ssh 驗證本地與遠端檔案的 SHA256 是否一致

要驗證傳輸到底有沒有傳對用的函式

# 獲取遠端檔案的雜湊值
function Get-RemoteFileHash {
    [CmdletBinding()]
    param ( 
        # 遠端檔案路徑
        [Parameter(Mandatory, ValueFromPipeline)]
        [string]$Path,
        # 遠端登入資訊
        [Parameter(Mandatory)]
        [string]$RemoteLoginInfo,
        # 遠端私鑰
        [Parameter(Mandatory)]
        [string]$IdentityFile,
        # 遠端作業系統
        [Parameter(Mandatory)]
        [ValidateSet('Windows', 'Linux')]
        [string]$RemoteOS
    ) begin {
        # 檢查私鑰是否存在
        if (-not (Test-Path $IdentityFile)) {
            Write-Error "Cannot find path '$IdentityFile' because it does not exist."
        }
        # 定義不同作業系統的雜湊命令
        $hashCommands = @{
            'Windows' = "powershell `"(Get-FileHash -Path ([WildcardPattern]::Escape('$Path')) -Algorithm SHA256 -EA 1).Hash`""
            'Linux'   = "sha256sum '$Path' 2>&1 >/dev/null && sha256sum '$Path' | cut -d' ' -f1 | tr '[:lower:]' '[:upper:]'"
        }
        # SSH 連線參數設定
        $sshParams = @(
            '-oBatchMode=yes'
            "-oIdentityFile=$IdentityFile"
            $RemoteLoginInfo
        )
    } process {
        # 執行遠端雜湊命令
        $hash = & ssh @sshParams $hashCommands[$RemoteOS] 2>&1
        # 檢查 ssh 命令是否成功
        if ($LASTEXITCODE -ne 0) {
            Write-Error "ssh command failed: $hash" 
            return $null
        }
        # 檢查雜湊值格式是否正確 (SHA-256 應為 64 個十六進制字符)
        if (-not ($hash -match '^[A-F0-9]{64}$')) {
            Write-Error "The hash value '$hash' returned from command '$hashCommand' is not a valid SHA-256 format"
            return $null
        }
        return $hash
    }
}


使用範例

Get-RemoteFileHash "/home/chg/work/Tester.bats" `
    -RemoteLoginInfo "chg@192.168.3.53" `
    -IdentityFile "${env:USERPROFILE}\.ssh\id_ed25519" `
    -RemoteOS "Linux"

執行完會自動返回遠端檔案的哈希值,再來比較本地端即可知道是否一致了。


更進階的可以讓這個函式再跟自動判斷組合
CHG: 如何僅利用 sftp 判斷對方是 unix 還是 win




如果是要從 sftp 指令腳本中,獲取傳輸的路徑可以參考這個

# 解析 SFTP 命令
function ParseSftpCommandPath {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline)]
        [string]$CommandText
    )
    process {
        # 跳過空行和註解
        if (-not ($CommandText -match '\S') -or $CommandText -match '^\s*#') { return }
        # 解析命令行
        $tokens = [regex]::Matches(
            $CommandText.Trim(), '"[^"]+"|[^\s"]+'
        ).Value.Trim('"')
        # 獲取遠端檔案路徑
        if ($tokens[0] -in 'get','put') {
            $paths = $tokens[1..($tokens.Count-1)].Where({ $_ -notmatch '^-' })
            $idx = @{
                'get' = @{local=-1; remote=0}
                'put' = @{local=0; remote=-1}
            }[$tokens[0]]
            [PSCustomObject]@{
                Command = $tokens[0]
                LocalPath = $paths[$idx.local]
                RemotePath = $paths[$idx.remote]
            }
        }
    }
} # "get /home/chg/work/Tester.bats Tester.bats" | ParseSftpCommandPath




2024年5月29日 星期三

WSL 安裝 ssh 並更改 port 設置自動啟動 (包含私鑰設置方法)

WSL 安裝 ssh 並更改 port 設置自動啟動

預設狀態是不會自動啟動的而且 port 可能與主機端有衝突,視情況可以自行改成 2222 口這樣可以避開 Windows 本身如果也有 ssh 的話。

教學用的環境是 Win11 24H3 上安裝的 WSL2 虛擬機運行 Ubuntu 24 版本。版本不同可能會些許的差異。



安裝並配置 OpenSSH

首先,確保 WSL 中已安裝 OpenSSH 伺服器:

sudo apt update
sudo apt install openssh-server


1. 設定 SSH 端口與密碼登入 (選用)

編輯 SSH 設定檔:

sudo nano /etc/ssh/sshd_config

在此可以修改你要的設定如果你不知道要改什麼跳過這個步驟即可。


2. 設定 SSH 伺服器開機自動啟動

設置 systemd 服務管理器:(必須要wsl2才支援)

sudo systemctl enable ssh

必須開著 WSL 視窗才會生效(這服務 systemctl 其實是由 wsl.conf 文件間接啟動的)


如果是舊版的 wsl 1 不支持 systemctl 請這裡編輯 /etc/wsl.conf 文件:

sudo nano /etc/wsl.conf

在文件末尾添加以下內容:

command="service ssh start"

保存文件(按 Ctrl + O),然後退出編輯器(按 Ctrl + X)。


3. 重啟 WSL

在  PowerShell 中執行:

wsl --shutdown

然後再次打開 WSL 後,SSH 伺服器應該會自動啟動並使用設定的端口。


回到 WSL 中執行以下命令確認 SSH 伺服器是否正在運行:
sudo service ssh status

沒有的話手動啟動 (這也表示 步驟2 應該沒設置成功)

sudo service ssh start




從主機端以 SSH 連接 WSL

打開主機端的 PowerShell 嘗試從主機端連接 WSL:
ssh -p 22 your_username@localhost

這裡 -p 的選項預設值就是 22,如果沒有改 port 可以省略不打


至此SSH設置完成可以利用 localhost 由本機登連接了,但還無法給外部電腦連結。

如果沒有要給外部電腦使用,做到這邊就可以了







[番外篇1] 在 WSL 中添加允許的公鑰

WSL 中創建 .ssh 目錄並設置適當的權限:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys

接著可以手動將你想要使用的公鑰添加到 authorized_keys 文件中:

nano ~/.ssh/authorized_keys

這一步不知道輸入什麼先不用管,確保文件已經被創建可以打開即可

接著按下 Ctrl+X 離開編輯頁面接著繼續做


回到 PowerShell 創建私鑰:

ssh-keygen -t ed25519

預設會詢問是否要保存到使用者底下直接按下 Enter 同意即可
再來會詢問你密碼,空白密碼也是直接 按下 Enter 兩次即可

至此私鑰就創建好了,再來需要把公鑰上傳到WSL中


在 PowerShell 中,執行下面的代碼上傳:

獲取本機 publicKey 公鑰

# 獲取本機 publicKey 公鑰
$publicKey = Get-Content -Path "$env:USERPROFILE\.ssh\id_ed25519.pub"
# 使用 SSH 連接到 Linux 伺服器並執行命令
ssh username@localhost "echo ""$publicKey"" >> ~/.ssh/authorized_keys"

從私鑰獲取可以參考這個指令 ssh-keygen -y -f $env:USERPROFILE/.ssh/id_ed25519

接下來會提示要你輸入密碼,輸入WSL密碼即可自動上傳


再來就可以在 PowerShell 中使用簡單的方式登入了

ssh username@localhost




[番外篇2] 從 Windows 轉發 wsl2 的連接埠

在預設情況下 wsl 是掛虛擬網卡的NAT網段裡,本機可直連該網段但外部電腦是連不到的,需要設置虛擬伺服器。

分兩個部分首先在 WSL 中你需要先得到他的ip是多少,在 wsl 中執行

ip addr show eth0

找一下其中 inet 172.25.69.52/20 這個是你的 wsl ip

再來是 Windows 的 IP,打開工作管理員在效能頁面中找到乙太網路,裡面有寫IP地址


管理員模式執行 PowerShell ,然後依序執行下面指令


1. 添加路由表

設置路由表 (用來穿透WSL的NAT)

netsh interface portproxy add v4tov4 `
    listenaddress=192.168.3.13 listenport=22 `
    connectaddress=172.25.69.52 connectport=22

重啟監聽服務

net stop iphlpsvc && net start iphlpsvc

把 192.168.3.13 映射到你的 wsl ip,下面代碼可以確認

netsh interface portproxy show all

你應該要能看到下面這樣

PS C:\Users\chg> netsh interface portproxy show all

接聽 ipv4:             連線到 ipv4:

位址            連接埠      位址            連接埠
--------------- ----------  --------------- ----------
192.168.3.12    22          172.17.55.208   22


2. 防火牆

打通行火牆讓外部的電腦可以連接

New-NetFirewallRule -DisplayName "WSL2_SSH" -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow

確認防火牆是否設置成功

Get-NetFirewallRule -DisplayName "WSL2_SSH"


至此就可以從外部電腦連接了



2024-11-12 重啟後失效的問題

發現已經設置好的伺服器重新啟動後路由雖然還在但是會失效
下面是刪除路由重建的指令,重建可以修好暫時不知道原因

# 刪除路由
netsh interface portproxy delete v4tov4 `
  listenaddress=192.168.3.13 listenport=22
# 重建路由
netsh interface portproxy add v4tov4 `
  listenaddress=192.168.3.13 listenport=22 `
  connectaddress=172.25.69.52 connectport=22




[番外篇3] 指定SSH連接使用者與遠端伺服器

在預設情況下當你輸入

ssh 192.168.3.13

預設會使用當前主機使用者名稱連接目標電腦,但如果有設置的話這邊是可以自訂名稱的

例如在以下

notepad $env:USERPROFILE\.ssh\config

文件中輸入

Host wsl
  HostName 192.168.3.13
  User chg

就可以使用以下方式登入了

ssh wsl

ssh會自動去讀取 wsl 中的資訊,使用指定的使用者連接到指定伺服器





參考