Windows 开启 SSH 与远程桌面完整指南:OpenSSH、WSL、家庭版 RDPWrap 与 Remmina 调优

十月 09, 2026 更新: 十月 10, 2026 [网络与安全] #Windows 与 WSL #SSH #RDP #安全 #网络

摘要:本文整理 Windows 开启 SSH Server 的两种方式(原生 OpenSSH Server 与 WSL),覆盖 ICMP 放行、账户密码与 PIN、公钥认证、默认 Shell、提权与密码修改;后半部分是家庭版开启远程桌面的 RDPWrap 实战——Smart App Control 拦截排查、从安装器中雕刻提取 rdpwrap.dll 手工安装、版本匹配与长期维护,以及 Linux 下 Remmina 客户端黑背景/清晰度问题的完整调优。

1. 方案一:Windows 原生 OpenSSH Server

从 Windows 10 1809 和 Windows 11 开始,系统内置了 OpenSSH 服务器组件,无需额外下载安装包。

1.1 检查是否已安装

以管理员身份打开 PowerShell:

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

如果 OpenSSH.Server 的 State 显示为 Installed,说明已安装;否则需要手动安装。

1.2 安装 OpenSSH 服务器

图形界面方式:

  1. 打开「设置」→「应用」→「可选功能」。
  2. 点击「添加可选功能」。
  3. 搜索并安装 OpenSSH 服务器。

PowerShell 方式:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

1.3 启动服务并设置开机自启

Start-Service sshd
Set-Service -Name sshd -StartupType Automatic

验证服务状态:

Get-Service sshd

Status 显示 Running 即表示 SSH 服务已正常运行。

1.4 防火墙规则:重复创建报错怎么办

安装 OpenSSH Server 时,系统通常会自动创建名为 OpenSSH-Server-In-TCP 的防火墙规则,允许 TCP 22 端口入站。

如果你手动执行:

New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

可能会遇到:

New-NetFirewallRule : 当文件已存在时,无法创建该文件。
Windows System Error 183

这说明规则已经存在,不需要重复创建。正确做法是先查看:

Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' | Select-Object Name, DisplayName, Enabled, Direction, Action

如果 Enabled 为 True,说明规则已生效。

如果规则存在但未启用,使用:

Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -Enabled True

如果确实需要重建:

Remove-NetFirewallRule -Name 'OpenSSH-Server-In-TCP'
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

1.5 放行 ICMP,让外部可以 ping 通

开启 SSH 与允许 ICMP ping 是两个独立操作,可以同时进行。

Windows 防火墙默认会阻止 ICMP 回显请求。以管理员身份运行:

netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow

也可以使用 PowerShell:

New-NetFirewallRule -DisplayName "Allow ICMPv4-In" -Protocol ICMPv4 -IcmpType 8 -Direction Inbound -Action Allow

安全提示:允许 ICMP 会增加主机在网络上被发现的概率。公共网络环境下建议限定来源 IP,或谨慎开启。


2. 方案二:WSL 中开启 SSH Server

WSL 本质上是运行在 Windows 中的 Linux 子系统,可以在其中安装 Linux 版 OpenSSH Server。适合需要 Linux 开发环境的场景,但需要处理端口转发和 WSL IP 变动问题。

2.1 在 WSL 中安装 OpenSSH Server

进入 WSL 终端,例如 Ubuntu:

sudo apt update
sudo apt install openssh-server -y

2.2 修改 SSH 配置

编辑配置文件:

sudo nano /etc/ssh/sshd_config

建议修改:

Port 2222
ListenAddress 0.0.0.0
PasswordAuthentication yes
PermitRootLogin no

说明:

2.3 启用 systemd 并启动 SSH

在 WSL 中创建或编辑 /etc/wsl.conf:

[boot]
systemd=true

重启 WSL 后执行:

sudo systemctl enable ssh
sudo systemctl start ssh

如果 systemctl 不可用,可以临时使用:

sudo service ssh start

2.4 Windows 主机端口转发

WSL2 使用虚拟网络,外部设备无法直接访问 WSL 内部 IP,需要将 Windows 主机端口转发到 WSL。

先获取 WSL IP:

hostname -I

然后在管理员 PowerShell 中执行:

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=2222 connectaddress=172.23.22.69 connectport=2222

将 172.23.22.69 替换为实际 WSL IP。

添加防火墙入站规则:

netsh advfirewall firewall add rule name="WSL2 SSH" dir=in action=allow protocol=TCP localport=2222

局域网设备可通过以下方式连接:

ssh 用户名@Windows主机IP -p 2222

注意:portproxy 指向的是 WSL IP,而 WSL 每次重启后 IP 可能变化,转发会失效。需要重新执行 netsh interface portproxy delete v4tov4 listenport=2222 再添加,或改用下面的镜像网络模式。

2.5 WSL 镜像网络模式

如果希望 WSL 与 Windows 共享同一 IP,可以启用镜像网络模式。

编辑或创建 C:\Users\你的用户名\.wslconfig:

[wsl2]
networkingMode=mirrored

保存后执行:

wsl --shutdown

重启 WSL 后生效。启用镜像模式后,再结合 Windows 防火墙规则,外部访问 WSL 会更直接,也省去了 portproxy 的 IP 变动问题。


3. 登录用户名和密码是什么

Windows OpenSSH Server 本身没有独立的用户名和密码,它直接使用 Windows 系统账户凭据。

3.1 用户名

用户名就是当前 Windows 账户名,可通过以下命令查看:

whoami

输出通常形如:

desktop-abc123\peter

SSH 登录时可以使用:

ssh peter@Windows主机IP

3.2 密码

密码取决于账户类型:

如果你在电脑上只设置了 PIN,需要回想或重置 Microsoft 账户的完整密码。

3.3 只知道用户名和 PIN 怎么办

SSH 不支持 PIN 码。可以尝试以下方案。

方案一:关闭"仅允许 Windows Hello 登录"

  1. 打开「设置」→「账户」→「登录选项」。
  2. 找到「为了提高安全性,仅允许对此设备上的 Microsoft 账户使用 Windows Hello 登录」。
  3. 将其关闭。
  4. 锁定电脑再重新解锁。
  5. 重启 sshd 服务:
Restart-Service sshd

然后设置或使用 Microsoft 账户在线密码登录 SSH。

方案二:配置 SSH 公钥认证

使用密钥登录,不再依赖账户密码。见下一节。

方案三:创建专用本地用户

net user peter YourPassword123 /add

该用户默认属于 Users 标准用户组,不具备管理员权限。

如果只是 SSH 登录并执行普通命令,标准用户足够。若需要管理员权限,可加入 Administrators:

net localgroup Administrators peter /add

注意:Remote Management Users 组主要面向 WinRM,不是管理员组,也不是 SSH 必需。


4. SSH 公钥认证

长期使用密码登录不够安全,更推荐 SSH 公钥认证。

4.1 在客户端生成密钥

在客户端机器执行:

ssh-keygen -t ed25519

默认会生成:

~/.ssh/id_ed25519
~/.ssh/id_ed25519.pub

4.2 部署公钥到 Windows

普通用户:

C:\Users\用户名\.ssh\authorized_keys

管理员用户:

C:\ProgramData\ssh\administrators_authorized_keys

如果用户属于 Administrators 组,公钥必须放到 administrators_authorized_keys,否则可能无法登录。这是 sshd_config 默认末尾的 Match Group Administrators 段决定的行为。

4.3 命令行添加管理员公钥

在管理员 PowerShell 中执行:

$path = "C:\ProgramData\ssh\administrators_authorized_keys"
$key  = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@client"

# 确保目录存在
$dir = Split-Path $path
if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }

# 如果文件不存在则创建
if (!(Test-Path $path)) { New-Item -Path $path -ItemType File -Force | Out-Null }

