I'm starting to provide Chinese / English versions of some articles, switch with the Language menu above. 我开始提供部分文章的中文、英文翻译,请使用顶部语言菜单切换。

用 Drone CI 替换掉 Jenkins

Jenkins 是一款免费开源的 CI/CD(持续集成、部署)软件,被广泛应用在各种场景中。Jenkins 的主要优势在于其包罗万象的插件,可以完成各种任务,例如自动执行 SCP、Ansible 等部署,Cppcheck 等代码分析,Telegram、钉钉等状态通知。我之前也将 Jenkins 用于大量任务的自动化执行,例如我的 Dockerfile 镜像的自动更新,你正在浏览的 Hexo 博客的部署,甚至还有原神自动签到。但是 Jenkins 是一款拥有悠久历史的 CI,其前身 Hudson 早在 2005 年就发布了。因此,Jenkins 执行任务时依然是传统的直接执行命令,而非使用 Docker 容器等现代化的方式。这意味着 CI 执行的成功与否很大程度上依赖 Worker 主机的系统环境。例如,前段时间我租了一台配置更高的服务器,由于重新搭建了环境,导致 CI 执行过程中出现一堆莫名其妙的问题,花了一个星期才全部发现解决。此外,Jenkins 用 Java 写成,因此它的内存占用相当恐怖,一个 Jenkins 实例的内存占用可以达到 1GB 以上,导致它完全没法用在低配置的主机上,即使是最简单的任务也不行。而且,Jenkins 强大的插件功能却难以用配置文件的方式调用。有很多插件都没有实现通过 Jenkinsfile 配置参数的功能,...

用 nginx 搭建能查询任意公网 WHOIS 的服务器

在魔改 nginx,建立一个 DN42 的 WHOIS 服务器之后,我把我的 DN42 Looking Glass 接到了这个 WHOIS 服务器。由于我的 Looking Glass 可以作为一个 Telegram 机器人运行,群友们就用它来查询 IP 和域名的 WHOIS 信息。很快,我们发现了一个问题。有相当一部分群友在接触 DN42 之后,又在公网上申请了自己的 ASN 和 IP 段,并且在各个 IX 进行 Peering。因此,群友们常常会查询一些公网的 IP、ASN 和域名,而群里的机器人都不支持这个。如果有一个 WHOIS 服务器可以把公网的查询代理到对应的注册局,就会极大的方便大家的查询。而代理正是 nginx 擅长的事。只要魔改一下 nginx 让它支持向上游发送 “一问一答” 的协议,再加上 OpenResty 的 Lua 脚本支持,就可以很快地搭出一个 WHOIS 代理。修改 nginx 代理逻辑 ¶nginx 向代理上游发送请求时,会调用 ngx_http_proxy_create_request 函数创建请求头部,也就是 GET /url HTTP/1.1 这部分。这里的逻辑大概是这样的:def ngx_http_proxy_create_request(): # 拼接请求的第一行(GET xxx)...

DN42 实验网络介绍及注册教程(2021-05-02 更新)

DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型、去中心化的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 本身不提供 VPN 出口服务,即不提供规避网络审查、流媒体解锁等类似服务。相反,DN42 的目的是模拟一个互联网。它使用了大量在目前互联网骨干上应用的技术(例如 BGP 和递归 DNS),可以很好地模拟一个真实的网络环境。简而言之,DN42:不适合单纯想要保护隐私、规避网络审查的用户不适合在网内消耗大量流量,例如用于解锁流媒体服务的用户适合想要研究网络技术,练习服务器、路由器等网络设备配置,甚至后续在真实互联网建立 AS 的用户适合拥有真实 AS,但担心自己配置错误广播出错误路由、干掉半个互联网,希望有个地方测试的用户。正因为此,使用 DN42 的门槛比较高。就像在真实互联网中一样,你要扮演一个 ISP(互联网服务提供商),注册自己的个人信息,ASN 号码,IPv4 和 IPv6 的地址池,并且使用 BGP 在自己的服务器上广播它们。你还要和其它的用户联系,和他们做 Peering(对接),一步步进入完整的 DN42 网络。DN42 在 172.20.0.0/14 和 fd00::/8 上运行,而这两个 IP 段都是分配给内网使用的。换句话说,你在 DN42 上怎么折腾,都不会影响到服务器其它的互联网连接。...

将 nginx 用作 DN42 WHOIS 服务器

