在 WSL 中配置开发环境

本帖记录了一些我常用的 WSL 设置。

安装常用包

Ubuntu:

sudo apt install build-essential

Debian:

sudo apt install gcc g++

Debian Common:

sudo apt install gdb valgrind git gpg curl wget zip unzip zsh

设置 Zsh

/bin/zsh 设置成默认 shell

chsh -s /bin/zsh

安装 oh-my-zsh 和常用插件

wget https://gist.githubusercontent.com/dingwen07/1261eac531f7f080d72b78f931a8ca01/raw/omz-setup.sh
chmod +x ./omz-setup.sh
./omz-setup.sh

编辑 ~/.zshrc 启用插件

plugins=(
    git
    zsh-autosuggestions
    zsh-syntax-highlighting
)

Java 环境

一般使用 Home | SDKMAN! the Software Development Kit Manager 管理 Java 环境。需要安装 unzip 包。

curl -s "https://get.sdkman.io" | bash

为 WSL 配置 Windows Terminal

为 CLI 程序开启鼠标滚动功能

默认情况下 WSL 中的 CLI 程序比如 lessnano 不支持鼠标滚动,需要手动设置。设置完成之后,鼠标操作将默认由应用程序接收,如需选中对应程序中的内容,需要按住 Shift 键然后再进行选择。

