服务器维护初步结束

2013 年,爱德华·斯诺登披露了棱镜计划,于是人们,包括盖子自己终于学会了如何正确配置 TLS;2014 年,各研究者纷纷加入到 Linux 安全的研究行列中,随着一篇“炮打shell司令部root,我的一个 exploit”的 Bug 报告,以前那种“随便配置个 Linux 服务器让它跑”的欢乐时光已经彻底结束,真是让各运维苦不堪言,都快患上 Shell Shock 了,人们不得不以正确的态度开始对待安全;2015 年,越来越多的安全审计也被提上日常。

在这样的背景环境下,学习并应用的安全技术是多多益善的。因此,我在今年初部署了一台实验性的服务器,用于测试 PaX 技术。如今,虽然 grsecurity 以盖子的能力完全掌握还需要时间,但 PaX 已经完成测试可以部署了,而盖子的服务器运行了两年时间,也暴露出来一些问题。

因此盖子进行了一次大型服务器维护。而凑巧,在服务器进行维护之前的 8 月 15 日,忽然被 GFW 屏蔽了!一天之后,服务器也进入了关机维护状态,以至于不少人出现了“这服务器怎么挂了代理也不能翻墙访问”的错觉。

长话短说,这此维护的摘要如下(随着维护的进行,可能会更新):

  • 发行版切换到 Gentoo Hardened 稳定版
  • 全面启用 PaX 和其它系统加固措施
  • 服务器 IP 被 GFW 屏蔽,目前的新 IP 切换至 106.187.50.120。IP 配置和解析记录的切换将逐步进行,若要了解细节或需要帮忙,欢迎联系我。
  • 服务器 SSH 密钥重新生成:

    • RSA 指纹:SHA256:rdiQjAfAIG1OsgmKgSZgLeslb50QqcjsIa4oi2WnsA8
    • ED25519 指纹:SHA256:LGohlHLSTIP/PRW16JwNdQbjXrV887VZKeseJeGG2uQ
  • 禁用不活跃、以及不使用 PHP 用户的 php-fpm 进程,一些用户已经长期不活跃,还有一些用户不需要使用 PHP。但 php-fpm 却被盖子配置成默认运行,消耗系统资源。以下用户的 PHP 已被默认禁用。盖子计划未来对不活跃用户进行清理。

    • alleria0218
    • cnzh2005
    • colin4124
    • ffddybz
    • grinv
    • huangtao728
    • lengbamboo
    • pynix
    • roowe
    • tianyu
    • wangfeitong
    • xinmuontheway
  • 严禁运行 SSH 端口转发,以及 Shadowsocks 等代理服务器。这是服务器最后的备用 IP,作死的行为将导致服务器完全不可用。我会定期进行进程审计。

为什么 os.path 可以被直接导入

今天在微博上,@julyclyde 发现了一个看似简单但很有意思的问题,import os.path 的行为很奇怪。

Python 使用 import 语句来“导入”外部模块,而常见的情况有:

  • a 已经被导入了,a 已经被 sys.modules 记录在案,重复导入没有效果,只会返回 sys.modules 中的 现有的引用
  • a 是一个位于搜索路径中的文件,Python 导入该文件
  • a 是一个位于搜索路径中的目录,包含 __init__.py,Python 导入此 package
  • 使用 Import Hook 在 Python 的 import 语句中挂上钩子,改变 import 逻辑,实现自定义行为

在导入子模块 a.b 时,

  • a 是 package,Python 导入该 package 的子模块 b
  • a 定义了子模块 __path__ 列表,Python 根据这个搜索路径去寻找并导入 b
  • b 是 a 下的一个变量,不是子模块,因为不存在字面上名为 “a.b” 的模块,导入失败

但是 os.path 却不符合其中的任何一种条件。首先,os 是一个普通的文件, 位于 /usr/lib64/python[x].[y]/os.py,也没有 __init__.py,因此它并不是 package;通读源代码,没有发现它使用了任何 Hook,也没有定义 __path__,更不存在 os.path 这个模块,因此 import os.path 理应失败!然而,有趣的是,os.path 居然可以作为 os 的 子模块直接导入,这实在是太奇怪了。