在前一篇文章《用 nginx 建立 Gopher 网站》中我提到,用 nginx 提供 Gopher 服务只是魔改的副产物,我原本的计划是将 nginx 魔改成一个 WHOIS 服务器,用于 DN42。这篇文章将介绍详细过程。WHOIS 协议 ¶首先,我们可以找一个 WHOIS 服务器,来观察它都返回了哪些数据。以向 .pub 域名的 WHOIS 服务器查询我的域名信息为例,执行 telnet whois.nic.pub 43:# 输入下面一行并按回车lantian.pub# WHOIS 服务器返回以下信息Domain Name: lantian.pubRegistry Domain ID: c69e5ccf9d834900be26f88fddc5c9e4-DONUTSRegistrar WHOIS Server: whois.dnspod.cnRegistrar URL: https://www.dnspod.cnUpdated Date: 2021-01-07T14:09:11ZCreation Date: 2016-10-23T08:36:41ZRegistry Expiry Date: 2029-10-23T08:36:41ZRegistrar: DNSPod, Inc.# 略过部分内容# 随后 WHOIS 服务器关闭连接和 Gopher 一模一样,一问一答的协议。...
插图

用 nginx 建立 Gopher 网站

更新日志 ¶2021-03-24:改进文章处理逻辑,增加识别链接和图片的代码。2021-03-21:最初版本。什么是 Gopher ¶Gopher 是互联网发展早期的一种网络协议,由美国明尼苏达大学于 1991 年发明,用途类似于现在的 HTTP。它的基础协议非常简单:客户端连接服务端的 TCP 70 端口,并发送一串 URL,用 CRLF 结尾,例如:some_dir/hello.txt服务端把这个文件的内容全部发过来,然后关闭连接。没了。服务端返回的文件可能是一个 TXT、一张图片、一个二进制文件,也可能是一个有着特殊格式的 Gopher 列表文件,称为 Gophermap。这个文件每一行由以下几部分组成:一个字符,代表这一行的类型,是文字(i)、到一个 TXT 的链接(0)、到另一个 Gophermap 的链接(1)、图片(I),还是二进制文件(9)。当然还有一些现在已经不再使用的协议,可以参阅 RFC1436 Section 3.8。一句话,代表这一行显示的信息,例如 Hello World。一个 TAB。这个链接指向的路径,例如 /some_dir/hello.txt。一个 TAB。这个链接指向的服务器域名或 IP,例如 gopher.lantian.pub。一个 TAB。这个链接指向的服务器端口,一般是 70。CR+LF 换行符结尾。在所有内容结束后,...

制作只有 4KB 大小的永久挂起程序

在我的网络配置中,部分 Docker 容器的服务需要用 Anycast 的方式实现高可用,例如 DNS。在之前的文章中,我的做法是,创建了一个 Busybox 容器运行 tail -f /dev/null 这条命令,永久挂起,不占用 CPU 也永远不会退出,来维持一份网络命名空间给服务程序和 BIRD 共享。用人话说就是:我自己发明了一遍 Kubernetes 的 Pod。我不使用 K8S,因为我的节点都是独立的,不组成集群,因此不使用 K8S 的集群功能,另外它的配置也比较复杂。但是我转念一想,为了网络命名空间建一个 Busybox 容器好像有些大材小用,我还需要手动配置一个 Entrypoint。如果有一个极小的 Docker 镜像,唯一干的事情是等待,那就更好了。方案一:直接用 Musl + 静态编译做一个 ¶最容易想到的方法就是写一个死循环的 C 程序,不断的用 sleep 之类命令等待。Linux 系统中,Glibc、Musl 等 C 语言运行库提供了一个 pause 函数,暂停程序运行直到程序收到了外部信号。所以我写了一个死循环调用 pause:#include <unistd.h>int main() { while(1) pause();}然后把它静态链接到 Musl。不要用 Glibc,原因我在上次制作微型 Docker 镜像时讲了:...

静态编译制作微型 Docker 镜像

Docker 镜像中存储的,可以看作是一个个小型 Linux 系统。它们大都以 Debian、Ubuntu 或是 Alpine 作为基础,再在上面安装额外的软件而成。以完整的 Linux 作为基础的好处就是镜像中会自带常用的命令(ls,cat 等),在镜像构建过程中常常用到。另外它们也带有完善的包管理机制,简单使用 apt-get 就能装好软件,做出一份能用的镜像。但当镜像做出之后,上面这些工具就用不到了,占用了不必要的磁盘空间。另外,完整的操作系统也会带有 SystemD、OpenRC 等管理后台服务的程序,而 Docker 容器常常只用来运行一个程序,后台管理程序就多余了。虽然 Docker 镜像采用分层设计,将基础的系统镜像(例如 Debian)和上层修改(例如安装的 nginx)分开存储并进行去重,从而减少了重复的空间占用,但没有完全解决问题。例如假设我先基于 Debian 构建了一个镜像 A,过了一个月又构建了镜像 B。但在这一个月中,Debian 的基础镜像进行了升级,于是 Docker 就会存储新旧两份镜像,占用了大量的空间。可以看出,空间占用问题大都是基础系统镜像导致的。而且基础镜像也不小,Debian、Ubuntu 的都要 100 MB 以上,Alpine 好些,但也有 5-10 MB,而且它相比 Debian 等不常用。那么,能不能在做出的 Docker 镜像中,...
插图

