cookie 的一点研究

Published on:
Tags: cookie http

这几天搞了一下 python 里面 cookie 相关的东西。我的目的是想要尝试用 python 登录某个网站,并且保持登录状态直到过期。因为 http 协议是无状态的,所以一般来讲,网站想要用户保持登录,那么网站在用户登录之后,必须要和用户端协商好怎么来证明这个用户已经登录过了。

用户端如果使用浏览器,那么网站就可以利用浏览器对 cookie 的支持来让用户在不知情的情况下,让网站在用户登录后发的一个 token 在用户后续的请求里面都包含上。

用户端如果不是浏览器,比如是个 python 程序,那么网站可以和用户协商每次请求里面都包含某个下发的 token(当然,甚至要求客户端每次请求都带着用户名密码也是可行的)。

但是如果网站本身只是给浏览器用户准备的,那么通过用程序来「模拟」浏览器行为,把必要的 token 保存并在后续的请求里面都带上,也是可行的。

python 里面,发送 http 请求可以简单的使用 urllib.request.urlopen(url),但是如果想要定制一下请求,比如修改一些 header 信息,那么就得使用 urllib.request.Request 这个 class 先构造一个 Request 对象,然后传递给 urlopen 了。

如果要处理 cookie,那就需要使用 http.cookiejar.CookieJar 了,有了 Cookiejar 对象,就可以把网站下发的 cookie 保存到这个变量里面,然后在必要的时候,可以返回给服务器端了。如果想要保存到文件,那么可以使用 http.cookiejar.LWPCookieJar 或者 http.cookiejar.MozillaCookieJar,也可以基于 http.cookiejar.FileCookieJar 自己实现一个子类,来用自己的办法保存和加载 cookie,比如保存到数据库什么的,这样就可以多台机器之间共享 cookie 了。

urlopen 本身不支持自定义 cookiejar 逻辑,得使用 opener = build_opener(HTTPCookieProcessor(cookiejar=Cookiejar对象)) 来先构造一个自定义的 openner, 然后使用 opener(Request对象) 来发送请求。

如果不定义自己的 cookie policy,那么会使用默认的 http.cookiejar.DefaultCookiePolicy,也可以自己基于 http.cookiejar.CookiePolicy 实现自己的逻辑。只需要 override set_okreturn_ok 这两个方法就可以。

http cookie 其实有很多属性,比如 domain, expire, path 等常见属性,也有 httponly, secure 等几个不常见的。这些属性都是浏览器处理的。就是说,浏览器把 cookie 返回给服务器端的时候,如果 domain 不匹配,或者已经过了 expire 时间等等一些不符合浏览器制定的 cookie 逻辑的时候,浏览器就不会把 cookie 发送给服务器端。就比如,服务器产生 cookie 的时候,声明了 domain=a.com,那么如果是来自于 b.com 的请求,浏览器是根本不会给他发送这个 cookie。再比如,服务器端产生 cookie 的时候,声明了 1 天后过期,那么 1 天之后,浏览器也不会再给服务器端发这个 cookie 了。

但是如果是我们自己实现客户端模拟浏览器的时候,其实我们是可以耍流氓的,可以制定自己的 cookie 逻辑,也就是上面提到的 cookie policy。比如我可以简单的在 return_ok 这个方法里面 return True,在任何情况下都把所有的 cookie 返回给服务器,这样服务器端如果不提前想明白,它是一点都不知道的。

所谓提前想明白就是想明白是不是需要针对这种情况做处理。如果本身我们系统也没有那么严格要求,那么不处理也可以。但是如果是某个比如金融系统,那么是必须要考虑的。否则如果完全依赖 cookie 的话,如果我通过某些手段弄到了用户的 cookie,那么我就可以骗过服务器端,让他认为我就是那个用户。

我想了一下,貌似被盗窃 cookie 这种事情服务器端不太好防范,但是可以做的是防止浏览器耍流氓。比如我们把 cookie 加密,并里面增加一个发送 cookie 的时间。收到客户端发过来的 cookie 之后,我们解密看看时间有没有过期,这样就可以在服务器端让 cookie 失效了。

另外,也可以考虑使用 session。session 是把一些用户的状态保存在服务器端。但是 session 实际上也是依赖 cookie 的,因为前面说了 http 协议无状态,就算可以把用户状态保存在服务器端,但是总还是得识别用户才可以。那个识别的 cookie 就是所谓的 session cookie,其实就是某个用户的唯一标识。

对于 session cookie 被窃,好像也没有太好的办法,无非也是想办法比对之前用户的一些状态信息,比如 ip 和现在的信息是不是一致,不一致可以认为有被窃的怀疑,这个时候让用户再次验证用户信息,这都不能 100% 保证,但是至少会增加窃贼的成本。

上面说到这些,都可以自己测试一下,测试也并不一定需要搭一个服务器端配合,以及使用复杂的抓包专鉴,其实使用 nc 就可以。

使用 nc -l 9999 就可以启动一个监听在 9999 端口的 socket 服务器。之后使用 python 或者 curl 之类的程序请求,就能立刻看到请求发送过来的 http 信息,这个对于学习 http 协议其实也很方便。

1
2
3
4
5
6
7
$ nc -l 9999
GET / HTTP/1.1
Accept-Encoding: identity
Connection: close
Cookie: QN2=test; QN1=ClbaCVfZF5lfszBALzTIAg==
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Host: localhost:9999

收到的上面这个请求,可以看到发送过来了 2 个 cookie。

如果还想测试数据返回的情况,那么可以写一个 test.resp 文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat test.resp
HTTP/1.1 200 OK
Date: Sun, 18 Oct 2009 08:56:53 GMT
Server: Apache/2.2.14 (Win32)
Last-Modified: Sat, 20 Nov 2004 07:16:26 GMT
ETag: "10000000565a5-2c-3e94b66c2e680"
Set-Cookie: QN1=ClbaCVfZF5lfszBALzTIAg==; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/
Set-Cookie: QN2=test; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/; secure; httponly
Accept-Ranges: bytes
Content-Length: 44
Connection: close
Content-Type: text/html
X-Pad: avoid browser bug
<html><body><h1>It works!</h1></body></html>

然后使用 nc -l 9999 < test.resp 命令启动服务,客户端来请求的时候,就会返回上面 test.resp 里面的内容。

从双拼讲输入法

Published on:
Tags: input