# 检查公钥是否已存在,不存在则追加
if (-not (Select-String -Path $path -Pattern ([regex]::Escape($key)) -Quiet)) {
    Add-Content -Path $path -Value $key -Encoding Ascii
    Write-Host "公钥已添加。"
} else {
    Write-Host "公钥已存在,未重复添加。"
}

# 设置严格权限:移除继承,只允许 SYSTEM 和 Administrators 完全控制
icacls $path /inheritance:r
icacls $path /grant '*S-1-5-18:F'
icacls $path /grant '*S-1-5-32-544:F'

# 显示最终内容和权限
Write-Host "`n--- 文件内容 ---"
Get-Content $path
Write-Host "`n--- 文件权限 ---"
icacls $path

说明:*S-1-5-18 是 SYSTEM,*S-1-5-32-544 是 Administrators,用 SID 授权可避免中文系统上组名不一致的问题。权限过宽(如继承了 Users 组读取)会导致 sshd 拒绝使用该公钥文件。

4.4 验证

Get-Content C:\ProgramData\ssh\administrators_authorized_keys
icacls C:\ProgramData\ssh\administrators_authorized_keys

确认内容正确,且权限列表中只有 SYSTEM 和 Administrators。

客户端登录:

ssh -i 私钥路径 用户名@Windows主机IP

无需重启 sshd,OpenSSH 每次认证都会重新读取该文件。


5. 默认进入 cmd 还是 PowerShell

Windows OpenSSH Server 默认进入的是 cmd.exe,不是 PowerShell。

5.1 如何查看当前 Shell

看提示符:

在 cmd 中验证:

echo %COMSPEC%

输出 C:\Windows\System32\cmd.exe 说明当前是 cmd。

在 PowerShell 中验证:

$PSVersionTable

能输出版本表格就是 PowerShell。

5.2 修改默认 Shell 为 PowerShell

以管理员身份运行:

if (!(Test-Path "HKLM:\SOFTWARE\OpenSSH")) {
    New-Item -Path "HKLM:\SOFTWARE\OpenSSH" -Force
}

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force

重启 sshd:

Restart-Service sshd

重新 SSH 登录后,提示符会变成:

PS C:\Users\peter>

如果安装了 PowerShell 7,也可以改为:

C:\Program Files\PowerShell\7\pwsh.exe

临时切换:在 cmd 中输入 powershell 回车即可进入 PowerShell,输入 exit 退回 cmd。

5.3 实战坑:reg add 写了却不生效

