XF

Windows: Softwares and Configurations

自己的 Windows 日用配置。不时更新。

Scoop

对于习惯了命令行工具的用户,我推荐使用 Scoop 软件包管理器在 Windows 下安装常用命令行小工具。

WSL2 相关

安装并启用 WSL2 参考 Microsoft Docs。以下假定 WSL2 的发行版是 Ubuntu 20.04.

我的 WSL2 采用了与自己大部分 Linux 服务器相同的一套 dotfiles,共享在 GitHub 上

效果图:

Windows.Terminal.WSL

SSH Server and Port Forward

现阶段固定 WSL2 的 IP 地址比较麻烦(讨论),但可以使用 PowerShell 脚本来自动获取 WSL2 的 IP 并将特定的端口转发到 Host (也就是 Windows)的对应端口。以转发 SSH 端口为例:

先安装 SSH Server:

sudo apt install ssh
sudo vim /etc/ssh/sshd_config

修改 SSH 配置文件,假设端口改为非标准端口 2222:

# /etc/ssh/sshd_config
Port 2222
# Other configurations...

启动 SSH Server:

sudo service ssh start

下载(或创建)此脚本,并在 Windows 的 PowerShell 中运行,可将 WSL2 的 2222 端口转发到 Windows Host 的 2222 端口。最后,如果有在外部访问的需求,记得在 Windows Firewall 设置中允许 2222 端口的访问。

ssh-agent and keychain

Note: YubiKey 等智能卡用户可跳过此小节,并前往 GPG Bridge 小节。

WSL2 中 ssh-agent 并不好用,为了避免每次使用 SSH Key 时都要手动输入 Passphrase,可以安装 keychain 来解决:

sudo apt install keychain

然后在 .zshrc 中加入:

if (( $+commands[keychain] )); then
  keychain -q --nogui $HOME/.ssh/id_ed25519
  source $HOME/.keychain/$HOST-sh
fi

之后每次开机只需输入一次 SSH Private 的 Key 的 Passphrase 即可。

Windows Terminal

这里有一个 Windows Terminal 配置文件的简单的例子,可以自行参考取用全部或其中部分设置。注意该配置文件中引用了几个壁纸和图标文件,它们的路径是 ms-appdata:///roaming/... 开头的,对于 Windows Terminal 来说,这个路径对应的实际文件夹位置是:

%USERPROFILE%\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\RoamingState\

如果想换用自己的图标或壁纸,把相应的图片文件放置在这个目录下即可。当然,在 settings.json 中,我们实际上可以用绝对路径引用电脑上任意地方的图片文件。

另外,我对 PowerShell 和 WSL2 中的 Shell(默认是 bash,但我改成了 zsh)均进行了一定程度的配置,配置文件不长,可供参考。

PowerShell

自行安装新版 PowerShell,目前版本是 7.x。Windows 自带的是 5.x,缺少一些特性。

然后安装如下 Modules:

Install-Module -Name posh-git
Install-Module -Name oh-my-posh
Install-Module -Name PSReadLine

PowerShell 的配置文件目录是 %USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1这里有一个非常简短的例子。

效果图:

Windows.Terminal.PowerShell

SSH over Socks5 Proxy

由于某些原因,我的办公网络使用了白名单策略,只允许用户访问外界特定的常见端口(如 22、80、443 等),其它端口一律 Deny by default。我的 VPS 使用非标准 SSH 端口,因此默认情况下我无法在办公网络中直接 SSH 登录自己的 VPS。

假定我们在本文开头配置好的 Clash for Windows 中使用的代理节点在这样的白名单网络环境下是可用的(例如,与代理服务器建立隧道时使用了 HTTP2 类型的传输方式,这种情况对于网管而言与访问一个普通的 HTTPS 网页没什么区别),则可借助这个代理访问非标准 SSH 端口的 VPS。

在 macOS/Linux 下我们使用 nc,如下是 ~/.ssh/config 中某个 Host 的配置示例:

Host g
  Hostname g.xxxx.com
  User my_username
  Port 12345
  ForwardAgent yes
  ServerAliveInterval 10
  ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p