less (包括 man

将下面的内容保存为文本文件:

#env
LESS = --mouse

然后运行 lesskey <filename>(较新的发行版可以忽略这一步,将文本保存到 ~/.lesskey 即可)。

nano

~/.nanorc 中添加:

set mouse

vi[m]

~/.vi[m]rc 中添加:

set mouse=a

SSH Agent

使用 npiperelay.exe 将 Windows 套接字 //./pipe/openssh-ssh-agent 转发到 WSL12

首先需要确保 Windows 的 PATH 里有 npiperelay.exe,这样 WSL 内部就可以直接访问。可以通过 WinGet 安装。之后在 WSL 的系统里安装 socat

sudo apt install socat

然后将这一段脚本写入 ~/.win-ssh-agent/agent-bridge.sh

# Code extracted from https://stuartleeks.com/posts/wsl-ssh-key-forward-to-windows/ with minor modifications

# Configure ssh forwarding
export SSH_AUTH_SOCK=$HOME/.win-ssh-agent/agent.sock
# need `ps -ww` to get non-truncated command for matching
# use square brackets to generate a regex match for the process we want but that doesn't match the grep command running it!
ALREADY_RUNNING=$(ps -auxww | grep -q "[n]piperelay.exe -ei -s //./pipe/openssh-ssh-agent"; echo $?)
if [[ $ALREADY_RUNNING != "0" ]]; then
    if [[ -S $SSH_AUTH_SOCK ]]; then
        # not expecting the socket to exist as the forwarding command isn't running (http://www.tldp.org/LDP/abs/html/fto.html)
        echo "removing previous socket..."
        rm $SSH_AUTH_SOCK
    fi
    echo "Starting SSH-Agent relay..."
    # setsid to force new session to keep running
    # set socat to listen on $SSH_AUTH_SOCK and forward to npiperelay which then forwards to openssh-ssh-agent on windows
    (setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork &) >/dev/null 2>&1
fi

之后在 .bashrc 或者 .zshrc 中添加

source $HOME/.win-ssh-agent/agent-bridge.sh

就可以了。

GnuPG

参照 在 WSL2 中使用 GPG 命令行工具以及对 Git commit 进行签名

1Password CLI

使用 op 命令行进行方便且安全的凭据存取,首先在 Windows 中安装:

winget install AgileBits.1Password.CLI

之后在 .bashrc 或者 .zshrc 中添加如下内容:

# Aliases
alias op="op.exe"
# alias sudo="sudo -S <<< $(op read "op://Personal/Account Password/password")"

# Completions
eval "$(op completion zsh)"; compdef _op op.exe

参考

  1. Use 1Password SSH Agent in WSL – DEV Community ↩︎
  2. Forwarding SSH Agent requests from WSL to Windows – stuartleeks.com ↩︎

Mac 时间机器“检测到备份无法可靠恢复”的解决方法

最近备份到Mac mini网络磁盘的时间机器备份出现了无法完成的情况,似乎是在一次内核崩溃之后出现的。

具体的报错信息为:

时间机器检测到“目标”上的备份无法可靠恢复。时间机器必须抹掉现有的备份历史记录并创建新的备份来修复此问题。
Time Machine detected that your backups on “destination” can not be reliably restored. Time Machine must erase your existing backup history and start a new backup to correct this.

出现这个提示并不代表备份已经损坏,但系统并不允许进行新的备份。

如果不想抹掉备份历史记录,可以尝试在网络共享中找到备份磁盘映像(sparsebundle),这个时候磁盘映像文件可能是处于“锁定”状态,按Command + I打开详情将磁盘映像解锁。

然后右键-显示包内容,其中的“token”文件可能也会被锁定,同样解锁它。

然后使用Xcode打开“com.apple.TimeMachine.MachineID.plist”文件,将键“VerificationState”的值从2修改为1并保存。

之后再次重试时间机器备份并验证备份,如果能够成功验证那么备份就没有损坏。

在 WSL2 中使用 GPG 命令行工具以及对 Git commit 进行签名

网上找到的绝大多数方法都是使用 npiperelay 将 Gpg4win 的 GPG 的 Agent 的 socket 映射到 WSL2 里面,其实更简单的方法是直接在 WSL2 内部使用 gpg.exe

如果想要为 Git 签名但是私钥在智能卡里,可以直接设置 git config --global gpg.program gpg.exe,(如果GPG 不在 Windows 的 PATH 里,需要使用绝对路径,通常为 /mnt/c/Program Files (x86)/GnuPG/bin/gpg.exe,为了方便最好还是加到 PATH 里面去,加完之后需要打开一个新的终端)。

除非程序需要直接的 GPG Agent 访问或者不支持自定义 GPG 二进制,这个方案都比映射 GPG Agent 的套接字要方便不少。

罗技 MX Keys Mini —— 用了就回不去的输入体验

最近入手了 Logitech MX Keys Mini,使用几天后它集本上替换了Filco Convertible 2 TKL成为我的主要输入设备了。

懒得拍就找了官网的图。我购入的是Graphite,是一种偏暗的灰色,实际看起来与官网图片的颜色类似。

https://www.logitech.com/en-us/products/keyboards/mx-keys-mini.920-010388.html#buy-mx-keys-mini

键盘功能上,和罗技高端办公键盘都差不多。连接方面,MX Keys Mini不支持Unifying接收器,采用了新的Bolt接收器,包装盒内并不附带(无论是不是Mac版),因此我所有的设备只能通过蓝牙连接。键盘支持三台设备自由切换,这也是罗技MX系列的老本行了,和罗技的其它多设备键盘一样,如果你是用的是支持Flow功能的鼠标,那么键盘的多设备切换也可以跟随鼠标自动进行。键盘内置充电电池,通过USB-C接口充电,但是不支持作为USB键盘。MX Keys的功能键里这次有了一个很有趣的静音快捷键,听说是可以在网络会议中方便的开启和关闭麦克风,不过按下这个按键后似乎并没有向系统发送任何按键事件,需要安装罗技的软件才能使用。

输入体验是Logitech MX Keys Mini最让我惊喜的部分。我用过的键盘有笔记本内置的有宏碁、各种Thinkpad、Lenovo Yoga,也用过MacBook的蝶式和剪刀。外置的薄膜用过K480、K780和Magic Keyboard,机械键盘只长时间用过Filco Convertible 2 TKL棕轴。在这些键盘中,我可以毫不犹豫的说,除了机械键盘外别的都不如MX Keys。它类似老款Thinkpad的内置键盘:键程较长,手感柔软但段落分明,并不像Magic Keyboard那样清脆。但与老款Thinkpad不同的是,MX Keys在按压到底的时候也是“柔软”的,这一开始感觉有些点怪怪的,不过用多了就能发现之前使用薄膜键盘时“敲击在钢板”上的感觉不复存在了,这是一个很大的提升,能增加长时间输入的舒适度。

当我使用MX Keys作为主要输入工具仅仅半天后,用回薄膜中我第二喜欢的Lenovo Yoga 14s内置键盘就觉得有点不适应了,打字就像敲击在钢板上。这种体验的落差是我使用过那么多键盘从来没有遇到过的。当然,手感喜好因人而异,有些人可能更喜欢Apple键盘的清脆短键程,也可能有很多人喜欢各种轴体的机械键盘,不过对我来说,目前MX Keys Mini是我用过手感最好的薄膜键盘。而相比于机械键盘,Low Profile的设计又让我的手掌减少了不少压力。

总的来说,MX Keys Mini是让我很满意的键盘,功能足够,打字体验很棒。唯一的缺点可能是电池续航,按照官方的数据开启背光灯后只能用10天。

BitLocker 智能卡自签名证书

假定智能卡能被识别而且其中有自签名证书(如果是 YubiKey 可以参照这篇文章)。

修改注册表
将 HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\FVE 中的 DWORD 值 SelfSignedCertificates 设置为 1.

也可以把下面的文本保存为 REG 文件导入。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\FVE]
"SelfSignedCertificates"=dword:00000001