实测一台 Windows 11 25H2(OpenSSH 9.5p2)上,用 reg add 写入 DefaultShell 后 net stop sshd && net start sshd,新会话仍然进 cmd;换成 PowerShell 原生方式一次性生效:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell `
  -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
  -PropertyType String -Force
Restart-Service sshd -Force

排查思路备忘:

另一个高频痛点:默认 shell 是 cmd 时,从 Linux 远程执行复杂命令会陷入引号转义地狱(%、"、嵌套引号层层剥皮,curl -w "%{http_code}" 这类必然阵亡)。最稳的办法是根本不让 cmd 解析——本地把 PowerShell 脚本编码后用 -EncodedCommand 传输,全程无引号:

# 本地任意复杂的 PowerShell,base64(UTF-16LE) 后传给远端
ENC=$(printf '%s' 'Get-Service sshd | Select-Object Status,Name | Out-String' \
      | iconv -t UTF-16LE | base64 -w0)
ssh 用户名@Windows主机IP "powershell -EncodedCommand $ENC"

顺带的编码坑:中文系统 cmd 远程输出是 GBK,curl -w 的 %% 转义在不同层级表现不一致,timeout /t 在 SSH 无 stdin 时直接报错不可用于延时(改用 Start-Sleep)。


6. 提权:sudo、runas 与专用管理员账户

6.1 Windows 11 内置 sudo

Windows 11 24H2 及以上版本支持原生 sudo。

打开「设置」→「系统」→「开发者选项」,启用 sudo。

之后可以:

sudo netstat -ab

注意:该功能依赖 UAC 弹窗,在纯 SSH 会话中可能无法正常工作。

6.2 使用 runas

runas 是 Windows 传统提权命令,兼容所有版本。

runas /user:Administrator "powershell.exe"

执行后会提示输入 Administrator 密码。

注意事项:

如果内置 Administrator 账户未启用,需要先启用并设置密码:

net user administrator /active:yes
net user administrator YourStrongPassword

用完建议禁用:

net user administrator /active:no

6.3 更推荐:专用管理员 SSH 账户

创建一个专用本地管理员账户:

net user SSHAdmin YourStrongPassword /add
net localgroup Administrators SSHAdmin /add

然后为 SSHAdmin 配置 SSH 公钥,公钥放到:

C:\ProgramData\ssh\administrators_authorized_keys

之后直接登录:

ssh SSHAdmin@Windows主机IP

这种方式登录后的会话通常具备管理员权限,不需要再 runas 或 sudo,更适合长期 SSH 管理。


7. 本地账户与 Microsoft 在线账户

7.1 两者的区别

类型凭据存储位置验证方式
Microsoft 账户微软在线服务器需要在线密码
本地账户本机 SAM 数据库本地密码验证

Windows OpenSSH Server 验证的是本地账户数据库。使用 Microsoft 账户登录 Windows 时,系统会在后台创建一个对应的本地用户,但密码验证会转发到微软服务器。因此 SSH 登录 Microsoft 账户时,需要的是在线密码,而不是 PIN。

7.2 需求对照

需求是否需要 Microsoft 在线账户
SSH 远程管理,使用本地管理员不需要
桌面日常登录,使用 PIN / Windows Hello需要,保持现状即可
用原 Microsoft 账户 SSH 登录需要在线密码,或改用公钥认证

结论:

7.3 在线账户丢失是否影响本地用户

不影响。 即使 Microsoft 在线账户丢失、无法登录、密码遗忘或被注销,本地用户仍然可以正常使用,包括:

原因:本地账户的用户名和密码哈希存储在本地 SAM 数据库中,验证完全在本地完成,不依赖微软服务器。

7.4 需要注意的例外情况

虽然本地账户本身不受影响,但以下事项可能和 Microsoft 账户有关:

  1. BitLocker 恢复密钥 如果系统盘启用了 BitLocker,恢复密钥可能备份在 Microsoft 账户中。在线账户丢失可能导致无法获取恢复密钥。但这影响的是磁盘解锁,不是本地账户本身。

    查看本机是否开启了 BitLocker(需管理员,家庭版对应的是「设备加密」,机制相同):

    Get-BitLockerVolume | Select-Object MountPoint,VolumeStatus,ProtectionStatus,EncryptionPercentage,EncryptionMethod
    

    实测一台 Windows 11 家庭中文版的输出(两块盘全部加密、TPM 就绪):

    MountPoint   VolumeStatus     ProtectionStatus   EncryptionPercentage   EncryptionMethod
    ----------   --------------   -----------------   --------------------   ---------------
    C:           FullyEncrypted   On                 100                   XtsAes128
    D:           FullyEncrypted   On                 100                   XtsAes128
    

    VolumeStatus = FullyEncrypted 且 ProtectionStatus = On 即已启用。顺手确认 TPM 状态:Get-Tpm,TpmReady 为 True 才能无感解锁。

    查看恢复密钥保护器(只看 ID,不在终端展开密钥本身):

    (Get-BitLockerVolume -MountPoint C:).KeyProtector |
      Where-Object KeyProtectorType -eq RecoveryPassword |
      Select-Object KeyProtectorId
    

    有 RecoveryPassword 条目说明恢复密钥存在。务必确认它至少有一份离线备份:登录 aka.ms/myrecoverykey 查看 Microsoft 账户中的托管记录,同时建议额外保存一份(打印或密码管理器)——恢复密钥是 48 位数字,主板/TPM 变更、系统重装后是唯一解锁手段,且不要把密钥明文贴到任何终端输出或笔记里。

    读出恢复密钥本身(管理员权限,SSH / RDP / 本地终端均可):

    # 方式一:PowerShell 原生
    (Get-BitLockerVolume -MountPoint C:).KeyProtector |
      Where-Object KeyProtectorType -eq RecoveryPassword |
      Select-Object KeyProtectorId, RecoveryPassword
    
    # 方式二:老牌工具,ID + 密钥分栏显示,更直观
    manage-bde -protectors -get C:
    

    注意事项:

    • 每个卷有独立的恢复密钥,多块盘要逐卷执行(把 C: 换成 D: 等)。
    • 本机读出的与 aka.ms/myrecoverykey 里托管的是同一把——两边核对:微软账户里查不到,则本机这份就是唯一副本,立即存入密码管理器。
    • 密钥属于敏感凭据:在自己的终端里查看、存好后清掉终端回滚缓冲;不要让 AI 助手 / 聊天工具代查(密钥会进入会话记录,与密码不进任何中间上下文是同一条原则)。

    若怀疑密钥已泄露,可以轮换(生成全新随机恢复密钥,旧的可后续用 Remove-BitLockerKeyProtector 删除):

    Add-BitLockerKeyProtector -MountPoint C: -RecoveryPasswordProtector
    
  2. 原 Microsoft 账户的用户配置文件 原在线账户对应的 C:\Users\原用户名 文件夹仍然存在,但本地新用户默认无权访问。如需里面的文件,需要手动修改权限或取得所有权。

  3. OneDrive / Microsoft 服务 原账户关联的 OneDrive、Office 订阅、Edge 同步等会失效,但这些与本地登录和 SSH 无关。

  4. 密码重置盘 / PIN 本地用户默认没有 PIN,只能用密码登录。请务必记住密码。

  5. 组策略限制 极少数情况下,域策略或本地安全策略可能限制某些用户本地登录。默认情况下,Users 和 Administrators 组都有"允许本地登录"权限。

7.5 建议


8. 修改用户密码

8.1 使用 net user

net user 用户名 新密码

示例:

net user peter NewP@ssw0rd2026!

交互式输入,避免密码出现在命令历史中:

net user peter *

系统会提示输入两次密码。

8.2 使用 PowerShell Set-LocalUser

Set-LocalUser -Name "peter" -Password (ConvertTo-SecureString "NewP@ssw0rd2026!" -AsPlainText -Force)

8.3 图形界面

如果能通过远程桌面连接:

  1. 按 Win + R,输入 control。
  2. 进入「用户账户」→「管理其他账户」。
  3. 选择目标账户,点击「更改密码」。

注意:


9. 常见问题排查

9.1 New-NetFirewallRule 报错"文件已存在"

说明规则已经存在。使用:

Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP'
Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -Enabled True

9.2 SSH 登录提示 Permission denied

可能原因:

查看日志:

C:\ProgramData\ssh\logs\sshd.log

9.3 只知道 PIN,不知道密码

9.4 sudo 被禁用

Windows 默认禁用 sudo。可在 Windows 11 开发者设置中启用,但 SSH 中可能受 UAC 限制。更推荐使用专用管理员 SSH 账户。

9.5 登录后默认是 cmd

这是正常默认行为。可通过注册表 DefaultShell 改为 PowerShell。

9.6 错误代码 1326

常见于 Microsoft 账户认证失败。可尝试关闭 Windows Hello 限制,或改用本地账户 / 公钥认证。

9.7 本地用户能否正常本地登录

可以。使用 net user 创建的本地用户默认属于 Users 组,拥有本地登录权限。在登录界面选择"其他用户",输入 电脑名\用户名 和密码即可登录。

9.8 Microsoft 账户丢失后本地用户还能用吗

可以。本地账户的验证完全在本地进行,不依赖 Microsoft 在线账户。在线账户丢失不影响本地用户的本地登录、SSH 登录和日常使用。


10. 安全建议


11. 进阶:家庭版开启远程桌面(RDPWrap 实战)

需求:Windows 11 家庭中文版(EditionID = CoreCountrySpecific)通过 SSH 开启原生 RDP 服务。家庭版没有 RDP 服务端,这是功能阉割不是配置问题——TermService 服务存在、fDenyTSConnections 注册表键也在,但 termsrv 有版本许可检查,改键也拒绝连接。免升级的专业版解锁方案是 RDPWrap。

11.1 版本判定:看 termsrv.dll 而不是 OS build

RDPWrap 按 termsrv.dll 的文件版本精确匹配 ini 配置段,这里有两个极易踩的坑:

  1. OS build ≠ dll build。Windows 11 25H2 是 enablement 升级包,OS 显示 26200.x,但很多系统 DLL 仍在 26100 分支。实测一台 25H2(OS 26200.9168)的 termsrv.dll 是 10.0.26100.8972——按 OS build 去搜 ini 会搜错方向。
  2. 字符串属性会骗人。(Get-Item C:\Windows\System32\termsrv.dll).VersionInfo.FileVersion 返回的字符串显示 26100.8875,但 FileVersionRaw 才是 RDPWrap 实际读取的字段:
(Get-Item C:\Windows\System32\termsrv.dll).VersionInfo.FileVersionRaw
# Major  Minor  Build  Revision
# 10    0      26100  8972

ini 用社区持续维护的版本(官方 stascorp 仓库 2017 年就停更了):

https://github.com/sebaxakerhtc/rdpwrap.ini

下载后 Select-String -Pattern '^\[10\.0\.26100\.8972\]' 确认有对应段再继续。

11.2 Smart App Control:Win11 24H2+ 的头号拦路虎

新版 Windows 出厂默认开启 SAC 评估模式(VerifiedAndReputablePolicyState=1),基于云信誉拦截"无签名无信誉"的程序。RDPWInst.exe(2017 年的老 exe)必被拦,症状很有迷惑性:

实锤方法看 CodeIntegrity 事件日志:

Get-WinEvent -LogName 'Microsoft-Windows-CodeIntegrity/Operational' -MaxEvents 10
# 事件 3077/3033: ... did not meet the Enterprise signing level requirements
# 事件 3118: Smart App Control Block

排除法过程记录(都不是原因,但值得知道):MOTW 标记(Get-Item -Stream Zone.Identifier,curl.exe 下载的文件本来就不带)、Defender 拦截(Get-MpThreat 为空)、WOW64(32 位 exe,SysWOW64\cmd.exe 能跑)、.NET 运行库(4.8 在、3.5 也装了)。

关闭 SAC(不可逆,重装系统才能再开,个人桌面跑社区工具的标准前提):

Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\CI\Policy' `
  -Name VerifiedAndReputablePolicyState -Value 0 -Type DWord