优雅地在 Traceroute 里膜 拜大佬

Traceroute 是常用的检查网络状况的工具之一,会显示你操作的电脑到指定服务器的网络路径上经过的每一个路由器的 IP 地址,类似于这样:可以看到后两跳的 IP 显示出了对应的域名,这个域名就是 IP 的反向解析记录。反向解析记录在 DNS 服务器中以类似 4.3.2.1.in-addr.arpa 域名的 PTR 记录形式存在。更多的信息可以参考《在 DN42 中设置 IP 反向解析》这篇文章。自然,Traceroute 里能显示字,也就能显示一篇文章。两年前我为了达到这个目的,开了一堆 Docker 容器,修改它们的路由表让它们连成一长串,来做出显示文章需要的路径。但是开一堆容器不够优雅,而且也不方便管理,尤其是路径过长的时候。更好的方法是用一个程序创建一张虚拟网卡,直接根据进入的 Traceroute 请求回复相应的数据包。这样不仅节省了一大堆容器的系统资源和管理负担,而且也容易根据需要实现复杂的功能。于是我就写了这样一个程序,在 https://github.com/xddxdd/route-chain 可以下载到。用法 ¶首先确定你的系统支持 TUN/TAP 驱动,除了少数 OpenVZ 或者 LXC 的系统外都是支持的。下载源码后 make,然后 make install,然后执行 route-chain 192.168.0.1/24 192.0.0....

友华 PT926G 关闭 TR069

本文介绍如何关闭友华 PT926G 光猫的 TR069 功能,防止电信推送配置 / 固件更新,导致你自己改的桥接、端口转发等失效。这台光猫的 WAN 设置里,TR069 连接是无法修改或者删除的。但是我们只要对光猫后台的代码做一点小小的修改,就可以破解这个限制。首先你需要按照我的《友华 PT926G 光猫破解》这篇文章获取 Telnet 管理员密码。然后 Telnet 进去,执行 su 并输入密码进入 Root Shell。进入后命令行应该会显示 #。然后依次执行以下操作:输入 cp /home/httpd/web/net_eth_links.asp /var/,回车运行。我们准备修改这个文件,但这个文件放在一个只读的分区上,所以先把它复制一份到可以读写的地方。输入 vi /var/net_eth_links.asp 编辑这个文件。vi 是著名的非常难用的编辑器,因此我们一步步来:输入 /is_configurable 然后回车,也就是查找 is_configurable 这个字符串。光标应该会跳转到这个位置://If connection type is TR069 return false, else return truefunction is_configurable(){ var lk = document.forms[0].lkname....
插图

未雨绸缪:使用后量子时代的加密算法

现代互联网上,绝大多数网站都已经支持 HTTPS,其使用的 SSL/TLS 加密协议会将用户的请求数据与网站的响应进行加密,以防止信息被路径上的恶意用户窃取或篡改。而 SSL/TLS 协议中的一个重要组成部分是 RSA、ECDSA 等非对称加密算法,这些算法的密钥分为公钥、私钥两份,公钥可以公开,而私钥则要妥善保管。在访问 HTTPS 网站时,会经过以下的流程:网站会将它的公钥(以证书形式)发送给浏览器。浏览器会校验公钥的有效性,防止中间人篡改公钥,从而拦截或监听通信。浏览器(或操作系统)内置了一组可信任的证书颁发机构(CA)的公钥,通过密码学方法可以确认这份公钥是其中某个颁发机构生成的。证书颁发机构则会通过一系列方法(多级证书链,物理隔绝的密钥保存设备)来保护他们自己的私钥安全,防止有人窃取他们的私钥来随意生成被信任的证书信息。浏览器会与证书颁发机构的服务器联系,查询 “证书吊销列表”(Certificate Revocation List)。这个列表保存了所有的 “虽然的确是证书颁发机构颁发,但是因为系统错误 / 私钥泄漏等原因不能再被信任” 的证书。浏览器在确定公钥可信后,本地随机产生一个随机密钥,用来加密这一次的连接。浏览器将随机密钥用网站的公钥加密,然后发送给网站服务器。加密后的内容只能用网站的私钥解密,不能用公钥解密,因此监听者是无法获取随机密钥内容的。...