仔细阅读 os,不难发现这段代码

if 'posix' in _names:
    ...
    import posixpath as path
    ...
elif 'nt' in _names:
    ...
    import ntpath as path
    ...
elif 'ce' in _names:
    ...
    import ntpath as path
    ...
else:
    raise ImportError('no os specific module found')

sys.modules['os.path'] = path

从中我们可以看出,os 会根据不同的系统平台导入不同的 os.path 实现模块,然后把该模块 的引用,强行插入到已导入模块 sys.modules 里。这样一样,import os.path 会优先在 sys.modules 搜索到目标,立刻返回。

问题在于,os 的代码是在何时被执行的呢?它是在 Python 启动时的 bootstrap 中执行的吗? 使用 python -v 调试,

import _frozen_importlib # frozen
import imp # builtin
import sys # builtin
# /usr/lib64/python3.4/__pycache__/os.cpython-34.pyc matches /usr/lib64/python3.4/os.py
# code object from '/usr/lib64/python3.4/__pycache__/os.cpython-34.pyc'
# /usr/lib64/python3.4/__pycache__/stat.cpython-34.pyc matches /usr/lib64/python3.4/stat.py
# code object from '/usr/lib64/python3.4/__pycache__/stat.cpython-34.pyc'
import 'stat' # <_frozen_importlib.SourceFileLoader object at 0x7f70160d1e10>
# /usr/lib64/python3.4/__pycache__/posixpath.cpython-34.pyc matches /usr/lib64/python3.4/posixpath.py
# code object from '/usr/lib64/python3.4/__pycache__/posixpath.cpython-34.pyc'
# /usr/lib64/python3.4/__pycache__/genericpath.cpython-34.pyc matches /usr/lib64/python3.4/genericpath.py
# code object from '/usr/lib64/python3.4/__pycache__/genericpath.cpython-34.pyc'
import 'genericpath' # <_frozen_importlib.SourceFileLoader object at 0x7f70160d6710>
import 'posixpath' # <_frozen_importlib.SourceFileLoader object at 0x7f70160d30b8>

>>> "os" in sys.modules
True
>>> "os.path" in sys.modules
True

可以看到,在 Python 解释器在初始化过程中,os 确实被执行了一次。而且,osos.path 存在于已导入列表中。但是,使用 -S 让 Python 不自动 import site 进行部分初始化之后,os 和 os.path 都不会自动导入了,但 import os.path 依然可以正常运作。

众所周知,在 Python 中,对象是被代码实时的创造出来,因此,import 必然要执行模块中的代码,否则变量、函数、类都不会存在,import 也就不可能导入任何东西了。但值得一提的是,在而导入子模块的时候,因此父模块的代码也会不可避免的被执行,原因之一是 Python 需要查阅 父模块的 __path__ 变量来决定子模块的位置,也就是说,考虑 hello.py

print("Hello, world!")

如果我们试图 import hello.should_not_exist

>>> import hello.should_not_exist
Hello, world  # hello.py 被执行了

# 执行完了,现在看看程序有没有定义好 `__path__`
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'
# 然而 `__path__` 不存在,except AttributeError,继续尝试

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'hello.should_not_exist'; 'hello' is not a package
# hello 也不是一个 package,因此出错

可见,我们在 import os.path 时,首先 os 被执行,注入 os.pathsys.modules 里,然后,Python 才尝试导入 os.path,这时它 已经位于导入列表,于是得以顺利导入。因此,与其把 os.path 看作 os 的子模块,不如把它看作名为 os.path 的独立模块。根据同样的原理,我们不难在自己的项目中使用同样的技巧。

开发者张峻锋被指参与恶意软件

今天下午,惊闻 MMD 宣布张峻锋(微博:@马鹿峻鋒連聊C)被认定参与了恶意软件的编写。按照我个人的了解,张峻锋在学业之外,积极参与自由软件开发,包括 AOSC 社区的一部分工作,不太可能从事利用蠕虫危害网络安全的事情。因此做了一些调查,事件始末如下。 阅读更多…