Reference: Using Smart Cards with BitLocker

YubiKey PIV 配置

一般信息

默认 PIN 码为 123456. 默认PUK码为 12345678。

默认 3DES 管理密钥(9B)是 010203040506070801020304050607080102030405060708。

存在以下密钥槽:

  • 9A, 9C, 9D, 9E: RSA 1024, RSA 2048, or ECC secp256r1 keys (algorithms 6, 7, 11 respectively).
  • 9B: Triple-DES key (algorithm 3) for PIV management.

对于当前版本的 YubiKey NEO 和 YubiKey 4,存储对象的最大大小分别为 2025/3049 字节。

目前,所有功能都可通过接触式和非接触式接口获得(与规范要求相反)。

以上信息从 Yubico 网站翻译得来

配置

YubiKey PIV 接口在Windows中是只读智能卡,所以需要使用管理软件 YubiKey Manager 进行管理。先从官网下载并安装 YubiKey Manager。插入 YubiKey 并进入 PIV 设置。

YubiKey Manager
YubiKey Manager / PIV

首先需要设置 PIN 和 PUK,打开 Configure PINs > PIN 设置用户 PIN,如果 YubiKey 是第一次使用或者初始化过那可以勾选 “Use default”。PUK 同上,注意,PUK 可以直接重置 PIN,所以请务必设置,如果不需要 PUK 可以通过多次尝试错误 PUK 来屏蔽 PUK。

接下来还可以设置 Management Key,这个是为了保护 YubiKey 中的证书不被恶意修改的,可以不设置也可以设置。不设置的话默认值在一般信息中可以查找到。

最后就是导入证书了,YubiKey 有4个证书插槽,分别是 Authentication, Digital Signature, Key Management 和 Card Authentication(分别对应 9A, 9C, 9D, 9E)。其中 Digital Signature 插槽中的私钥操作每次都需要 PIN,而 Card Authentication 插槽永远不需要 PIN(但是我实测还是需要)。我的习惯是把证书导入 Authentication 和 Digital Signature(Digital Signature 的证书似乎不能用于 BitLocker)。

打开 Certificates 选择合适的插槽后选择“导入”或者“生成”证书,导入的话需要导入 PKCS#12 格式(PFX 或 P12 文件)的证书,如果之前是通过 CSR 向 CA 申请证书则需要导入 CA 签名后的 DES 格式证书。一般个人使用生成一张自签名证书即可。