上高中的时候,就流行五笔打字,不过那会家里都没有电脑,都是去网吧(或者叫打字社)去学习的,不过那会学习这个貌似唯一的用途就是录入用。

当时也背过五笔的码表,王旁青头兼五一,估计很多人都很熟悉。上了大学在有更多机会接触电脑的时候,上网什么的,自然就开始使用拼音输入法,因为基本不需要练习,会盲打知道键盘按键键位就可以使用。当时用的比较多的是智能 ABC,后来 2000 年左右写书的时候,用的是紫光拼音,紫光的词库比智能 ABC 好一点,所以用起来也好用很多。此后一直使用拼音输入法。

直到应该是大概 2008 年左右,ssslang 在使用二笔,就开始想尝试一下码表输入法。因为本身使用了这么多年的电脑输入和拼音输入法之后,对字形其实已经失去了概念,如果学五笔的话,肯定会是很痛苦的。

而二笔输入法一个字 4 个码,第一个码还是拼音的第一个字母,但是大部分常用字都是 2 个码就可以出,所以这样等于每个字都至少知道了一半的编码,这个还是很赞的。

二笔输入法也有很多编码方案,当时选的是哲豆二笔,这个方案只用了 26 个字母键,所以也可以在手机上面使用(其他方案用了一些符号键,比如 [ ],当时手机还都是流行硬键盘,一般都没有单独的符号键,而且貌似现在的软键盘也没有单独的符号键)。我当时用的 palm treo 650,输入还是蛮爽的。后来自己把一些词库导入了进去,用起来就更加舒服了。

但是后来的问题是慢慢的一些流行的智能机没有那么好的输入法自定义支持,就没法用了,慢慢切回来了拼音输入法。

二笔是码表输入法,就是每个字有自己的编码,联系的过程就是熟悉码表的过程,如果某个字不熟悉,那么其实你是需要轻微的思考的,想一下那个字怎么写,是哪个码。所以输入的速度取决于对这些字的熟悉程度,遇到不熟悉的会有卡顿。

最近看到了不少双拼的讨论,就想尝试一下双拼。因为如果反正都是用拼音输入法,那么对于 ing, eng 这些,如果可以按一个按键就输入进去,那么岂不是可以节省很多时间?并且这个还是基于拼音的,和那些需要记住字形的输入法不是一个套路,看着还不错。

我是这周一开始尝试的。mac 上面用的是鼠须管,ios 用的 touchpal。双拼也有很多方案,我选的方案是小鹤双拼,也没啥特别的原因,就是看用的人挺多的。

尝试的结果就是,输入了 4 天之后,周五我又换回了拼音输入法。。。。

因为我越用越发现,双拼也是个码表输入法。开始想得是节省拼音的输入时间,但是打字的时候,比如输入 hao 的时候,想到的不是输入 h 然后输入 ao 对应的字母 c,而是熟悉之后自然而然的按照 hc 来输入,下次需要输入 lao 的时候,还是需要想一下 ao 在字母 c,需要输入 lc。

这么看的话,和前面说的码表输入法有啥区别呢?所以我感觉双拼也是个码表输入法。既然是码表输入法,双拼的区分度那么差,何必折腾他呢,不如去用二笔呢。而且我用的时候最郁闷的是,二笔训练出来的键位记忆居然总会出来捣乱,这其实也更加说明这个就是码表输入法。。。

而且还有就是,普通拼音输入法里面,尤其是手机上面,容易按错键,比如 hao 输入成了 hso 的时候,手机上面会纠错,把「好」这个选项放在第一个。但是如果是双拼就没那么好搞了,如果也增加纠错,那会增加很多重码,体验不好。

另外还有个问题就是对于 sh, s, en, eng 这些不太清楚的人来讲,更加是个挑战,当然拼音可以用模糊音,按说双拼也可以想办法自定义模糊音。但是可能就失去了双拼的一些优势。

进化论

Published on:
Tags: tech

回忆一些没用的

我是 1998 年上的大学。小的时候就对各种电子产品比较感兴趣,当然其实没有什么机会的,当时主要就是游戏机,但是我家里是没有的。高中的时候曾经借同学的回家玩过,和我弟弟一起玩的挺嗨,但是对于增长知识应该是没啥用的。

高考完毕之后,其实最想要报的还是计算机系,记得暑假的时候在电视里面看电脑相关的讲座,讲的最多的好像就是五笔,那会 windows 用户也不多,都是用的 dos。ucdos 是最常用的。那会电脑最大的用途感觉就是打字输入,然后打印。

当时没有报计算机,因为闭塞的农村人认为计算机会和财经一样(当时财经类专业曾经火过一些时间,但是介于毕业的人都没啥靠谱工作,所以就认为一般了),过段时间就不行了,所以没有报这块,报的是应用物理专业(当然了,这个专业更屎)。

那个假期去我舅舅的办公室去玩玩电脑。我舅舅是微机专业毕业的,毕业后回我们那边做类似一个打字的工作(其实我也不知道具体做什么….)。我当时去那边就是熟悉各种 dos 命令,学习一下 foxbase。

当时我记得有一本 foxbase 的书,看里面东西看不懂,没有现在的论坛和方便的网络,没有人可以交流。我记得印象最深的是有一道题需要算 1+2+3+…+100 等于多少,不懂编程完全不知道怎么做这个事情,但是看了答案看不懂,因为不懂 i=i+1 是什么意思,那会不明白为什么 i 还可以在右边。现在看来,生在那个年代那个地方真的很悲哀。

进入大学之后,选修了一门 word 之类的课,开始接触 windows。然后宿舍同学熟悉之后,就计划一起买了一台电脑,每个人 1200,我们总共 6 个人,7200 一台电脑,包括音箱电脑桌。当时要上网只能是拨号,56k 猫,开始是用不起的,大概到了大2,3 才开始拨号。然后 6 个人轮流用。那是我们班的地一台电脑,当时辅导员要求大家写保证书,保证不玩游戏才允许买。当然,你们懂得,保证书有个卵用,所以后来某天被发现玩游戏之后,给我们把电脑格式化了。但是之后大家还是会玩。

上了大学之后,就有网络中心,第一次去网络中心的时候,有点懵逼,和 xh 两个人对着电脑不知道该干啥。旁边的人都在玩 mud,当时不懂,就是看着一个绿窗口觉得很神奇。当然后来我们玩 mud 到昏天黑地就不多说了。玩 mud 玩的多了,慢慢了解到了 mud 的机制,有时候自己搭一个开始研究里面的编程,不过还比较粗浅。当时学的也就是 fortrun,c 语言这些。

