Firefox不应该管理DNS(和证书库)

Firefox已经越俎代庖,开始管理证书了,而且还想染指DNS。

最近Firefox在nightly版本中添加了DNS overt HTTPS的支持,第一眼就觉得这个事情不是系统来做吗?比如Android支持DNS overt HTTPS才是比较合理的事情嘛。

看了Reddit上面的评论,发现其他人也有类似的感觉,不止一个人觉得这事应该由系统来做。

另外,这也可能会导致hosts文件配置失效;而在web开发中,修改hosts文件是常用的操作。

而且,Firefox中没有清除DNS缓存的地方,所以很多时候,对于hosts的修改,不能立即在Firefox中看到结果。

总而言之,让浏览器(比如Firefox和Chrome)来管理DNS,不是一个好主意。

说到这儿,Firefox之前也做过类似的事情:

Firefox不知道什么时候,开始自己搞了一套独立的证书信任系统,和系统内置的证书系统是独立的(至少在Android上是这样的)。

比如,我要使用charles抓https的包,需要将charles的tls证书倒入到Andorid系统的证书库中,但是回头一看,Firefox还是不认,所以还得自己将证书添加到Firefox的证书库中。

另外一个更加智障的问题是,我在charles抓包结束后,需要删除这个证书,我可以在Android系统的证书库中删除掉。但是对于添加到Firefox中的那一份,我是没有办法删除的,只能卸载并重新安装Firefox

阅读更多

cherry-pick到底应该怎么翻译?

git当中的cherry-pick命令,翻译成中文叫什么名字呢? GitLab给出了答案

// gitlab.po
msgid “ChangeTypeAction|Cherry-pick”
msgstr “优选”

这个是不是听起来怪怪的? cherry-pick的中文意思是“择优挑选”,比如

They seem to cherry-pick the loss leaders and discount items in the supermarkets and discount stores, relying on smaller retailers for everything else. 因为他们会选择超市和打折店里的特价商品和和打折商品,而其他所有的东西都是从小商贩那里获得。

当然,也要注意的是,写作论文的时候,只挑选那些好的数据写在文章中,这种行为也可以叫cherry-pick,比如:

Be careful not to ‘cherry-pick‘ data: don’t choose just what you like, or what supports your objective. 注意别“优选”数据:别选择一些只是您喜欢的,或者支持您的目标的。

所以从常用语义上来讲,优选这个翻译也不算太差。 但由于“优选”这个词在中国被用烂了,多用在电商等领域,如果我们开发的时候来一句“请将aaa提交优选到B分支”,完全不能理解啊。 个人觉得,翻译成“拾取”会比较好,比如“请将aaa提交拾取到B分支”就顺口好多。


另外,也可以看看GitLab对其他git术语的翻译: Revert 还原,Issue 议题等。

阅读更多

PHP/Composer是如何加载一个类的

PHP/composer开发中,我们只需要require 'vendor/autoload.php',然后就可以直接使用各种类了。那么这些类是如何加载的呢?其中有没有什么可以优化的点呢?

概览

PHP/composer下,类的加载主要到如下部分(还没有包括各个部分的初始化逻辑):

1
2
3
4
5
6
7
8
PHP中zend_lookup_class_ex
|-> EG(class_table)
|-> spl_autoload_call
|-> ComposerAutoloadClassLoader::loadClass
|-> findFile
|-> class map lookup
|-> PSR-4 lookup
|-> PSR-0 lookup

PHP的类加载

首先,PHP在运行的时候,需要一个类,是通过zend_lookup_class_ex来找到这个类的相关信息的。

zend_lookup_class_ex查找类的主要逻辑如下(假设类名字放到变量lc_name中):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
{
// 1. 类名字转化为小写
if (ZSTR_VAL(name)[0] == '') {
lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
} else {
lc_name = zend_string_tolower(name);
}

// 2. 直接在class_table中查找
ce = zend_hash_find_ptr(EG(class_table), lc_name);
if (ce) {
if (!key) {
zend_string_release(lc_name);
}
return ce;
}
// 3. 如果没有autoload_func,则注册默认的__autoload
if (!EG(autoload_func)) {
zend_function *func = zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1);
if (func) {
EG(autoload_func) = func;
} else {
if (!key) {
zend_string_release(lc_name);
}
return NULL;
}

}

// 4. 加载ACLASS的过程中,又加载ACLASS,递归加载,直接找不到类
if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
if (!key) {
zend_string_release(lc_name);
}
return NULL;
}

// 5. 调用autoload_func
ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name);
fcall_info.symbol_table = NULL;

zend_exception_save();
if ((zend_call_function(&fcall_info, &fcall_cache) == SUCCESS) && !EG(exception)) {
ce = zend_hash_find_ptr(EG(class_table), lc_name);
}
zend_exception_restore();