而在 Windows 下则使用 ncat。首先下载 ncat 并安装,或者将其路径添加到 %PATH% 中。%HOME%/.ssh/config 配置文件中的 ProxyCommand 语法也要稍作调整,如下:

Host g
  Hostname g.xxxx.com
  User my_username
  Port 12345
  ForwardAgent yes
  ServerAliveInterval 10
  ProxyCommand ncat --proxy-type socks5 --proxy 127.0.0.1:1080 %h %p

SSH-Agent

Windows 自带一个 OpenSSH 服务及 ssh-agent,可参阅 Microsoft 的文档。简单而言,在 services.msc 中将名为 OpenSSH Authentication Agent 服务启动(并设置为自动启动)即可。

GPG Bridge

本小节描述 YubiKey(或其他 GPG 智能卡,下同)用户可用的 SSH/GPG 解决方案。此方案可实现:

注: 本节的方案与 WSL2 中的 keychainWindows 的 OpenSSH Agent 冲突或功能重复。如果采用本节的方案,最好不要在 WSL 2 中使用 keychain,也不要在 Windows 服务中开启 OpenSSH Agent。

1. Windows 中的 GPG/SSH 方案

前置条件当然是安装 Gpg4win —— 理论上读者可以自行选择 Windows 的 GPG 软件包,但这里直接使用 Gpg4win 是比较省事的选择。