那会的搜索引擎是目录式的,就和黄页一样,除了去看一些门户,就是翻这些东西,希望发现一些有意思的东西。那会学习也基本是靠买书和看自带的文档(不如 msdn),和通过网络靠一些小论坛里面的一些交流。那会写的比较多的是 vc vb 这些,php 之类学的人不多,java 我记得好像也不多。我的毕业论文是一个 vb 的程序,现在看写的比较烂,也就是能用。

开始讲网站开发

前面废话太多,又不太舍得删掉,就分一下块吧,下面讲讲网站开发技术的进化。

dreamwaver & frontpage 时代

那会做网页比较多的应该是 asp,用 frontpage 写,用 iis 发布,都是图形界面的,linux 没有什么人会用。linux 下面那会各种问题,驱动输入法这些都得花费很大的精力去解决。我装的第一个 linux 应该是 xterm linux,11 张光盘,因为他把一些软件也刻录到光盘了。第一次装 linux 就把宿舍的电脑搞挂了,没选对直接重新分区了。不过也就当年折腾这些弄明白了分区表 mbr 这些东西。

那会还攒了一些书,有一本就是讲怎么用 dreamwaver 的,当时觉得这个东西真牛逼,抛弃了 frontpage。我还记得我用 frontpage 做的第一个自我感觉良好的网页给别人看的时候,人家的那个表情,基本就是想吐的那种。我现在想,典型的那些花背景底色,大字体,图片按钮,来回滚动的一些内容等等,都是很烂的。

基于对 dreamwaver 的熟悉,当时还去联想实习了一段时间,给他们解决了一些问题。

那会做网页一般也就是收个表单,存到数据库什么的,不会有太复杂的东西。做个论坛是最常见的了。那个年代 javascript 是忌讳的东西,一般也就是用来滚动个页面标题什么的,没人拿他做特牛逼的东西。

毕业之后,就进了出版社。那个时代桌面程序很流行,因为大部分电脑都不能上网的,我到了出版社凭着自己的兴趣,用 vb 做了一个库存管理的软件,其实就是入库多少,出库多少登记一下,简单的很。

后来也是自己的兴趣,找了一台没人用的电脑,windows 上面跑起了 java web 服务,那会还流行搞一些 java applet 跑。出版社最早的网站就是这么跑起来的。

在后来装了一个 linux,开始在上面跑 qmail,跑 apache,开始熟悉 linux。同时也有了 php 的网站,不是我开发的,跑在我那个 linux 机器上面。

ajax & mvc

后来大概有几年没有接触这些了,大概 08 年左右接触到了 ajax,javascript 算是就那几年走上神坛。当时老何演示了一个跑在本地浏览器里面的留言本程序,服务器端不用提供任何 html 相关的服务,只需要保存数据返回数据就好,逻辑都跑在本地浏览器里面。

不过那个时候我写的比较多的还是那种古老的表单方式,自己没去仔细了解这种新技术。后来大概 09 年左右有机会开始写 javascript 的时候了解了一些机制,感觉这种方式很有意思,渲染逻辑跑在浏览器,这样节省了一些服务器端的压力,并不是什么操作都需要提交到服务器让服务器去判断下一步怎么办。那会用到了 jquery,感觉真的好方便,并且他还提供一些 css 的效果,让不太熟悉的人也可以很方便的搞起来。而服务器端那会用 php 比较多。

php 当时也接触了一些框架,名字是不记得的。我这种野路子程序员,根本不明白人家的一些设计思路,代码和模板分离,mvc 这些都不懂,不过代码看多了也能明白一些。

我记得 09 年写这些的时候,一个遗留的 php 网站,需要增加一点功能,发现需要我一个人在 n 个文件里面修改,楞要把一个功能分散个 n 个文件让我很不理解,不是蛋疼么。当然后来明白这么做是为了分工合作为了灵活扩展,那么如果就一个人写的时候,我们是不是也需要这么做呢?

emberjs & angular & react & django & spring

后来大概 10 年左右的时候,我写代码还是用 jquery 的方式来做,因为当时觉得很好用。再后来接触了一些 emberjs angular 的一些知识。学习到了 emberjs 里面的命名惯例,比如一个路由叫 posts 那么就有对应的 PostsController,不用你显式的去让他们产生关系。学习 angular 学到了双向绑定的概念,你在定义了一个模型之后,在模板里面用到变量的地方会自动跟着这个模型的数据变化而变化,这就比用 jquery 的时候需要你自己去替换 dom 里面的内容方便多了。然后到了现在的 react 又提出了 virtual dom 的概念,让你不需要关心 dom 结构,你只需要操作你的虚拟 view 就好了。

当然前端其实还有好多的进步,比如 coffee script 来解决 javascript 这个语言本身的一些问题,哪里不严谨,一些最佳实践什么的就不用你操心了,只需要写 coffee script 就好了,编译成 javascript 之后,会自动处理好。

还有比如 css 不能 include,import,很多方案来解决这个问题。

后端这块,最近接触了 django,spring 这些。程序员要分 2 类的话,那就是 java 的和非 java 的,要分三类的话,就是 java ,javascript 和其他,呵呵。看过之后感觉 spring 真是不错的东西。难怪 java 程序员不去了解其他的,入了 java 坑就不用搞其他的了,库类很方便。并且类似 spring 这种东西,好多年前就有了,可以极大的方便 web 开发(不止 web 开发可以用)。如果能很好的驾驭 java,驾驭 tomcat jvm 这些东西,那么使用 java 其实是很不错的方案。通过 java 的 oo 特性,比如继承,重载 interface abstract 这些,可以很方便的定义好一些规范,也可以很好的把大家的工作划分开,架构,定义模型定义接口的人大家协同工作。

以前文件路径就是网页路径,现在有了 route 的概念(这个概念在 angular, emberjs 里面也有),做了 route mapping 之后,可以很方便的把不同的 route 映射到相同的方法上面,可以很方便复用代码逻辑。

总结下

上面讲了很多,整个就是个进化史。以前弄个网站出来需要花不少时间,还很难看。现在基于 bootstrap 还有这些开发框架,做一个出来很快外观还好看。这就是进步。

计算机技术的颠覆是很快的,如果打算一直从事这块工作,建议还是得保持一颗持续学习的心态,也得扩展自己学习的广度,这样可以吸收到各种技术的长处。