Restart-Computer -Force   # 必须重启才生效,重启服务无效

11.3 关 SAC 前的安装路径:从安装器里"雕刻"出 rdpwrap.dll

若不想关 SAC,还有一条硬核路:SAC 拦的是执行,纯文件读写不受影响。而官方安装包 RDPWInst.exe 里以资源形式内嵌了所有需要的 DLL(rdpwrap.dll x86/x64、rdpclip、RfxVmt.dll),可以用 PowerShell 按 PE 结构手工提取(官方 GitHub Release 是 RDPWrap-v1.6.2.zip,注意老的 RDPWInst.zip 路径已 404):

$b = [IO.File]::ReadAllBytes('C:\Users\你的用户名\rdpwrap\RDPWInst.exe')

# 扫描所有内嵌 PE:MZ 头 + e_lfanew 指向合法 PE 签名
for ($i = 0; $i -lt $b.Length - 0x40; $i++) {
    if ($b[$i] -eq 0x4D -and $b[$i+1] -eq 0x5A) {
        $pe = [BitConverter]::ToInt32($b, $i + 0x3C)
        if ($pe -gt 0 -and $pe -lt 0x400 -and
            $b[$i+$pe] -eq 0x50 -and $b[$i+$pe+1] -eq 0x45) {
            $mach = [BitConverter]::ToUInt16($b, $i + $pe + 4)
            Write-Output ("MZ at {0} machine 0x{1:X4}" -f $i, $mach)
        }
    }
}