YubiKey Manager / PIV / Certificates

注:Yubico 提供的 PIV 管理软件已经从 YubiKey PIV Manager 换成了 YubiKey Manager。经过我的测试, YubiKey PIV Manager 不支持 YubiKey 5 系列,但 YubiKey Manager 支持。

在 GitHub Desktop 中对 Commit 签名

GitHub 的文档中提到 GitHub Desktop 不支持签名,应用中也确实没有给出签名选项。不过,可以通过修改 GitHub Desktop 使用的 Git 的配置来签名。

首先打开 GitHub Desktop 的安装目录,Windows 一般在 “%USERPROFILE%/AppData/Local/GitHubDesktop” 下面。

可以看到几个 “app” 开头的、跟着版本号的目录,选择修改日期最近的那个目录,依次打开 resources/app/git/cmd 会看到 “git.exe”,在 “cmd” 目录里面打开命令提示符,用 git 命令配置 Commit 签名就可以了。下面的命令会默认对所有 Commit 签名。

git.exe config --global user.signingkey <Key ID>
git.exe config --global commit.gpgsign true

使用 TinyProxy 搭建代理服务器

安装

sudo apt update
sudo apt install tinyproxy

配置

TinyProxy配置文件位于
/etc/tinyproxy.conf

注释掉 Allow 127.0.0.1 即可允许任何局域网设备连接

管理服务

启动

sudo service tinyproxy start

停止

sudo service tinyproxy stop

重新启动

sudo service tinyproxy restart

YubiKey OTP 配置

YubiKey的OTP接口有两个插槽(slot),分别可以用来存放两个凭据(OTP、Static Password、HOTP-TOTP等)。OTP密码是长度为45的字符串,前12位是该OTP凭据的ID,后面的是一次性密码。(获取OTP可以打开记事本,把输入法换成英文,插入YubiKey,然后触摸一下金属圆盘)。

Yubico在生产YubiKey的时候会在插槽1放入一个OTP凭据,Yubico提供的凭据ID开头是“cc”,后期上传的凭据ID开头是“vv”。Yubico提供的OTP凭据是受信任的,后期上传的没有出厂自带的那么可信,因为在传输和保存的时候私钥可能会泄露。这是官方的说法:’vv‘ prefix credentials are not guaranteed to have the same availability as production ‘cc’ prefix credentials. Yubico reserves the right to revoke any ‘vv‘ prefix credential on the Yubico validation service (YubiCloud) at any time, for any reason, including if abuse is detected or if the credential is loaded onto a counterfeit YubiKey. (From Yubico AES Key Upload)

注意,YubiCloud不允许“cc”开头的凭据ID上传,你可以在YubiKey Personalization Tool上面生成“cc”甚至别的开头的凭据,不过只能上传到自己或第三方建立的OTP验证服务器上。

管理OTP接口

我们可以使用YubiKey Personalization Tool来管理YubiKey的OTP接口(YubiKey Personalization Tool支持命令行,这里只介绍GUI的使用,Linux下可以PPA安装),我们可以从Yubico支持页面获得YubiKey Personalization Tool。

YubiKey Personalization Tool

在YubiKey Personalization Tool中点“Yubico OTP”,然后点击“Quick”或者“Advanced”就可以管理YubiKey的OTP接口,一般来说,Slot 1不进行改变。

如果要增加一个OTP凭据,插入YubiKey,选择“Configuration Slot 2”,然后点击“Regenerate”来生成一个凭据(这里可以多点几次增加随机数的熵),如果需要使用第三方验证服务器那需要记下所有文本框中的内容,之后点“Write Configuration”向YubiKey中写入配置。写入完后需要上传凭据到YubiCloud,工具会要求你打开一个网站,工具会自动在网站中填充刚刚生成的凭据,点击上传即可。

提示:在生成凭据的时候,请使用一台受信任的电脑。在上传凭据时,确保使用HTTPS连接并确认网站的SSL证书是由受信任的CA颁发的。