if (!key) {
zend_string_release(lc_name);
}
return ce;
}
  1. lc_name转化成小写(这说明PHP中类名字不区分大小写)
  2. 然后在EG(class_table)找,如果找到,直接返回(我们自己注册的类,扩展注册的类都是这样找到的)
  3. 然后查看EG(autoload_func),如果没有则将__autoload注册上(值得注意的是,如果注册了EG(autoload_func),则不会走__autoload)
  4. 通过EG(in_autoload)判断是否递归加载了(EG(in_autoload)是一个栈,记载了那些类正在被autoload加载)
  5. 然后调用EG(autoload_func),并返回类信息

SPL扩展注册

阅读更多

Docker for Mac with Kubernetes初次尝试

首先,2018-01-09日Docker公司宣布了Docker for Mac支持Kubernetes。 后来陆续尝试了几次,今天终于成功了,所以记录下。

安装Docker for Mac with Kubernetes

首先,安装Docker for Mac Edge版本:

brew cask install docker-edge

设置代理(我用的是https://github.com/netheril96/MEOW): 开启Kubernetes:   等待安装: OK了: kubectl version也能看到客户端版本和服务端版本了:

$ kubectl version
Client Version: version.Info{Major:”1”, Minor:”9”, GitVersion:”v1.9.2”, GitCommit:”5fa2db2bd46ac79e5e00a4e6ed24191080aa463b”, GitTreeState:”clean”, BuildDate:”2018-01-18T10:09:24Z”, GoVersion:”go1.9.2”, Compiler:”gc”, Platform:”darwin/amd64”}
Server Version: version.Info{Major:”1”, Minor:”9”, GitVersion:”v1.9.2”, GitCommit:”5fa2db2bd46ac79e5e00a4e6ed24191080aa463b”, GitTreeState:”clean”, BuildDate:”2018-01-18T09:42:01Z”, GoVersion:”go1.9.2”, Compiler:”gc”, Platform:”linux/amd64”}

创建kubernetes-dashboard 服务

$ kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
secret “kubernetes-dashboard-certs” created
serviceaccount “kubernetes-dashboard” created
role “kubernetes-dashboard-minimal” created
rolebinding “kubernetes-dashboard-minimal” created
deployment “kubernetes-dashboard” created
service “kubernetes-dashboard” created

等一会就可以看到创建好了:

$ kubectl get pods –namespace kube-system
NAME READY STATUS RESTARTS AGE
etcd-docker-for-desktop 1/1 Running 0 6m
kube-apiserver-docker-for-desktop 1/1 Running 2 6m
kube-controller-manager-docker-for-desktop 1/1 Running 0 6m
kube-dns-6f4fd4bdf-zl9dh 3/3 Running 0 7m
kube-proxy-xsx8n 1/1 Running 0 7m
kube-scheduler-docker-for-desktop 1/1 Running 0 5m
kubernetes-dashboard-5bd6f767c7-6szsl 1/1 Running 0 1m
$ kubectl get deployments –namespace kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kube-dns 1 1 1 1 7m
kubernetes-dashboard 1 1 1 1 1m

阅读更多

如何在macOS上运行GTK 3(hello, world)

首先,安装 Homebrew

然后,brew install gtk+3 随后,查阅GTK的官方文档,写Hello, world:

hello.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <gtk/gtk.h>

static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;

window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
}

int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;

app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

return status;
}

然后编译:

1
gcc `pkg-config --cflags gtk+-3.0` -o hello hello.c `pkg-config --libs gtk+-3.0`

当前目录下就有了hello二进制可执行文件,执行即可:

阅读更多

Use pty as ansible connection

Well, sometimes, we can only use pty to access machines. For example, Jump Server only allowed use ssh pty to type command, get the result. But, how can I deploy application via ansible?


There are two good news:

  1. pexpect can interactive with the ssh session.
  2. ansible can use custom connection plugin.

Let’s try it

Let’s start at directory ansible-pty Firstly, we should create a connection plugin. Put those code to ansible-pty/plugins/pty.:

import base64
import re

import pexpect
from ansible.plugins.connection import ConnectionBase
from ansible.utils.display import Display

display = Display()

class Connection(ConnectionBase):
transport = ‘pty’
_mark = “=” * 10

阅读更多

[评论]systemd @ Facebook — a year later[All Systems Go! 2017]

今天看了All Systems Go! 2017上,systemd @ Facebook — a year later这个talk。记录下自己的感想。

首先,Facebook软件更新还是比较及时的,CentOS 7 和 systemd 都上了:

可怜我司还在Ubuntu 14.04上 另外,很多基础组件都是和上游有良好的沟通的:

长远来看,紧跟上游对公司的技术实力、技术影响力都有好处。当然,短期来看,我的系统工作的很好,不跟进上游没毛病啊。国内,大部分是后者吧……

当然,大公司都有自己的repo:

Facebook居然都已经接入了Meson,很让我吃惊。

资源管理

阅读更多

如何退出无响应的 SSH 连接

经常出现ssh连接由于网络问题,“卡住”了。不能进行任何操作,也不能退出。 ssh文档里面也有写通过~.来断开ssh连接:

$ man ssh

ESCAPE CHARACTERS

 The supported escapes (assuming the default \`~') are:

 ~.      Disconnect.

 ~?      Display a list of escape characters.

但是,实际使用过程中发现,按了没有反应。 后来看了其他人的做法,发现两个技巧:

  1. ssh转义字符,只有在新行生效。所以最保险的按键方式是:回车 -> Shift+` -> .
  2. 由于输入两个~会导致ssh直接发送~。比如我们按~``~``~``. 会关闭第二层ssh,而不是当前失去响应的ssh会话。

所以为了保险起见,我的操作是这样子的: 回车``~``?,直到出现ssh的转义字符帮助(没有出现就继续按回车``~``? 然后按 ~``. 退出ssh


~``~``~``. 会关闭第二层ssh,对吗?

  1. ~``~是给第一层ssh会话发送~字符
  2. ~``~``~是给第二层ssh会话发送~字符
  3. ~``~``~``.是给第二层ssh会话发送~``.字符,即关闭第二层ssh会话

阅读更多

如何调试iptables [CentOS 7]

首先,来一张非常有用的图:

基础知识

iptables可以jump到TRACE目标,开启_包追踪_(packet tracing)选项。 iptables有一个raw表,基本上是iptables最先处理包的地方。

开始调试

在最入口的位置给符合条件的包开启包追踪,比如对所有进入的icmp包:

1
iptables -t raw -I PREROUTING -p icmp -j TRACE

有的时候,还需要加载需要的模块(CentOS 7下):

1
modprobe nf_log_ipv4

然后你就可以在/var/log/messages日志中看到包追踪信息了。

阅读更多

Hello Wayland -- Wayland教程

翻译自https://hdante.wordpress.com/2014/07/08/the-hello-wayland-tutorial/

TLDR

我写了一个wayland下的hello world,源码在 https://github.com/hdante/hello_wayland

介绍

从最终用户的角度,很容易理解wayland是什么:它是一个新的窗口系统,它将显示服务器和窗口管理器合并了[1]。从技术角度来看,wayland是为了摆脱传统,使用现代设计来实现一个高效的窗口系统,解决X窗口系统中长期存在的效率问题和一些极端情况[2]。这个教程展示如何实现一个作为wayland客户端的hello world程序、解释基础的wayland概念、创建一个GUI程序的必要流程。hello world程序不需要任何GUI工具包,它直接使用底层的wayland协议,以便解释wayland的基础概念。本教程是我自己研究wayland协议的结果。教程分为两部分。这是第一篇教程,解释所有的概念和程序的高级部分。

再问一次,什么是wayland?

wayland窗口系统的的完整设计分为好几层。如果你下载了wayland library的代码[3],或者你看了下wayland的API[4],你会注意到两层:

  1. 最基础的一层是进程间通讯功能的实现,以及一些实用工具。比如主循环调度器和一些数据类型。大部分这些代码都出现在wayland library中(所有在src文件夹[5]中的内容),并且和窗口系统无关。
  2. 第二层是窗口系统协议。它的描述在protocol/wayland.xml[6]文件中,这个文件应该算是一种接口定义语言。IDL文件可以用wayland-scanner 工具处理,并在 wayland-client-protocol.h 和 wayland-server-protocol.h中生成代理方法。协议定义了客户端程序和显示服务器的基础功能。比如访问输入设备、注册共享缓存以便显示在屏幕上。wayland library并不实现这些协议。这些协议的实现被分割到一个第三方层。服务端的参考实现是weston的一部分[7],它在客户端和服务端都定义了一些附加层。以实现wayland协议。在hello world程序中,我们并不需要了解任何关于weston的东西。我们仅仅需要IDL文件。

从上面关于wayland library的描述中,我们发现wayland的三个定义。它是一个(额听用途的)IPC库,不像D-Bus库,它仅仅用于显示服务器,并且它没有定义wayland到底是什么、wayland协议的定义以及如何找到协议定义。我相信即使人们在阅读官方文档后,大部分人也不明白wayland到底是什么。我想,这三个定义澄清了“什么是wayland”这个问题,每一个定义都能够用在不同的上下文中。

Hello, World!

阅读更多