现在学习的手段也多了很多,我看视频直播网站都有开始讲课的了(不一定靠谱),还有各种学习视频,更别说各种可参考的学习文档了。实在是太方便了,只要愿意花时间,进步速度绝对很快。

LLD in zabbix

Published on:

如果需要监控的内容比较多的时候,手动管理报警信息就已经不使用了,加一批机器就需要忙活一阵子。也不能体现我们充满智慧的大脑的作用。

zabbix 支持 LLD(low level discovery) 方式来自动产生监控项目,包括 item, trigger 这些都可以自动添加。大概讲解一下可以利用这个东西做什么事情。

zabbix 收集数据的方式

zabbix 有很多收集数据的方法,这里重点讲 2 个,一个是 zabbix agent,一个是 zabbix traper。这两个方式可以和 nagios 里面的 active 和 passive 方式做类比。traaper 方式对应的就是 passive,就是 client 主动发送数据给 server。

对于 zabbix agent 方式,我们可以自己定义一些 userParameter 来添加自定义监控,这些网上很多例子。如果使用 trapper 方式,那么原则上面可以不用做任何自定义,就可以通过 zabbix-sender 或者自己模拟 sender 的协议,通过比如 python,java 等发送自己的监控信息。通过 python 发送的例子网上也有。

LLD

参考这里,LLD 主要的思路就是给服务器端发送一个 json 数据格式。例如下面这个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"data":[
{ "{#FSNAME}":"/", "{#FSTYPE}":"rootfs" },
{ "{#FSNAME}":"/sys", "{#FSTYPE}":"sysfs" },
{ "{#FSNAME}":"/proc", "{#FSTYPE}":"proc" },
{ "{#FSNAME}":"/dev", "{#FSTYPE}":"devtmpfs" },
{ "{#FSNAME}":"/dev/pts", "{#FSTYPE}":"devpts" },
{ "{#FSNAME}":"/lib/init/rw", "{#FSTYPE}":"tmpfs" },
{ "{#FSNAME}":"/dev/shm", "{#FSTYPE}":"tmpfs" },
{ "{#FSNAME}":"/home", "{#FSTYPE}":"ext3" },
{ "{#FSNAME}":"/tmp", "{#FSTYPE}":"ext3" },
{ "{#FSNAME}":"/usr", "{#FSTYPE}":"ext3" },
{ "{#FSNAME}":"/var", "{#FSTYPE}":"ext3" },
{ "{#FSNAME}":"/sys/fs/fuse/connections", "{#FSTYPE}":"fusectl" }
]
}

这个数据里面,data 是必须的,里面包含里面发现的可监控数据,这可以是任何数据。例子里面是发现了可以用来监控的磁盘分区。data 是个数组,每个可监控项是一个数组元素。还有类似下面这样的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"data": [
{
"{#HOST}": "Japan 1",
"{#COUNT}": "5"
},
{
"{#HOST}": "Japan 2",
"{#COUNT}": "12"
},
{
"{#HOST}": "Latvia",
"{#COUNT}": "3"
}
]
}

这个是发现了一些可监控的 host。

理解没有?发现是发现可监控的服务,并不是发现监控项。比如我们可以通过发现这机器上面有没有启动 ssh,发现有启动之后,我们就可以通过服务器端配置 discovery 自动添加一些监控规则。

1
2
3
4
5
6
{
"data": [
{ "{#SSH_PORT}": "22" },
{ "{#SSH_PORT}": "8022" }
]
}

比如上面这个,我们发现了 2 个 ssh 进程,一个是 22 端口,一个是 8022 端口。

所以重点是发现有什么可监控的服务,并不是发现监控项。

BUT,其实并不是不能发现监控项,也是可以的。不过是,这种被发现的监控项,除非对应的 trigger 也都是一样的,否则你会发现无法分别添加不同的 trigger 规则。

发现监控项

有了发现服务之后,就肯定需要对相应的服务的一些监控项做监控了。这个给 discovery 规则配置 item prototype 就可以了,不过这个里面有点坑需要填,后面会说,这里先不讲。

那么比如对于 ssh 服务,可以监控

  • 当前链接人数,conn.cnt
  • 配置文件的 md5,conf.md5(配合 zabbix trigger 可以用来监控文件是不是被修改了)

那监控数据就如下面

1
2
3
4
5
6
{
"22.conn.cnt": 4,
"22.conf.md5": "18492113fb263c9d0a33c9fea403eea1",
"8022.conn.cnt": 9,
"8022.conf.md5": "6cab272daa07202ccb57c4064c0dcfb8"
}