YubiKey 介绍

介绍

YubiKey是由Yubico生产的身份认证设备,支持一次性密码(OTP)、公钥加密和身份认证,以及由FIDO联盟(FIDO U2F)开发的通用第二因素(U2F)协议。它让用户可以透过提交一次性密码或是使用设备产生的公开/私密金钥来安全地登录自己的帐户。针对不支持一次性密码的网站,YubiKey也可以存储静态密码。Facebook使用YubiKey作为员工凭证;Google同时为雇员和用户提供支持。还有一些密码管理器也支持YubiKey。 (YubiKey – 维基百科

YubiKey 5 NFC

YubiKey每个系列有多个版本,分别支持USB-A、USB-C和NFC接口。NANO版本非常小,适合一直放在USB口里面。还有一个Security Key by Yubico,只支持FIDO U2F和FIDO2,不支持别的接口(比如OTP),不推荐购买。还有FIPS版本,支持FIPS 140-2,应该是用来存放证书的(比如文档、代码的签名证书),没有需求不推荐购买。

最近Yubico出了新的YubiKey 5系列,在YubiKey 4系列的基础下增加了FIDO2和NFC(只有YubiKey 5 NFC支持)。目前淘宝上有卖但是价格很高,我的YubiKey 5 NFC是在官网买的, 价格45刀。

接口

YubiKey支持如下接口:
U2F
FIDO2 (YubiKey 5 Series & Security Key by Yubico only)
OTP
OATH
OpenPGP
PIV

U2F

U2F(通用第二因素),是一种开放的标准,通过USB和NFC验证用户对设备的访问权。通过USB验证时,YubiKey作为HID设备使用 。目前很多应用(Google、GitHub、DropBox、Facebook、Twitter等)都采用这个标准,U2F验证的方式是服务器提交质询(challenge),设备用私钥签名,返回响应(response)。特点是要求直接的USB访问而且验证的时候没有输入框,所以远程桌面的时候一般都不能用U2F。

index__1.png
The basic process flow of U2F (From Yubico)

FIDO2

FIDO2是FIDO联盟开发的提供免密码认证的协议,只有 YubiKey 5 Series 和 Security Key by Yubico 支持。应用方面目前只有微软支持,Windows 10 Insider Preview 版本现在可以在设置里面调整FIDO2设置(不要点重置安全密钥,可能会导致OTP和U2F凭据丢失),需要把Microsoft Account网页调成英语才能设置,这个协议我没有过多的了解,附上官方的网页。

FIDO2

OTP

OTP(一次性密码)是Yubico自己的协议,在进行OTP验证时,YubiKey作为HID设备使用。触摸YubiKey上面的金属圆盘即可激活并向电脑输入一串字符,前12位是密钥ID,后面是一次性密码。服务器与YubiKey拥有同样的密钥,验证时使用Yubico的私有算法计算一次性密码进行验证,通过计数器防止重放攻击。YubiKey有两个OTP插槽(slot),出厂时插槽1会自带一个密钥(已经被安全地保存到YubiCloud服务器),出厂密钥的ID是c开头的,自己生成的是v开头的。对个人来说出厂密钥是最可靠的。YubiKey OTP插槽中的密钥可以手动生成,但是不可以导出,因此千万不要手欠删除出厂密钥,我之前在搞FIDO2的时候重置了OTP插槽,就再也弄不回来了。

OATH

YubiKey的OATH接口与别的接口不同,它并不直接进行身份认证,它更接近手机上的谷歌身份验证器。OATH用于存储HOTPTOTP凭据,大多数应用的两步认证都支持它们。

OpenPGP

YubiKey可以被识别成OpenPGP智能卡,可以存放OpenPGP证书的私钥。

PIV

PIV接口可以存放X.509证书,用于代码和文档签名。Windows会把YubiKey识别为智能卡,可以用于EFS,Bitlocker好像因为证书问题不行(更新:已经解决Bitlocker证书问题,参考这篇文章)。