宣布「盖子 CA」

很多时候,去大型正规 CA 机构获取证书是不现实的,包括但不限于:测试 应用、私人服务器。然而,单独为这些使用场景每次都现生成一个自签名证书 不便于管理:你必须手工核对大量的自签名证书指纹。

「盖子 CA」是比尔盖子为了对自己的自签名证书进行统一管理,解决其签名证书混乱,而自行设立的个人 CA。当然了,这个 CA 是不被任何厂商信任度的。比尔盖子的信任管理手段很简单,就是使用 PGP 对我的 CA 证书进行签名,这样,如果 你本来就信任我的 PGP 公钥,那么你就可以确信某证书的确是我签署的。

比尔盖子保证:

  • CA 的私钥是安全的,它是在断网情况下在 tmpfs 中生成的,签署完毕后,就被 GPG 加密保存到硬盘。
  • CA 的签名过程也是安全的,安全措施类似。
  • 我只会对我自己管理的应用进行签名,而不是代替别人,给别人的域名和应用,如 GMail 签名,更不会用来进行中间人攻击。
  • 如果有网友可通过 PGP 配合,证明其身份,以及服务器或域名的管理权,我可以帮他进行签名,同时我会在个人网站公开查验记录。

什么?你依然不敢把我的 CA 加入全局信任列表?我也并没有期待你这么做,因为我这么做的主旨仅仅是:让他人仅仅通过核对一个 CA 证书证明我的服务器是真实的,而不是核对大量证书。

目前使用这个证书的有

  • Starbrilliant 使用的 brilliant.biergaizi.info
  • erhandsome 上的 XMPP

那么这个证书有什么缺点呢?不支持吊销……因为这个 CA 我并不打算长期使用,我想如果发生证书泄露我会作废 CA,因此这似乎不是一个问题。

签名的信息和证书可以在这里查看

服务器 SSH 新增备用端口

由于众所周知的原因,服务器的 SSH 端口 22000 开始变得不太稳定,经常出现无法连接的情况。因此,现启用备用端口,如无法连接服务器,可尝试连接端口 12450

利用公共邮件列表进行邮件洪水攻击

A Flooded Mailbox

近日起,比尔盖子在 24 小时内收到了 20000 封来自公共邮件列表的订阅确认邮件,八成都来自自由和开源软件(FOSS)项目的邮件列表。而涵盖的项目也至少多达 20 个,不限于 OpenBSD、FreeBSD、GNU 计划、Ubuntu、CentOS、Qt、HostAp,甚至是以邮件著称的 Postfix。“订阅者”来自多个 IP。

在社交网络上分享经历后,不到 5 个小时,截至第一次发稿,就确认了受害者 @LI欣欣zn, @黑椒饼干, @路过的小新, @玩脱了的奶鱼, @機智的阿卡林chan, @06peng, @被窝型笨笨鱼, @和樹白翼, @无名小卒_路人A,似乎以技术圈为主。紧接下来的几天内,更是确认了萌娘百科官方邮箱,月光博客的作者 William Long,上海 Linux 用户组的 Thomas 等显著案例。部分受害者的邮箱因来信太多已经停止工作。个人用户只能暂时利用关键词过滤器规避攻击。更有甚者,@和樹白翼 紧急更换的新邮箱居然在新的一波攻击中遭殃。

邮件列表是 FOSS 项目的重要交流工具,日常开发几乎完全倚仗邮件列表。订阅邮件列表时,常见的程序均会给用户发送确认邮件,避免用户受到骚扰。然而,由于 FOSS 项目邮件列表大量存在,这就使得利用确认邮件本身加以骚扰他人成为可能。邮件列表通常均使用 GNU Mailman,而且通常不设有验证,更是为批量自动化操作提供了捷径。一个数字节的 POST 请求即可放大为内容更长的电子邮件。