上面就是一个 discovery 项目,filter 是 {#SSH_PORT},和 2 个 item prototype,分别是 {#SSH_PORT}.cnn.cnt 和 {#SSH_PORT}.conf.md5。

复杂一点的 LLD

一个 LLD 还可以发现多个服务。比如下面这种。

1
2
3
4
5
6
7
8
{
"data": [
{ "{#SSH_PORT}": "22" },
{ "{#SSH_PORT}": "8022" },
{ "{#PG_PORT}": 5432 },
{ "{#PG_PORT}": 6432 }
]
}

这个除了我们前面讲的 ssh 服务,还发现了两个 pg 的服务。在服务器端,只需要添加两个 discovery 规则就可以了,分别使用 {#SSH_PORT} 和 {#PG_PORT} 这两个宏来过滤数据。

1
2
3
4
5
6
7
8
9
10
{
"data": [
{ "{#SSH_PORT}": "22" },
{ "{#SSH_PORT}": "8022" },
{ "{#PG_PORT}": 5432 },
{ "{#PG_PORT}": 6432 }
{ "{#MASTER_DB_PORT}": 5432, "{#SLAVE_DB}": "host1" },
{ "{#MASTER_DB_PORT}": 5432, "{#SLAVE_DB}": "host2" },
]
}

上面这个,除了有 2 个 db 之外,还有一个 db 是个 master,能看到他对应的 slave 有哪些。要注意,我们在新增加的这个发现项里面,不能再使用 {#PG_PORT} 这个宏了,因为如果使用了这个宏,就会和第3,4个项目无法区分了。所以我们改了一下名字。

到此为止,只是我们的构思,想要告诉 zabbix 我们想要监控什么。真正使用还需要走一些路。

如何发送数据

不管是 discovery 数据,还是 item 的监控数据,都可以通过 agent 和 trapper 方式发送。

对于 discovery 数据,使用 agent 发送就是上面讲的格式。

1
2
3
4
5
{
"data": [
{ "{#PG.OTHER}": "0" },
]
}

如果使用 trapper 方式发送,格式如下

1
2
3
4
5
6
7
8
9
10
{
"data": [
{
"host": "HOST1",
"value": "{\"data\": [{\"{#PG.OTHER}\": \"0\"}]}",
"key": "pg.discover"
}
],
"request": "sender data"
}

上面这个数据里面,data 和 request 是 zabbix sender 的固定格式。data 里面,包含了 host, value, key 三个字段。host 是被监控的 host,和将来服务器端的 host 对应。value 是发送的监控内容,可以看到也就是我们使用 agent 发送的内容。key 就是对应的监控项,这个监控项也就是 agent 方式发送对应的那个 userParameter。

使用 trapper 方式发送里面,是可以伪造被监控的 host 的,所以 trapper 方式并不要求一定要在被监控机器上面执行。

对于 item 监控数据,使用 agent 发送是下面这种格式。

1
2
3
4
{
"key1": 2,
"key2": "ok"
}

使用 trapper 方式发送,是下面的这种格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"data": [
{
"host": "HOST1",
"value": 1,
"key": "key1"
},
{
"host": "HOST1",
"value": "ok",
"key": "key2"
}
],
"request": "sender data"
}

zabbix 里面的限制

上面的例子很完美,但实际上 zabbix 是有一些限制的。比如 item 定义。

假如对于发现的 pg 服务,有一个监控项是连接数,比如 {#PG_PORT}.conn.cnt,此时你会发现在 zabbix 新建 item 的 Key 那个设置里面,这么写无法提交。需要使用假装类似 userParameter 的方式来写,比如 pg.[{#PG.PORT}.conn.cnt],假装那个 pg. 是个 userParameter 命令,[{#PG.PORT}.conn.cnt] 里面的内容是他的参数。当然,这个 pg. 可以基本可以是任何字符串,比如 abc,你自己觉得有意义就好了。

那么这个时候对于发现那块,我们基本不用动,需要动的是被发送的服务的监控项的命名上面。

比如以那个 ssh 的监控为例,原来发送的数据如下

1
2
3
4
5
6
{
"22.conn.cnt": 4,
"22.conf.md5": "18492113fb263c9d0a33c9fea403eea1",
"8022.conn.cnt": 9,
"8022.conf.md5": "6cab272daa07202ccb57c4064c0dcfb8"
}

我们只需要修改成这样

1
2
3
4
5
6
{
"ssh[22.conn.cnt]": 4,
"ssh[22.conf.md5]": "18492113fb263c9d0a33c9fea403eea1",
"ssh[8022.conn.cnt]": 9,
"ssh[8022.conf.md5]": "6cab272daa07202ccb57c4064c0dcfb8"
}

对应的 2 个 item prototype,key 分别修改为 ssh[{#SSH_PORT}.cnn.cnt] 和 ssh[{#SSH_PORT}.conf.md5]。那个 ssh 可以随意起。并且其实并不一定就得是这种模式,比如叫做 ssh.conf.md5[{#SSH_PORT}] 应该也可以,当然需要你发送的数据也做对应修改。

如何发送监控数据

咦?好像说过一次了?这次和上面不一样,呵呵。

设计好并写好监控之后,选择什么方式发送监控数据呢。我选择的是 discovery 数据通过 agent 方式获取,也就是在各服务器上面定义相同的一个 key,然后执行这个 key 的时候发送发现的服务信息。

而对于监控项数据则通过 trapper 方式发送。通过 trapper 方式发送,需要定时执行,可以通过 crontab 发送。我选择的是建立了一个 agent 类型的 item,执行这个 item 的时候发送监控数据。这样一方面可以针对这个发送动作建立一个监控,另外一方面调整很方便,zabbix 界面修改就可以。并且我把这个 item 建立到了模板上面,只要修改应用模板就可以了。

监控数据也可以用 agent 方式发送,如果用 agent 方式发送,对于上面的 ssh 服务,就需要真的建立那个 ssh 的 userParameter 了,然后接受比如 22.conf.md5 这样的参数,去返回对应的监控数据。我没有用这种方式,是因为这样做等于有多少个 item 就需要在监控周期内执行多少次那个命令,给服务器增加负担(虽然没多少)。而使用 trapper 方式的话,就可以一次把所有的监控数据都发过去了,命令只需要执行一次。

如何应对不同的部分

到此为止,应该可以很完美的发现服务,并且监控了。但是会发现其实并不是所有服务器的服务都是一样的,比如对于 pgsql,slow query 的界定对于不同的业务可能不一样。而因为 trigger 也是自动发现添加的,这样也有可能需要不同的机器上面的服务有不同的阈值,怎么解决呢?

先说监控项的阈值。因为我的监控数据其实是通过建立一个 agent 类型的 item 定期发送 trapper 数据来实现的,所以只需要在调用那个 item 的时候传送不同的阈值就可以了。实际上面我的 itme key 定义是这样的 pg.sendtrap[{$PG.DISCOVER.SETTINGS}] 。那个 pg.sendtrap 是对应到一个 userParameter 的 UserParameter=pg.sendtrap[*],/etc/zabbix/bin/zabbix_pg.py --check --sendtrap --settings $1,在 zabbix_pg.py 里面,会处理 settings 参数。如果有阈值,那就定义好 {$PG.DISCOVER.SETTINGS} 这个宏就可以了。template 上面可以定义默认的阈值,当然默认阈值在程序里面定义也可以。然后不同 host 可以定义 host 的阈值,会覆盖模板的配置。

其实 trigger 的阈值和这个思路类似,也是 template 里面定义一个宏,trigger 里面使用这个宏就可以了。如果 host 有不同的阈值,那就定义一个 host 的宏覆盖他就可以了。

目前的情况

配合 zabbix 的 auto registration 这个 action,可以做到新机器只需要执行一个 saltstack state,安装好我们的 zabbix agent,就可以自动注册 host,自动添加监控报警。

相当完美。

能不能成功取决于什么

Published on:
Tags:

随着年龄的增长,自己对一些事情的认识在改变,一直想总结一个给年轻同学的帖子,但是总是不能总结太好怎么讲,大概从想讲到现在,已经几个月了,我感觉不讲的话可能就讲不出来了,所以乱谈一下。

从全栈讲起

什么是全栈?我感觉肯定不是普通人,我觉得全栈至少得是绝顶聪明的人才可以做到,对于他们来讲,有很扎实的 CS 功底,并且知识面非常广泛,还有很多产出,并且这些产出是各个方面的。

某种观点

上面是李笑来老师对于全栈的看法,这里 有知乎用户对这个的讨论。

我只是关注到了他那句话里面的「不太笨」,如果他的意思是很聪明的意思,那观点就和我一致了,呵呵。

不得不承认,智商和你能掌握的内容是有关系的,智商不够再怎么努力也很难达到某种顶峰。当然这并不是说,智商不够的就没戏了,换句话说,如果智商不够还不努力,你还是就想想老婆孩子热炕头就算了。

学习别人

学习别人的成功经验,似乎是一种很好的办法,至少人家那条路是走通了。

这几年流行健身,是吧。看着别人一个一个健身房也好,路边跑步也好,还有奥森跑步的,是不是看着眼红但是又觉得自己周边不具备环境?健身房贵,路边有觉得没有好环境,奥森还有点远,所以我得找一个满足条件的才能去进行这个事情。

还有比如看到有人拿 kindle 看书,是不是觉得我要是有个 kindle 带着方便,肯定可以看好多书,比如一直想学习的 iOS 开发,还有 Java 编程思想,哎呀呀,编程能力大幅增长啊。所以一定要买个 kindle。

等等类似的事情吧,别的不多讲了。就是我想要干什么事情,但是呢最好满足个什么条件,会让我干的更好更有动力。

最后通常的结果呢?步顶多跑几次就会觉得没意思了,kindle 在家里吃灰,然后开始有其他的想法,比如看着人家的 iphone 不错唉,我要是有个,看个 pdf 什么的,比 kindle 方便啊,手机可是一直带着的,所以。。。。

听别人讲

欧洲人在放难民进来的时候,想的可是我们可怜你们让你们进来,你们应该很满足,不要闹事老实呆着。所以实际上呢?

父母亲戚常见的「我都是为了你好」这种说法,大家估计都听腻了吧。有用么?

微信朋友圈网上各种鸡汤文,比尔盖兹为什么成功,雷军马云的奋斗,这些文章看的时候让人激动人心,看完了貌似就忘记了,是不是?。。

关键在哪里?

我感觉关键就是一个字「懒」。

懒

2004 年左右在 irc 玩的时候,就有一个网站 let me google that for you。这个网站就是鄙视那些连 google 都懒得用的,稍微有点问题就问别人。知识都是别人的,把别人当 google 用。

很多人都有类似习惯。我们学习的时候,别人都是引进大门,如果自己不能养成自己知识持续更新的习惯,等到自己连年轻人都跟不上的时候,就很悲哀了。

这个都无关智商,所谓活到老学到老,别人都给你总结好了,懒字一上来,就混吃等死吧。

想要客服懒字,得自己给自己洗脑,让自己能坚持的下去。老罗的奋斗 里面,老罗讲自己决定要去新东方当老师之前,学习英语的时候,隔段时间就会学不下去,学不下去的时候,看看成功学的书,给自己打打鸡血,就又活蹦乱跳了。

我大概总结几项提升的方向,遇事情想想,应该有好处

  • 主动思考解决问题的最佳思路
  • 主动发现问题,改进承担
  • 主动推进事情进展
  • 不要限定自己的范围,不停挑战难点
  • 积极参与到别人的有激情的项目里面
  • 对技术保持强烈的好奇心

如何不花钱建立一个支持 https 的 blog

Published on:
Tags: blog

早年的时候要搞 blog 还得弄一个空间,现在,免费的东西越来越多了,感觉共产主义的实现还要靠资本家啊,不过羊毛出在羊身上。。。

要想弄一个免费的 blog,首先你的 blog 内容最好是纯静态网页,如果是类似 php 什么的,那就难找了。使用 jeklly, hexo 这些都可以把 markdown 文件渲染成 html。

然后注册一个 github 或者 gitcafe 等等支持 pages 服务的空间,搞定之后就能得到一个类似于 http://wd.github.io 这样的地址。

然后你注册一个域名(发现标题没起好,这个还是要收费的。。),然后注册 cloudflare,把你的域名的 dns 使用 cloudflare 的,然后在 cloudflare 配置一个 cname 到 wd.github.io。然后建立一个 page rule,强制你的域名使用 ssl。

ok 拉,整个过程就是域名花钱了。可以访问下 http://wdicc.com 看看效果,会自动跳转到 https://wdicc.com :D

Custom Netgear r6300v2 wireless router

Published on:

科学上网。买了群晖之后,一直通过群晖上面跑一个 haproxy 来做转发。不过心里总觉得有点不爽,毕竟一方面多转发了一次,另外群晖在不使用的时候,还会休眠,又或多或少担心影响休眠(经过测试应该是不影响的,但是..)。所以买了 r6300v2 之后,就琢磨通过路由器做这个事情。

路由器上面搞就有两个选择,一是从 iptables 入手,直接转发出去,另外一个是从软件层面做。

开始搞了几天的 iptables,发现原有系统 iptables 条目还是挺多的,加上路由器翻墙的功能也需要加一些条目,导致尝试了好几天之后总算能够转发过去链接了,但是数据包过不去,为了调试就开始打算在路由器安装 tcpdump。然后找到了 https://github.com/Entware/entware ,配置好之后可以使用 opkg 来安装包。包列表可以参考这里 http://pkg.entware.net/binaries/armv7/Packages.html ,这个路由器是 armv7 版本的 cpu。

安装 opkg 之前先得了解下,梅林固件分两部分存储,一部分是系统区,一部分是自定义区。系统区应该是你刷的固件所在的地方,是不能修改的,自定义区是可以存放一些自己定义的脚本的。每次系统启动的时候,你的一些自定义的东西都是存在自定义区加载的。自定义区就是 /jffs 分区。想要使用,得在 系统管理 -> 系统设置 里面,打开 JFFS 的配置,允许执行上面的脚本。

因为系统自带的 /jffs 分区只有 60M 左右,而我们装包的时候很容易就超过这个限制了,我现在已经用了 8xM 空间。所以最好还是用一个 u 盘来做这个事情。每次想要自动加载 u 盘,启动 u 盘里面的程序的话,还需要一些自定义的脚本来做这个事情。

先把 opkg 配置好,需要先准备好 /opt 目录。

1
2
mkdir -p /tmp/opt
mount -t ext4 -o rw,noatime /dev/sda1 /opt

上面的 /dev/sda1 是 u 盘,ext4 是文件系统类型,按照自己的修改一下。一般 u 盘插上去就会自动挂载,df 看一下就知道是哪个名字了。系统配置里面有个 dlna 的配置记得关掉,否则他会读 u 盘导致你不能 umount 之类,或者 kill 掉一个叫做 minidlna 的进程也可以。

然后参考 https://github.com/Entware/entware 操作就可以了,可以看到他会在 /opt 给你安装一陀东西。因为这个是 u 盘,所以东西重启也不会丢失。

然后参考梅林的 wiki,它允许用户在 /jffs/scripts 自定义一些启动脚本,来支持我们自动挂载和启动 u 盘上面的程序。

post-mount 内容如下,前面几个注释的是调试用的。最后一个 if 里面内容是执行一些 opkg 安装的程序的启动脚本,这个后面说。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
#echo $(date) > /tmp/000service-start
#echo "$1" >> /tmp/000service-start
#ls /dev/sda* >> /tmp/000service-start
if [ -b /dev/sda1 ];then
mkdir -p /tmp/opt
mount -t ext4 -o rw,noatime /dev/sda1 /opt
fi
if [ -x /opt/bin/opkg ];then
/opt/etc/init.d/rc.unslung start
fi

要记得 sudo chmod +x post-mount,然后可以重启路由器看看是不是启动之后就能看到 /opt 有了你上次安装的程序了。

上面一阶段搞定之后,就可以装一些软件了,比如我装了 vim, tcpdump,bind-dig, haproxy。opkg 的命令使用可以参考这里 https://wiki.openwrt.org/doc/techref/opkg

接着上面的话题,本来打算装好 tcpdump 来调试的,然后发现可以比较方便的启动 haproxy 之后,就打算用 haproxy 弄了,路由表太多,分析比较麻烦,还是走简单的吧。。

/opt/etc/haproxy.cfg 如下,把 IP 和 PORT 改成你自己的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
global
ulimit-n 331071
defaults
log global
mode tcp
option dontlognull
timeout connect 1000
timeout client 150000
timeout server 150000
frontend ss-in
bind *:本机PORT
default_backend ss-out
backend ss-out
server server1 IP:远端PORT maxconn 20480

/opt/etc/init.d/S001haproxy.sh 如下,sudo chmod +x /etc/init.d/S001haproxy.sh

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
#!/bin/sh
haproxy_bin=/opt/sbin/haproxy
haproxy_cfg=/opt/etc/haproxy.cfg
pid=/opt/var/run/haproxy.pid
action=$1
if [ -z "$action" ];then
printf "Usage: $0 {start|stop|restart}\n" >&2
exit 1
fi
case "$action" in
start)
$haproxy_bin -f $haproxy_cfg -p $pid -D
;;
stop)
kill $(cat $pid)
;;
restart)
kill $(cat $pid)
$haproxy_bin -f $haproxy_cfg -p $pid -D
;;
esac

因为前面在 post-mount 最后一个 if 里面的语句,这样启动路由器就会自动启动 haproxy 了。

想使用这个端口转发,还需要在路由器配置界面里面增加一个到路由器 ip 的映射,然后还需要一个 /jffs/scripts/firewall-start 如下

1
2
3
#!/bin/sh
iptables -I INPUT -i ppp0 -p tcp --destination-port PORT -j ACCEPT

我使用的过程中还发现一个问题,pkg.entware.net 貌似被墙了。。虽然配置了翻墙但是不太明白为什么路由器上面时好时坏,而我局域网内的 mac 访问总是 ok 的,很奇怪。路由器上面不能访问有个办法是通过 mac 代理一下。

mac 上面启动一个 ngx,配置如下,使用 nginx -p ./ -c nginx.conf 启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
events {
worker_connections 1024;
}
http {
server {
listen 0.0.0.0:8000;
location / {
proxy_pass http://pkg.entware.net;
}
}
}

然后修改路由器上面 /opt/etc/opkg.conf src/gz packages http://MAC_IP:8000/binaries/armv7,然后就可以了。

写完自己看发现这不是一份操作指南,只能算是一些提示,如果有人照着做能不能成功可能还是得看自己。。。

lua metatable

Published on:
Tags: lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
t = setmetatable({ bar = 4, foo = 7 }, { __index = { foo = 3 } })
print(t.foo) -- 7
print(t.bar) -- 4
t = setmetatable({ }, { __index = { foo = 3} })
print(t.foo) -- 3
print(t.bar) -- nil
fuc = function (t,k)
if k == 'foo' then
return rawget(t, 'bar')
else
return 0
end
end
t = setmetatable({ }, { __index = fuc })
print(t.foo) -- 3
print(t.bar) -- nil
print(t.ff)

Across the Great Wall, we can reach every corner in the world

Published on:
Tags: gfw

科学上网估计是每个搞 IT 的人必须要掌握的知识了。简单讲讲我目前使用的一些方法。

国外服务

首先肯定需要先有个国外的资源,比如买专业的 vpn ss 服务等。数据经过第三方都不一定那么可靠,我的主力邮箱在 gmail,可不想被攻破,所以我选择了自己购买和搭建服务。

我买的是 linode 的服务,最便宜的是 10$ 一个月。也可以买一些美国的 kvm 或者 zen 的虚拟机,有比较便宜的一个月可能才不到 1$,当然这种便宜的一般很快就会卖没,得看运气。我的 linode 是和 3 个基友一起合租的,这样大家每个人一年也就 300 来块钱,也就一顿海底捞(我这两年非常喜欢用饭钱来衡量消费,吃饭可是天天都有的,但是有些消费,比如买软件,买服务这些一般都是一年或者几年才一次,比起吃饭真的便宜多了),一般都能承担的吧。

早期我买过一些 ssh 服务,速度不稳定,因为很难限制超售。后来还买过云梯,他们提供的节点比较多速度还不错。

有了 vps 搭一个 ssserver 就是很简单的了,就不多说了。服务器上面我还配置了 ocserv 这个支持 cisco 客户端的 vpn 服务。当然并不是所有 vps 都支持,有的 vps 没有 tun 设备,跑不起来,买的时候要注意。

ssh 方式

使用 ssh 方式的时候,最早是直接 ssh 链接弄一个 socks 端口给本地,然后本地使用 pac 配合。

后来有段时间被断的不行,就试了 stunnel,可以把 ssh 转为 https 服务,这样就可以跑在 443 端口了,和其他 https 服务比较难区分。可以起点作用。

这个方式没法支持手机。

使用 ngx

有段时间还使用 hosts 文件加 ngx 反向代理还翻墙。ngx 上面配置 google.com 和 twitter.com 的反向代理,然后手机或者电脑上面配置 hosts 指向 ngx。就可以实现翻墙了。不过因为都是 https 的网站,所以服务器上面得配置 https 的服务,证书得弄到电脑或者手机上面信任才行。

这个手机想要支持的话,ios 比较麻烦,必须得越狱。

vpn 方式

早期用 vpn 方式的时候,pptp 可以搭配 chnrouts 来实现国外和国内走不同的路由。用起来也不错,不过问题是全局的有时候切换也不方便,并且有时候还需要连公司的 vpn 路由一乱就麻烦了。

pc 上面选择比较多。手机上面,试过 anyconnect,缺点就是全局翻墙(我试过让 server 只 push fb twitter 的路由,但是维护麻烦,效果也不好)。anyconnect 比较赞的地方是他的链接 cookie 可以设置比较长的有效期,这样网络切换什么的临时断开之后自动重连也不需要输入密码。哦,当然,我的 anyconnect 和后面提到的 openvpn 都是通过自己签的证书来认证的,也不需要输入密码。

后来用过 openvpn,openvpn 是基友维护的。他的思路很赞。

他买了一台 server 放家里,家里是联通 adsl 24h 联机,然后 server 上面跑一个 openvpn 的服务器端给手机连接用,服务器上面再通过 vpn 和 vps 的 vpn 链接,同时这机器配置只有国外路由才走 vps,国内都是直接链接。大概链路就是 手机 -> 家里的 server -> vps。如果是国内的网站,就直接通过家里的 server 访问了,比国外的 vps 访问速度快。

这个方法还有好处是有时候一些公开的场合链接一些 wifi 的时候,很不安全,而通过 vpn 之后,数据都是加密的,就安全多了。我在 surge 之前,在 hosts 不能用之后,基本都是用这个和 anyconnect。

使用 ss

开始使用 ss 的时候,是使用 goagentx (貌似已经比较难找到下载了)的,这个工具异常好用,支持切换全局还是使用 pac 非常方便。pac 推荐使用 genpac 来维护 pac,放到 dropbox 里面就可以四处用了。

我有相当长一段时间都是这么翻墙的。直到后面 ios 9 放开网络权限之后,出来了 surge。surge 现在卖的太贵了,不建议购买,最近好像看到有一些新的软件也在出现,可以考虑。

surge 出来之后,ios 基本就是用这个了。

surge 也有 mac 版本。如果没有,使用 ss mac 版本也可以,搭配 pac 可以做到透明。

应对不稳定的网络情况

家里是联通 adsl,链接我的 linode 一直都比较稳定,速度不错也没有丢包。公司访问 linode 有时候丢包比较严重,不过也将就用了。去年去长沙出差,那边完全访问不能把我搞的很痛苦。回来就开始琢磨怎么搞。

上面基友的思路提醒了我,就是自己家里一台 server 建长链接,然后在外面翻墙先连家里。但是家里的路由器完全不能定制,后来发现我的群晖的 nas 可以装 haproxy,就搞定这个事情了。在路由器上面映射一个端口给群晖,群晖上面跑 haproxy 转发到 linode。给路由器弄了个 ddns,在外面翻墙都连接这个 dns。

群晖上面跑 haproxy 还不影响硬盘休眠,还挺不错。这样就彻底解决了我翻墙的问题了。

但是遇到家里停电断网就虾米了。。

家里的全局翻墙方案

前段时间换了 Netgear R6300v2,才发现我之前错过了好多好玩的东西。刷了个国内论坛定制的梅林 rom,自带了 ss 客户端,并且配置的非常完美,支持多种翻墙策略,具体就不细说了。就说现在的效果吧。

直接映射了端口到 linode 的 ss,并且也支持 ddns(我用的 3322 的),这样 nas 上面的 haproxy 就彻底可以不用了。

路由器跑了 ss 客户端,加 redsocks2 和 dns2proxy,实现了国内网站直连,国外根据域名匹配到列表里面的服务器通过 ss 链接。这样家里所有的终端,不需要跑任何服务,就可以无缝翻墙了。我的 ps4,apple tv,ipad 上面的 yotube 都可以访问了。然后还支持黑名单,我把 nas 加进去了,防止使用 bt 下载的时候跑到国外流量。

这样我目前手机和 mac 都是直接通过 surge,国外流量通过 3322 的 dns 先链接到路由器,然后转发到 linode 实现翻墙。

目前唯一的问题

mac 版本的 surge,还不能自己配置网络,这样临时想关掉代理的时候,就比较麻烦,得去网络配置里面关。也不能很简单的配置让全部流量走 proxy,有时候需要测试下什么的,就比较麻烦。所以我现在有时候还会使用 goagentx 辅助一下。

setup proxy for emacs

Published on:
Tags: emacs osx

我在 mac 上面使用 emacs 都是使用 daemon + emacsclient 模式。使用 paradox 包管理(其实就是比 list-package 稍微多了一点功能’),但是因为那些包什么的信息都在国外的网站,还有 github 什么的,导致速度巨慢甚至连不上,关键 emacs 单线程还得卡着别的操作,所以挺讨厌的(其实 paradox 提供了异步更新的方式,不会阻塞现在进程,但是有时候会不知道进度…)。

思路就是使用 proxychains

新建一个 /Library/LaunchAgents/gnu.emacs.daemon.plist 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>gnu.emacs.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/proxychains4</string>
<string>-f</string>
<string>/Users/wd/.proxychains/proxychains.conf</string>
<string>/usr/local/opt/emacs-mac/bin/emacs</string>
<string>--daemon</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>Gnu Emacs Daemon</string>
<key>UserName</key>
<string>wd</string>
</dict>
</plist>

其中 /Users/wd/.proxychains/proxychains.conf 文件的内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
localnet 127.0.0.0/255.0.0.0
localnet 10.0.0.0/255.0.0.0
localnet 172.16.0.0/255.240.0.0
localnet 192.168.0.0/255.255.0.0
quiet_mode
[ProxyList]
#socks5 127.0.0.1 1080
http 127.0.0.1 6152