得到一串内嵌 PE 后按特征识别:machine=0x8664 的是 x64,其中内含 ServiceMain 字样、无 .pdb 调试路径的 116736 字节那块就是 rdpwrap.dll(有 rdpclip.pdb/RfxVmt.pdb 字样的是另两个)。按节表计算精确长度后 carve 出来:

$dll = New-Object byte[] 116736
[Array]::Copy($b, 1271752, $dll, 0, 116736)   # 偏移/长度按实际扫描结果
[IO.File]::WriteAllBytes('C:\Users\你的用户名\rdpwrap\rdpwrap.dll', $dll)

家庭版通常还缺 RfxVmt.dll(远程会话虚拟通道组件,同样内嵌在安装器里),一并提取备用。

11.4 手工安装:注册表接线五步

关掉 SAC 并重启后(或直接用官方安装器 RDPWInst.exe -i,把新 ini 放同目录),手工安装的完整步骤:

# 1. 就位文件(ini 与 dll 同目录)
New-Item -Path 'C:\Program Files\RDP Wrapper' -ItemType Directory -Force
Copy-Item C:\Users\你的用户名\rdpwrap\rdpwrap.dll 'C:\Program Files\RDP Wrapper\'
Copy-Item C:\Users\你的用户名\rdpwrap\rdpwrap.ini 'C:\Program Files\RDP Wrapper\'
Copy-Item C:\Users\你的用户名\rdpwrap\RfxVmt.dll C:\Windows\System32\   # 家庭版缺失时