这已经不是第一次发生类此状况,去年,GNOME 基金会管理的 FreeDesktop.org 列表就被利用进行攻击,管理者通过自行给 GNU Mailman 订阅增加了 reCAPTCHA 验证解决了问题。然而,还有大量的社区邮件列表处于没有保护的境地下(如 Fedora Project)。如果公共邮件列表一旦被广泛利用,这类低成本的攻击将会严重耗费 FOSS 项目系统资源,影响大量潜在的个人或机构正常使用电邮,如果这类邮件被归类为垃圾邮件,更会影响用户和开发者的正常工作。

布局与输入法独立的可能性 a.k.a 我为什么在勉强使用 Fcitx

输入源管理的统一

前两年 GNOME 开始将 iBus 集成为其的一部分,为用户提供更为一致的输入体验,引发了众多非议,包括强迫用户使用如此之烂的 iBus “输入法”(显然是把 iBus 框架和 ibus-pinyin 引擎混为一谈的),阻止用户换用其它输入框架等等。 阅读更多…

PGP 邮件自动加密方案

互联网安全随着以 NSA、GCHQ 为首的大规模政府监视已经变得岌岌可危了。Google 虽然还有一些信任度,但也不是像以前一样可以完全信任了。就说电子邮件吧,自建服务器才是目前最为可行的方案。然而,一旦服务器被入侵,上面的明文邮件也会全部泄露。

只有数学还是可信的。如果我们的邮件服务器在接收到邮件的同时,对邮件进行 PGP 加密再储存(已经加密就不需要再加密了),就是一个完美的安全方案了。如果这封邮件本身还是通过 TLS 加密的 SMTP 投递过来的,那么可以说牢不可破了。我们还可以把服务器配置成一个转发服务器,继续用自己原先的邮箱服务。

原本盖子打算写一个 Postfix 的 Filter 脚本来解决这个问题,然而,盖子发现几年前,就有人编写了 Exim 和 qpsmtpd 的插件支持,都是 Perl,在此分享:

注意,这会导致垃圾邮件也会被加密。一定要配合完善的反垃圾措施使用,qpsmtpd 的反垃圾就非常强大。

GPG 密钥更换

pub rsa4096/717E3FB8 2013-03-20 [已吊销:2015-01-01]
uid [ revoked] Tom Li (Biergaizi) (My Gmail) biergaizi2009@gmail.com
uid [ revoked] Tom Li (Biergaizi) admin@biergaizi.com

吊销原因:密钥已泄漏

This key was considered as a unsafe key, because the private key was copied to multiple computers, including some semi-public computers. Although there is no any evidence shows anybody stole my private key, but I think I’d better to revoke the key and generate new keys. The new keys are E88E8D6D (crypt), 01EE20CD (sign), and 26DC385B (auth). Tom Li Thu Jan 1 16:31:50 CST 2015

服务器 SSH 密钥变更

从即刻起,服务器 SSH 的密钥变更为 c5:87:39:99:9f:1f:74:c0:36:83:44:93:c8:c3:bd:d9 (ECDSA)。请从 .ssh/known_hosts 中删除 biergiazi.com (106.187.38.29) 的旧记录,并重新核对指纹并信任服务器。同时,SSH 使用的加密算法限制也更加严格,3DES、RC4 等垃圾弱算法将不被服务器接受。

望互相转告,以免影响诸位的正常使用。

什么?你说 NSA 在 ECDSA 中植入了后门?那也比继续用之前貌似早就泄漏的 RSA 密钥强。

备注:

PuTTY 受到英国的密码学出口限制,以及专利的障碍,导致虽然 ECDSA 一直在 wishlish 中,但几年后依然没有实现,无法正常连接使用 ECDSA 的服务器。而且,PuTTY 开发早已不活跃。

推荐使用以下替代品,同为 FOSS:

  • IceIV + PuTTY

    • PuTTY 的 fork,操作与界面不变,但增加大量新特性,甚至支持 ADB
  • TeraTerm

    • 早年作为 Windows 超级终端 的替代品开发,可扩展性强,甚至支持 VBA 宏,而且默认的配色方案是好评如潮的 Solarized
服务器君用了 0.670 秒钟,查询了 45 次数据库(17 次被缓存),消耗了 13.67MB 内存,努力为您呈现了这个页面。