安装(可能需要 Rustgpg-bridge 并根据其使用说明书,(1) 将 Windows 下 GnuPG 的 extra socket 转发至一个本地 TCP 端口,(2) 将 GnuPG Agent 用作 SSH Agent。这两项操作可以使用一条命令完成:

~/.cargo/bin/gpg-bridge --extra 127.0.0.1:4321 --ssh \\.\pipe\gpg-bridge-ssh

前提是 Windows 中的 gpg-agent.conf 中启用了 enable-putty-support。 之后在 Windows 中将环境变量 SSH_AUTH_SOCK 的值设置为 \\.\pipe\gpg-bridge-ssh

之后在 PowerShell 中可以运行

ssh-add -l
# sample output:
# 4096 SHA256:1234567890asdfghjklASDFGHJKL cardno:1 234 567 (RSA)

如果输出形似上述样例,例如有 cardno 字样,则说明成功读取了 YubiKey 中的 GPG Authentication subkey 作为 SSH Key。

Forward SSH Agent and GPG Agent over SSH

在 SSH Client 的 config 文件(.ssh/config) 中,对于某个 Host:

Host g
  Hostname g.xxxx.com
  User my_username
  Port 12345
  ForwardAgent yes
  ServerAliveInterval 10
  ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p
  RemoteForward /run/user/1000/gnupg/S.gpg-agent 127.0.0.1:4321

其中 ForwardAgent yes 是转发 SSH Agent 到远端,而最后一行 RemoteForward ... 则是转发 GPG Agent 到远端。前者没什么难度,而要成功实现后者,则需要稍微了解一些操作要点 —— 这里有一份在类 UNIX 系统下的文档。RemoteForward 的语法是:

  RemoteForward <socket_on_remote_box>  <extra_socket_on_local_box>

这里 Local 环境是 Windows + Gpg4win,直接写 socket 路径不好使,我们换成经 gpg-bridge 转发的 127.0.0.1:4321 即可。

2. WSL 2 中的 GPG/SSH 方案

借助 wsl2-ssh-pageant 项目,我们可以把 Windows 的 SSH_AUTH_SOCKGPG_AGENT_SOCK 两个 Socket 都转发到 WSL2 里面去。假设我们已经完成上一小节「Windows 中的 GPG/SSH 方案」中的全部步骤。将两个 Sockets 转发到 WSL 2 中的方法:

先安装 socat 并下载 wsl2-ssh-pageant:

sudo apt install socat

destination="$HOME/.ssh/wsl2-ssh-pageant.exe"
wget -O "$destination" "https://github.com/BlackReloaded/wsl2-ssh-pageant/releases/latest/download/wsl2-ssh-pageant.exe"
# Set the executable bit.
chmod +x "$destination"

然后在 .zshrc 中添加:

UNAME=`uname -a`
if (( $UNAME[(I)WSL2] )); then
  # GPG Socket
  # Removing Linux GPG Agent socket and replacing it by link to wsl2-ssh-pageant GPG socket
  export GPG_AGENT_SOCK=$HOME/.gnupg/S.gpg-agent
  ss -a | grep -q $GPG_AGENT_SOCK
  if [ $? -ne 0 ]; then

    rm -rf $GPG_AGENT_SOCK
    setsid nohup socat UNIX-LISTEN:$GPG_AGENT_SOCK,fork EXEC:"$HOME/.ssh/wsl2-ssh-pageant.exe --gpg S.gpg-agent" &>/dev/null &
  fi

  # SSH Socket
  # Removing Linux SSH socket and replacing it by link to wsl2-ssh-pageant socket
  export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
  ss -a | grep -q $SSH_AUTH_SOCK
  if [ $? -ne 0 ]; then
    rm -f $SSH_AUTH_SOCK
    setsid nohup socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:$HOME/.ssh/wsl2-ssh-pageant.exe &>/dev/null &
  fi
fi

我加了一个 uname -a 是否包含 WSL2 字串的判断,因为我的 .zshrc 配置会用在各种不同的 Linux 系统中,只有在 WSL2 中这段转发配置才会生效。

DNS over HTTPS

按:在中国内地单独使用 DNS over HTTPS (DoH) 看上去意义不大;另一方面,主流的浏览器如 Firefox、Google Chrome 及 Microsoft Edge 均已支持在浏览器内部设置 DoH。但这里还是提供一种启用本地 DoH Server 的方案以备不时之需。使用 Cloudflared 客户端。

首先下载 cloudflared 程序。Windows 版本只有一个可执行文件。

创建 %USERPROFILE%\.cloudflared\config.yaml 文件,并填入以下内容(可以根据自己的需求调整):

proxy-dns: true
proxy-dns-port: 5553
proxy-dns-upstream:
  - https://1.1.1.1/dns-query
  - https://dns.google/dns-query
  - https://1.0.0.1/dns-query

之后直接以普通用户身份运行 <path-to-cloudflared>\cloudflared.exe 即可启动本地 DoH client,监听 5553 端口。

如果需要将 Cloudflared 安装为服务并后台运行,可以 Administrator 身份运行 Windows Terminal/PowerShell,并执行

<path-to-cloudflared>\cloudflared.exe service install

但此时安装的 Cloudflared Service 只会读取 C:\Windows\system32\config\systemprofile\.cloudflared\config.yml 这个位置的配置文件,而不会读取上述 %USERPROFILE%\.cloudflared\config.yaml 文件。一种方法当然是手动创建该系统配置文件;但如果不想自己手动在 C:\Windows\system32\ 下面乱放东西,也可以修改注册表

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Cloudflared\ImagePath

给 Cloudfared 服务加上 --config <path-to-config> 参数。文档在此

服务安装好后,可以在 Task Manager (任务管理器)的 Services 选项卡中控制 Cloudflared 服务的启动与停止。

Hugo

Hugo 是一个单 exe 程序,在其 Release 页面 下载后放置在自己习惯的位置(我经常放在 %USERPROFILE%\Prog 中,如果希望更好地遵循 Windows 的 Convention,可以考虑放置在 %LOCALAPPDATA%\Programs 中),最后记得将其目录添加至 %PATH%.

开始用 Scoop 管理小型命令行工具软件后,直接 scoop install hugo 就行了,省事多了。

C++

目前(截至 2021 年)C++ 的生态环境比较丰富(复杂),不同的项目可能用着非常不同的项目管理工具、生成工具链等,很多用有限的篇幅概括。对于「大一编程课」级别的 C++ 环境配置,其实随便什么网上的教程基本都可以满足需求,甚至对于单文件编程,在 WSL 里 sudo apt install build-essential,用 g++ 就可以搞定大部分任务了。

而更大的 C++ 项目通常会使用 IDE 及某些 build system。一般安装一个 Visual Studio / JetBrains CLion 等大型 IDE 就可以了。如果想要兼顾「偶尔用轻量文本编辑器编辑」与「一定的多文件项目管理及语义检查能力」,可以考虑 VS Code / Sublime Text 配合 LSP 及 clangd