从狗日的 T 讯手中保护你的隐私

1 背景

撰写本文的起因,源自一篇旧闻: https://www.solidot.org/story?sid=59369

这个新闻虽然说的是腾讯游戏,但是并不能保证其他的国产软件没有做同样的事情,包括但不限于 QQ,微信,钉钉,百度网盘客户端,各种国产浏览器等。

因此,看到这个新闻后,我第一时间对电脑上的 shadowsocks 配置文件进行了保护。

本文的目的,就是介绍并推广保护的方法,让这些狗日的公司不那么容易得逞。

而我拖了一年多才写出这篇文章来,是因为最近对这个方案有了一个改进,觉得总算可以凑出一篇文章的篇幅了。(其实是懒。)

差点忘记最重要的一点,本文仅针对 macOS,Linux 用户可以借鉴。但如果您是正版或盗版 Windows 的受害者,那么看到这里就可以关闭了。

2 原理

保护的原理非常简单:列用类 Unix 系统的多用户特性,将 shadowsocks 配置文件的 Owner 设置为一个独立的用户,并将访问权限设置为仅 Owner 可读(0400),然后将 shadowsocks 服务也设置为使用该用户身份运行即可。

这里只是以 shadowsocks 为例,如果你使用的是 v2ray 或其他敏感服务,可自行举一反三。

桌面系统中的几乎所有应用程序,都是以当前登录用户的身份运行的。因此它就无法访问到那些不属于当前用户,且只允许 Owner 访问的文件了。

注意:这个方案是以你用 shadowsocks-libev 作为客户端为前提的,如果你用的是某些图形界面的客户端,那么显然它只能以当前用户身份运行,因此配置文件也必须是对当前用户可见的,也就无法避免被其他应用读取了。

3 方案 A

基于原理,首先就有了方案 A,这也是非常容易操作的一个方案:将 root 作为那个独立用户。

这里假定你是通过 brew 安装的 shadowsocks-libev,如果你是通过其他方式,那么部分文件的路径可能不同,请对照进行调整。

操作步骤如下:

1
2
3
4
5
6
7
8
# 将配置文件的Owner设置为root
sudo chown root /usr/local/etc/shadowsocks-libev.json

# 将配置文件的访问权限改为只有Owner可读
sudo chmod 400 /usr/local/etc/shadowsocks-libev.json

# 以root身份启动shadowsocks-libev的服务
sudo brew services start shadowsocks-libev

4 方案 A-MkII

通过方案 A,我们阻止了来自流氓软件的窥视,但是却带来了一个安全隐患:一个访问网络的程序,在以 root 身份运行。

这意味着,假如这个程序存在什么安全漏洞,那么攻击者可以直接拿到你的系统权限。

因此在这个方案里面,我们首先创建一个权限很低的用户,再通过他来运行服务。

这里假定你使用 paperplane 作为用户名和用户组名。

4.1 创建低权限用户

macOS 下使用 dscl 命令管理用户和用户组。

与 Linux 的 useraddgroupadd 命令不同,使用 dscl 创建用户和用户组时,需要手工分配 ID,因为 dscl 不会帮你自动选择。

在选择用户 ID 和用户组 ID 时,要确保不与已有的 ID 冲突,因此首先需要通过如下指令查看已分配的 ID:

1
2
3
4
5
# 查看现有的用户ID
sudo dscl . -list /Users UniqueID

# 查看现有的用户组ID
sudo dscl . -list /Groups PrimaryGroupID

一般情况下,macOS 系统中的 300~399 号用户 ID 和用户组 ID 都是未分配的。这里假定选择 301 作为用户 ID 和用户组 ID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建用户组 paperplane
sudo dscl . -create /Groups/paperplane
# 设置用户组ID
sudo dscl . -create /Groups/paperplane PrimaryGroupID 301

# 创建用户 paperplane
sudo dscl . -create /Users/paperplane
# 设置用户ID
sudo dscl . -create /Users/paperplane UniqueID 301
# 禁止此用户登录
sudo dscl . -create /Users/paperplane UserShell /usr/bin/false
# 设置用户所属的用户组
sudo dscl . -create /Users/paperplane PrimaryGroupID 301

# 为用户设置密码,尽可能复杂
sudo dscl . -passwd /Users/paperplane

至此,你的系统中就多了一个叫 paperplane 的用户和用户组,你可以把配置文件的 Owner 指给新创建的这个用户:

1
2
3
4
sudo chown paperplane:paperplane /usr/local/etc/shadowsocks-libev.json

# 修改文件的访问权限
sudo chmod 400 /usr/local/etc/shadowsocks-libev.json

4.2 使用低权限用户运行服务

首先执行下列命令,以 root 身份启动 shadowsocks 服务:

1
sudo brew services start shadowsocks-libev

之后,brew 会帮你生成一个服务描述文件,位于:”/Library/LaunchDaemons/homebrew.mxcl.shadowsocks-libev.plist”。

打开并编辑此文件,在其中添加 UserNameGroupName 两项配置。

以下是修改后的服务描述文件(7~10 行为新增的内容):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>homebrew.mxcl.shadowsocks-libev</string>
<key>UserName</key>
<string>paperplane</string>
<key>GroupName</key>
<string>paperplane</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/opt/shadowsocks-libev/bin/ss-local</string>
<string>-c</string>
<string>/usr/local/etc/shadowsocks-libev.json</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>

修改完成后,使用下列命令重新加载服务:

1
2
sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.shadowsocks-libev.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.shadowsocks-libev.plist

之后服务就会以用户 paperplane 的身份来运行了,可以通过如下命令验证:

1
ps -e -o pid,user,group,args | grep ss-local

5 总结

本文介绍的方案,其要点总结来说就是:

  • 创建独立的(低权限)用户,将敏感文件 / 数据设置为仅该用户可访问。
  • 将访问敏感文件 / 数据的进程也以对应的用户运行。

其实这是一个在 Linux 服务器中被普遍采用的策略,只不过桌面用户大多缺少对这方面的考虑。

而桌面用户平时面对的威胁,并不比服务器小,尤其是那些别有用心的公司开发的应用软件。

再次祝各位科学上网愉快,并祝像狗日的腾 X 这样的公司,早日倒闭。