输入源管理的统一
前两年 GNOME 开始将 iBus 集成为其的一部分,为用户提供更为一致的输入体验,引发了众多非议,包括强迫用户使用如此之烂的 iBus “输入法”(显然是把 iBus 框架和 ibus-pinyin 引擎混为一谈的),阻止用户换用其它输入框架等等。 Continue reading
前两年 GNOME 开始将 iBus 集成为其的一部分,为用户提供更为一致的输入体验,引发了众多非议,包括强迫用户使用如此之烂的 iBus “输入法”(显然是把 iBus 框架和 ibus-pinyin 引擎混为一谈的),阻止用户换用其它输入框架等等。 Continue reading
互联网安全随着以 NSA、GCHQ 为首的大规模政府监视已经变得岌岌可危了。Google 虽然还有一些信任度,但也不是像以前一样可以完全信任了。就说电子邮件吧,自建服务器才是目前最为可行的方案。然而,一旦服务器被入侵,上面的明文邮件也会全部泄露。
只有数学还是可信的。如果我们的邮件服务器在接收到邮件的同时,对邮件进行 PGP 加密再储存(已经加密就不需要再加密了),就是一个完美的安全方案了。如果这封邮件本身还是通过 TLS 加密的 SMTP 投递过来的,那么可以说牢不可破了。我们还可以把服务器配置成一个转发服务器,继续用自己原先的邮箱服务。
原本盖子打算写一个 Postfix 的 Filter 脚本来解决这个问题,然而,盖子发现几年前,就有人编写了 Exim 和 qpsmtpd 的插件支持,都是 Perl,在此分享:
注意,这会导致垃圾邮件也会被加密。一定要配合完善的反垃圾措施使用,qpsmtpd 的反垃圾就非常强大。
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 的密钥变更为 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:
更新 1:经过 tonghuix 与官方的交涉,现在我获得了全套管理工具,和 PKCS#11 的动态库,已经可以和 gpg 联合使用了。然而灵活性还是太差,因为私有中间件只能在 x86 上工作,打算进行反向工程。
如果你熟悉并使用以 RSA 为代表的非对称加密算法,来加密文件、签名电子邮件或者登录 SSH 服务器,那么你肯定会遇到密钥便携性的问题。如果你带着个装有私钥的 U 盘四处跑,私钥什么时候被拷贝走了估计你也不会知道。
为了解决这个问题,可以将私钥放到一个黑盒里,并由黑盒完成全部的加密和签名,同时没有办法从中获取私钥,还可以设置 PIN 码。这个黑盒就是智能卡。有两种规格的智能卡可以实现上述需求:其一是 OpenPGP card,由 FSFE 主导开发,开箱即用,但很难获得;第二是各类符合 PKCS#11 标准的智能卡。
ACOS5-64 就是一款 PKCS#11 的智能卡。它不但支持非对称加密,还支持对称加密,从特性上看,是一款十分强大的智能卡。然而千万不要购买它,这卡……没!有!驱!动!对,你没有看错!
既然支持 PKCS#11,那么应该直接使用通用工具就可以了吧?图样图森破!PKCS#11 允许厂商提供一个动态库来提供 PKCS#11,而这个动态库就相当于私有驱动。而 ACOS5-64 支持 PKCS#11,却没有提供驱动。事实上,ACS 公司确实开发了相关的驱动,但附在 SDK 里,需要另行购买,然而,这个驱动究竟是 Windows Only,还是也有 so 模块我们不得而知。而且,就算有 Linux 模块,但因为这是二进制驱动,因此无法在非 x86 下正常工作。
但不同于其它卡片的是,此卡的具体规格和 Datasheet 均可获得,不需要签署 NDA。曾有一 MIT 学生在 2010 年企图在 OpenSC 框架下实现此卡驱动,然而他仅仅完成了基本功能,以及 RSA 1024 的支持,最终因为众多坑放弃开发。
也就是说,这卡在任何系统平台与应用程序上,均完全无法使用!
更新 2:wget 1.16.1 版本已包括补丁,问题彻底解决。
更新 1:我的补丁已经被接受了,Bug 已修复。
wget
是 GNU 开发的实用下载工具,最近它刚刚发布了 v1.16。
先介绍一下背景,wget
向来就有两种进度条,“点形”和“条形”,其中,“条形”还有可选的跑马灯效果。
“刷屏点形”是指这样的效果
0K .......... .......... .......... .......... .......... 0% 107K 8m30s
50K .......... .......... .......... .......... .......... 0% 52.0K 13m0s
100K .......... .......... .......... .......... .......... 0% 31.3K 18m21s
150K .......... .......... .......... .......... .......... 0% 22.0K 24m4s
如果你的终端设备功能有限,不能做到即时更新屏幕内容,或者是重定向到了文件,“点形”进度条就很实用。
“条形”就是指这样的效果
filename 0%[ ] 134.05K 59.7KB/s
很适合可以即时更新的终端。
这两种类型可以使用
wget --progress=dot
wget --progress=bar
切换。
现在问题来了。如果文件名称很长,条形进度条左侧那一点点空间显示不下该怎么办呢?wget
的开发者想出了一个跑马灯效果,很像大街上的 LED 横幅,不停的让文字滚动,这样用户就可以“管窥”整个文件名了。
然而,盖子发现一个特别郁闷,而且能逼死强迫症患者的问题。wget
的滚动有 Bug,文件名的最后一个字符始终不显示!就象这样:
this_is_a_
his_is_a_f
is_is_a_fi
s_is_a_fil
_is_a_file
is_a_file_
s_a_file_n
_a_file_na
a_file_nam
<-- WTF!
this_is_a_
在 progress.c
中,不难发现这段代码
if (((orig_filename_cols > MAX_FILENAME_COLS) && !opt.noscroll) && !done)
offset_cols = ((int) bp->tick) % (orig_filename_cols - MAX_FILENAME_COLS);
else
offset_cols = 0;
offset_bytes = cols_to_bytes (bp->f_download, offset_cols, cols_ret);
bytes_in_filename = cols_to_bytes (bp->f_download + offset_bytes, MAX_FILENAME_COLS, cols_ret);
memcpy (p, bp->f_download + offset_bytes, bytes_in_filename);
p += bytes_in_filename;
由于有一些字符占用 1 字节,有些占用 2 字节,因此下面部分的代码全都在处理把字符转换成字节数的问题,其实这段代码做的事情很简单
if (orig_filename_cols > MAX_FILENAME_COLS
&& !opt.noscroll // 没有禁用跑马灯滚动效果
&& !done) // 下载仍未结束
offset_cols = bp->tick % (orig_filename_cols - MAX_FILENAME_COLS);
bp->tick
是 int
,每刷新一次进度条,它会就自增 1,可以把它理解成进度条刷新的次数,(orig_filename_cols - MAX_FILENAME_COLS)
就不用多说了,显然是计算文件名超出最大允许长度的字符数。
最后,从 offset_cols 开始截取 orig_filename_cols,一直截取 MAX_FILENAME_COLS 个字符。
用取余数运算来实现不断截取字符串的特性,看起来还是挺巧妙的。不过,正是这里的代码存在着问题。
写程序的时候,经常因为该 + 1
/- 1
而忘记了(len()
vs. 下标),不该加减 1 的时候乱加减,导致典型的越界往往和正确范围只差 1 位。
再比如这些令人困惑的表述
def range(begin, end)
/* 11 日到 21 日间断电 */
/* 变量取值范围 0 ~ 256 */
到底包不包括这个 end,或者包不包括 21 日,或者 256?P.S:幸好数学家们早就意识到了这个问题,发明了区间表示法,圆括号表示“排除”,方括号表示“包括”。
而 wget
的“最后一个字符始终不显示”的 Bug,具有典型的“范围差 1”的特征,那真正的问题到底出不出在这里呢?
为了看看 wget
的这个算法到底有没有 Bug,写个程序检验一下。
FILENAME = "this_is_a_file_name"
MAX = 10
def cut(string, _min, _max):
assert _max <= len(string) - 1
return string[_min:_max]
for i in range(0, 20):
offset = i % (len(FILENAME) - MAX)
print(offset, offset + MAX, cut(FILENAME, offset, offset + MAX))
这就是 Python 版本的简单算法实现了,运行之后:
0 10 this_is_a_
1 11 his_is_a_f
2 12 is_is_a_fi
3 13 s_is_a_fil
4 14 _is_a_file
5 15 is_a_file_
6 16 s_a_file_n
7 17 _a_file_na
8 18 a_file_nam
<-- WTF!
0 10 this_is_a_
果然出错?那么问题究竟出在哪里呢?拿这个例子分析一下,”this_is_a_file_name” 有 19 个字符,而最大的允许字符是 10 个。那么,那么,相差 9,看来编写者认为 9 就是需要的滚动次数。然而,滚动 9 次,就是有 10 种组合啊!
果然忘记 + 1
,而接下来就不用多说了。就等开发者接受补丁了。真是低级错误不可避啊……
Gentoo 的 OpenRC 配置 IP 的方式是非常简洁的,只需简单修改 /etc/conf.d/net
就能完成任务。
然而,比尔盖子的 Gentoo Hardened 一直无法正确的配置 IPv6,主要表现是可以配置地址和 DNS,却认为网关是无效地址。
config_eth0="106.187.49.164/24
2400:8900::f03c:91ff:fe73:f8c7/64
"
routes_eth0="
default via 106.187.49.1
default via fe80::1
"
dns_servers_eth0="106.187.34.20 106.187.35.20 106.187.36.20 2400:8900::2 2400:8900::3"
有问题的就是这个 fe80::1
。
今天解决这个问题,发现这个问题的成因和解决方案都简单的气人。事实上,OpenRC 支持使用不同的工具初始化网络。在默认情况下,OpenRC 初始化网络的工具是最传统的工具,这些工具对 IPv6 支持有问题。而新的 iproute2
就没有这个问题。
emerge iproute2
然后在 /etc/conf.d/net
行首加 modules="iproute2"
让 OpenRC 使用 iproute2 的工具链配置网络即可。
很多时候,我们的文件系统中并不保存重要数据。比如 /var/tmp
, /usr/src
或 /usr/portage
,对于这些目录,我们可以专门创建一个文件系统,并以牺牲数据安全性(因为我们不需要)换取最高性能。
如果你的 ext4 分区中储存的是 /usr/portage
这样大量小文件构成的数据库,可以使用以下参数格式化:
mkfs.ext4 -b 2048 -i 2048 -O "dir_index" /dev/sdX
-b 2048 -i 2048
确保分区中有足够的 inodes,避免因大量小文件导致明明有空间却没有 inode 的困境发生;”dir_index” 会让内核以类似 ReiserFS 的 btree 储存文件,对于大量小文件有很大的性能提升。但其它类型的数据分区,比如 /usr/src
或 /var/tmp
请勿使用此方法格式化,请使用默认参数。
使用不安全的写入方式提升性能:
tune2fs -o journal_data_writeback /dev/sdX
禁用日志:
tune2fs -O ^has_journal /dev/sdX
使用以下挂载参数(写在 /etc/fstab
):
defaults,noatime,nodiratime,barrier=0,nosuid,nodev,data=writeback
noatime
和 nodiratime
彻底禁用一切访问时间记录;barrier=0
禁用为安全保护而设计的写入屏障;nosuid
和 nodev
提升安全性;data=writeback
使用不安全而最高效的写入方式。
效果拔群!
由于众所周知的原因,现将服务器端口号重新变更为 22000。望互相转告,以免影响诸位的正常使用。
啥?你说我为啥不用 iptables
转发端口?抵抗的行为会让服务器 IP 遭殃的……
GRUB 2 中,有个 play 命令,用来让蜂鸣器播放音频。这可不是什么玩法……
它接受无限个参数,对于一个典型的三参数的调用,文档如下
play [tempo] [pitch] [duration] {pitch2 duration2...}
tempo 是全局速度,所有的 pitch 都受到它的影响;pitch 即要播放的音频,单位为赫兹;duration 是持续时间。
为了播放音乐,需要搞清楚一个调用究竟是多长时间。把 play 看作一个函数,接受 tempo 和 duration 两个参数。经过试验:
tempo | duration | 时间 |
---|---|---|
60 | 1 | 1 s |
60 | 2 | 2 s |
30 | 1 | 2 s |
30 | 2 | 4 s |
120 | 1 | 1/2 s |
120 | 2 | 1 s |
从这里大概可以看出来,
时长 (s) = 60 / t * d
这样,如果使 t = 60000,d 就正好对应于 0.001 s,即一毫秒。这样,就可以轻松的将基于毫秒时长的 Linux 下 beep 调用翻译成 GRUB 2 的 play 调用了。
另外,这还可以用于 sleep。GRUB 2 提供的 sleep 分辨率只有一秒,但使用 play,让 pitch = 0 Hz,就曲线实现了毫秒级的 sleep 命令。
Copyright © 2023 比尔盖子 博客
Theme by Anders Noren — Up ↑