# 2. 核心接线:让 svchost 加载 rdpwrap.dll(它再加载真 termsrv.dll 并内存补丁)
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\TermService\Parameters' `
  -Name ServiceDll -Value 'C:\Program Files\RDP Wrapper\rdpwrap.dll'

# 3. 放开远程连接总开关
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' `
  -Name fDenyTSConnections -Value 0

# 4. 防火墙放行 3389(TCP+UDP)
netsh advfirewall firewall add rule name="RDPWrap-TCP-3389" dir=in action=allow protocol=TCP localport=3389
netsh advfirewall firewall add rule name="RDPWrap-UDP-3389" dir=in action=allow protocol=UDP localport=3389

# 5. 重启服务并验证
Restart-Service TermService -Force
netstat -ano | Select-String ':3389'   # 应看到 LISTENING

端到端验证技巧:不需要真实登录,用假凭据做一次 NLA 探测——错误码是 LOGON_FAILURE(凭据被真实校验后拒绝)就证明 TLS + CredSSP + 补丁后的 termsrv 全链路正常;若是协议层错误才是真有问题:

xfreerdp /v:Windows主机IP /u:probe /p:wrong /cert:ignore /auth-only /sec:nla
# ERRCONNECT_LOGON_FAILURE = 栈正常,只是密码错 —— 预期结果

11.5 长期维护与卸载


12. Linux 客户端(Remmina)黑背景与清晰度调优

RDP 通了只是第一步,Remmina 默认配置连上去是「小窗 + 黑背景 + 文字发虚」三连,对应 profile(~/.local/share/remmina/xxx.remmina)里三个键:

症状原因修复
窗口很小resolution_mode=2 + 宽高为 0,回落到默认小分辨率resolution_mode=1(跟随本地屏幕)或设固定宽高
背景纯黑quality=0(Poor 档)为省带宽主动剥离壁纸/主题quality=9(Best 档)
文字发虚colordepth=99 是 GFX AVC444(H.264 有损编码)colordepth=32(无损位图)+ viewmode=4(全屏 1:1)

改完必须断开重连(RDP 分辨率与编码在会话建立时协商)。全屏模式下鼠标移到屏幕顶部中央可呼出 Remmina 工具条退出全屏。

12.1 如何客观验证「到底糊不糊」

感知不可靠时,两个可复现的诊断手段:

一、从客户端往 RDP 会话内注入探针——SSH 在 Windows 上跑的进程不在 RDP 会话里,直接查分辨率查到的是控制台会话;用交互式计划任务把探针打进会话内部:

# 探针脚本: 输出会话 ID、屏幕尺寸、DPI、ClearType 状态
schtasks /create /tn RDPProbe /it /ru 用户名 /sc once /st 23:59 `
  /tr 'powershell -ExecutionPolicy Bypass -File C:\Users\用户名\probe.ps1' /f
schtasks /run /tn RDPProbe
Get-Content C:\Users\用户名\probe.txt
# probe.ps1 内容
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
"session: $([Diagnostics.Process]::GetCurrentProcess().SessionId)"
[System.Windows.Forms.Screen]::AllScreens | % { "screen: $($_.Bounds)" }
$g = [Drawing.Graphics]::FromHwnd([IntPtr]::Zero); "dpi: $($g.DpiX)"
"fontSmoothing: $((Get-ItemProperty 'HKCU:\Control Panel\Desktop').FontSmoothing)"

预期健康值:屏幕尺寸 = 本地显示器原生分辨率、dpi 96(100%)、fontSmoothing 2(ClearType 开)。

二、截图做像素级测量——GNOME Wayland 下 CLI 截屏走 xdg-desktop-portal(org.freedesktop.portal.Desktop 的 Screenshot 方法,会弹一次用户确认框),拿到截屏后用拉普拉斯高频能量对比、并检查 1px UI 线(任务栏边缘)是否仍是单像素:若 80% 强边缘保持 1px 锐利,说明客户端无缩放重采样、像素严格对齐,模糊感另有原因。

12.2 调优上限的诚实结论

无损 32bpp + 分辨率 1:1 + 全屏 + ClearType 开启,就是 RDP 的画质上限。剩余与「坐在实体机前」的观感差来自远端会话光栅化时的次像素排列/伽马假设与物理面板出厂校准不一致,属于协议固有特性(微软官方 mstsc 客户端同样存在),无法靠配置消除。缓解手段:在远程会话里 Win+R 运行 cttune 重新走一遍 ClearType 调谐向导。


13. 总结

Windows 开启 SSH Server 有两条主要路线:

  1. Windows 原生 OpenSSH Server:安装简单,适合远程管理 Windows 本身。
  2. WSL 中开启 SSH Server:适合 Linux 开发环境,但需要处理端口转发和网络模式。

远程桌面方面:

登录时,SSH 使用的是 Windows 账户凭据:

如果长期使用 SSH 管理,推荐:

本地账户与 Microsoft 在线账户相互独立。即使在线账户丢失,本地用户仍然可以正常本地登录和 SSH 登录。建议保留一个可用的本地管理员账户作为备用,并妥善保管密码。

索引
1. 方案一:Windows 原生 OpenSSH Server
2. 方案二:WSL 中开启 SSH Server
3. 登录用户名和密码是什么
4. SSH 公钥认证
5. 默认进入 cmd 还是 PowerShell
6. 提权:sudo、runas 与专用管理员账户
7. 本地账户与 Microsoft 在线账户
8. 修改用户密码
9. 常见问题排查
10. 安全建议
11. 进阶:家庭版开启远程桌面(RDPWrap 实战)
12. Linux 客户端(Remmina)黑背景与清晰度调优
13. 总结