无聊工程: 使用境外流量卡创建一个家用局域网代理服务

题外话 如果不是某CuniqHK的卡签了合约,可能不会有这篇文章。因为在使用过程中我发现把卡插在手机里直接用会有很多不方便的地方,比如健康码、丰巢、共享单车之类的本地服务在使用外卡加载的时候会有各种奇奇怪怪的卡顿或者报错。 另外需要说明这个纯粹时用来花境外流量的无聊工程,因为现在有很多成熟且高性价比的替代方案可以选择。 软硬件需求清单 一张境外流量卡 一个随身WiFi设备:这个设备插在主机上,需要能被电脑识别成网卡。 一台运行Ubuntu的主机设备(虚拟机其实也可以,用Host模式接入本地网络),我用的廉价NUC 家中要有现成的无线路由器 能搞出啥呢? 在使用iOS的手机上可以使用”无线局域网”设置界面内的“HTTP”代理功能,连上Ubuntu主机开启的代理服务,走USB 4G网卡的线路上(外)网。 当然了,如果配合Clash之类的允许配置路由规则的App,费些功夫就能给不同的流量设置规则,使得流量卡线路和国内线路能够并用。本文只是想做PoC,所以没管这些。 配置步骤 首先,Ubuntu主机通过网线与主路由器相连。一般情形下,路由器设置一个“静态分配”的路由给这个Ubuntu主机,避免分配的局域网IP地址因为DHCP发生变动。 随后把USB 4G网卡也插上Ubuntu主机,正常情况下主机会识别到这个USB网卡,在终端输入ifconfig能看到它: 由于接入了两张网卡,ubuntu的默认路由里这两张网卡会有不同的优先级。通常来说后连入的设备优先级更低,这样在路由表走默认路由“兜底”的时候会走有线线路出去访问互联网。 这并不是我们想要的,所以需要通过命令来把路由表改一下,让enx0c5b8f279a64这个设备优先。 可以再输入一下route命令,看看是否Metric上的值发生了变化。 接着是配置一个代理服务器,又一个开源i项目叫gost(https://v2.gost.run/)的,很方便。如果要保持持续运行的话,最简单的就是用nohup或者tmux启动它。 代理服务器启动后,就可以在手机上设置了,最简单的http代理就能work。需要注意一点,如果使用的是socks类代理,要注意DNS解析不能使用客户端机器上的,不然会有dns污染的现象。HTTP代理似乎不受影响(参考此处)。 免责声明 本文仅做技术讨论。至于如何获取境外流量卡合法上网,那就各显神通吧。

找到一个不错的Typecho hCaptcha插件

最近苦于机器人的垃圾评论,找了半天发现hCaptcha这个东西很好用。本以为小众的typecho需要自己手写,后来搜了一下发现已经有大佬帮忙写好了插件,地址是https://github.com/plok5202008/Typecho-HCaptcha。 使用起来也挺方便, 在控制台-插件里启用HCaptcha,然后点击插件的设置,填写自己的site key和secret。没有这两个东西的话去https://www.hcaptcha.com/创建一个新用户即可,免费。 在控制台-外观页面点入编辑当前外观,然后右侧选择comments.php文件。找到提交评论的按钮,一般是<button type="submit" class="submit">,在上面加一行 <?php $this->hCaptcha(); ?> 大功告成。

(使用VirtualBox)构建Ubuntu下的clash旁路由服务

效果图一张 几个月前写了一篇文章,讲怎么在Windows下面利用HyperV安装OpenWRT软路由。最近发现了几篇旁路由的文章,另外发现其实clash完全可以在ubuntu下面跑,不用再费那么多事情去研究OpenWRT了,于是乎就有了本文。 目标 本文的目标是利用一台Windows主机(或直接使用Linux主机)搭建一个旁路由服务器,这个服务器与我的光纤猫LAN口连接,提供网关服务,并且能够通过网页ui对clash服务进行配置修改。需要使用旁路由服务的终端(或无线AP),可以通过手工设定网关地址与DNS地址来接驳到旁路由上;同时,需要默认路由服务的终端,只需使用默认DHCP服务即可。施工完成后,家里的网络拓扑大致如下: 光纤猫 192.168.1.1 |- 192.168.1.21 旁路由服务器 |- 192.168.1.20 无线路由器(接驳旁路由网关192.168.1.21) | |- 192.168.50.xxx 手机、iPad、笔电等终端 |- 192.168.1.19 电视机(无需旁路由服务,使用DHCP的网关192.168.1.1) |- … 硬件需求 任意主机,直接运行Ubuntu系统或使用Windows系统。服务器需要有一个网口。本人用来跑旁路由服务的主机是一台Intel J1900,4GB内存的主机。 VirtualBox配置 首先需要安装一个Ubuntu,我选择的是20.04LTS Server版本,所以没有图形化界面。 在系统安装好之后,关闭虚拟机,需要在VirtualBox里配置网络接口类型。默认的网络接口类型应该是NAT,这边找到主机连接光猫的那个网络接口,改为桥接。桥接的意思是,把虚拟主机看做一个独立的主机接入光纤猫的LAN网络,于是乎他就有了一个独立于物理机器的一个“平等的”IP地址了。这个IP地址也就是旁路由的网关地址。 如果你的光猫可以配置静态IP地址分配的白名单,建议把这个旁路由的MAC地址对应的IP分配成静态的,避免因为光纤猫DHCP变动导致旁路由的IP地址不是一个静态值。 Ubuntu配置 允许ip转发 sudo vim /etc/sysctl.conf 找到 net.ipv4.ip_forward=1 这一行,取消掉注释。如果没有找到的话直接新增一行也可以的。随后执行 sudo sysctl -p 使修改生效。 配置iptables 依次执行下面的指令,注意注释的部分,修改成自己的网络配置 iptables -t nat -N clash iptables -t nat -N clash_dns # 这个是fake-ip对应的dns地址,一般不用动…

[C++] 在linux或windows上使用direct io

首先 Direct IO是一种不用内核缓存的IO, 它可以做到直接将用户空间的内存直接写入磁盘或者将磁盘数据直接读到用户空间的缓冲区,这种策略就是不用内核的缓存而使用用户自己设计的缓存. 需要注意的是,使用DirectIO会完全绕过系统的预取(prefetch)以及页缓存机制,如果不是必须,那么我认为还是优先考虑普通的read或者直接mmap吧。 Linux 几个方面注意一下就可以了 在调用[open]1时,把O_DIRECT加上。比如int fd = open("/path/to/file", O_DIRECT, O_RDONLY); 用于文件读写的buffer,必须和磁盘的块大小对齐(保守起见一般可以设为4KB)。有两种方法能拿到地址对齐的内存块: 直接使用posix_memalign; 直接new一段内存,然后根据返回的内存地址,往后找到第一个满足对齐要求的地址就可以。这种方法会浪费前面一段空间,不过其实posix_memalign在系统操作的时候”浪费”了; 借用mmap申请MAP_ANONYMOUS匿名映射,addr参数填NULL的话mmap出来的地址是页对齐的(至少是4K对齐),所以可以直接拿来用; 如果需要lseek之类的操作,注意seek的文件位置偏移量必须是磁盘块大小的整数倍; 2.4内核下, 每次文件读写的长度必须是块大小的整数倍(e.g. N * 4KB). Linux 2.6.0+无此要求; Windows下 参考这篇文章,可以知道Windows下也可以启用类似的机制,对应的打开文件flag是FILE_FLAG_NO_BUFFERING.用法类似,与Linux不同的地方在于: 在CreateFileA(…)调用的dwFlagsAndAttributes参数里把FILE_FLAG_NO_BUFFERING填上; 用于文件读写的buffer也是需要对齐的 也可以使用类似的方法_aligned_malloc申请对齐的内存,但是必须注意要使用_aligned_free释放内存,否则runtime error;

Boost Python的C++对象, Pickle支持及其原理

默认用boost python包裹的C++对象是不支持pickle的,如果要用pickle.dumps(obj)的话那会提示错误 Pickling of "xxx" instances is not enabled. 这边吐槽一下在最新的代码里,给的reference链接其实还是不可用的。真正正确的是https://www.boost.org/doc/libs/1_74_0/libs/python/doc/html/reference/topics/pickle_support.html。 让你的class支持Pickle协议 若要让你的C++ Class支持Pickle协议,比较“正统”的方法是利用boost提供的boost::python::pickle_suite. 拿代码说话: struct world_t { world_t(const string& country) { … } }; struct world_pickle_suite : boost::python::pickle_suite { static boost::python::tuple getinitargs(const world_t& w) { // [可选实现] 返回一个boost::python::tuple元组,其值被用来构造 // 如果一个类的构造函数**不需要参数**的话,可以不用重载这个方法。 return boost::python::make_tuple(w.country()); } static boost::python::tuple getstate(const world_t& w) { // [可选实现] 如果对象的构造函数并不能完全恢复对象的状态, // 那么要用此函数返回其状态值 }…

Apache2配置微信公众号的反向代理

题外话 迫于妹子生日要到了,今年手头又比较紧,所以打算做个微信公众号的小东西骗骗她😜目前跑网站的服务器虽然配置不咋地,但是服务器上也就一个typecho的php项目要跑,平时访问量也门可罗雀,所以打算利用原有的服务器搭个反向代理到微信公众号的服务端。 目标 主域名example.com: 80/443端口直接到原有的网站 子域名wechat.example.com 80端口反向代理到本地服务http://localhost:8766/ 实作 其实很简单,新建一个VirtualHost即可。创建一个/etc/apache2/sites-available/wechat.conf内容如下: <VirtualHost *:80> ServerName wechat.example.com ServerAdmin webmaster@localhost ProxyPass / http://localhost:8766/ ProxyPassReverse / http://localhost:8766/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> 其中的关键是ProxyPass以及ProxyPassReverse. 完成之后,用a2ensite wechat启用这个VirtualHost, 再systemctl reload apache2便万事大吉。

记录一下找了半天的huge page坑——fork越来越慢的原因

背景 之前发现Jupyter Notebook下面,如果数据占用多的话,开多进程池会特别的慢。一开始以为是Python的锅,但是把multiprocessing.pool改成直接用os.fork()调用以后,问题依旧。照理来说unix下面使用fork开进程,会启用copy-on-write机制,内存增长并不是特别明显,但是实际在htop下面看内存仍然会在fork之后增长,并且和进程数量是线性相关的。 原因 随后想了老半天,想到了可能和页表有关系。查了一下,跑的服务器上huge page确实被禁用了(不知为何…). fork的机制简单地说,是在创建新进程的时候把老的进程控制块(Process Control Block)里内存页表拷贝给了新的PCB——这边具体内存的信息是不拷贝的。由于当时Notebook跑的数据处理任务,里面已经用了不少内存(100GB+),所以拷贝的时候如果用默认的4KB内存页,将会有100 * 1024 * 1024 / 4 = 104,857,600个页表! 按典型一个页表项(Page Table Entry)大小4Bytes计算,一个进程开出来光页表会耗400MB内存.

使用互信息(Mutual Information)来评价特征

特征(feature, X)与响应(outcome, y)之间的互信息(mutual information, MI)是一种衡量两个变量之间相关性的方法。该方法将相关性这一定义拓展到非线性的关系上。具体而言,它衡量了一个随机变量经由另一随机变量能得到的信息量。 MI的概念与信息熵(entropy)的概念密不可分。信息熵度量了一个随机变量携带的信息量。形式上,两个随机变量(X,Y)的互信息I(X,Y)定义如下:连续形式 离散形式 sklern.feature_selection.mutual_info_regression方法实现了计算所有特征与一个连续输出之间互信息值的函数,可用于挑选最可能携带预测信息的特征。它也提供一个分类器版本。 本文全文翻译自Stefan Jansen’s Hands-On Machine Learning for Algorithmic Trading*

Support parallel XZ decompression for unix (7zip LZMA SDK based, C/C++)

为unix平台增加XZ多线程解压缩支持(基于7zip LZMA SDK, C/C++) Note This post has nothing to do with the pixz project. I am talking about decompressing the original xz archive using 7-zip’s LZMA SDK under unix environment. Background Originally the 7zip’s LZMA SDK (version 19.00) only covers parallel xz decompression for Windows systems. This post shows the C code that adds…

Visual Studio Code 如何在离线环境下安装远程调试(vscode-server)以及安装各种插件

公司的生产环境里的服务器是禁止了绝大多数互联网连接的,但是有些环境又只有生产环境里有。为了方便,以前总是直接ssh进去用vim写代码,但是总觉得效率还是不够高。(这是我的问题😄)。另一个方法是在本地机器上写好代码,然后rsync过去一把梭。但是写一些稍大的工程的时候,一把梭很难成功。今天决定趁周末解决这种“非技术问题”。 远程搬砖码字调试的意思如下图: 画个重点就是: 本地机器上安装好VS Code; 远程机器上安装好调试工具(vscode-server); 代码留在远程机器上,本地机器仅作为”文本编辑器”这样的前端界面; 本地机器安装远程调试插件(Remote Development Extension) 这个步骤没什么难度,因为本地机器是可以连上网的。在VS Code的Extension页面搜索”Remote Development”安装便是。这边提一句,笔者的环境是“墙中墙”,运行VS Code的也是一个“虚拟机”,里面也没网。像这样的情况,需要根据远程连接的类型(SSH, WSL, Docker…)选择具体的插件,比如SSH的话去 https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh 这个页面,点击右侧的”Download Extension”下载一个vsix后缀的文件传到墙里面。然后选择下图”…”里面的”Install from VSIX”离线安装 离线安装vscode-server调试服务器 正常安装完远程调试插件以后,左侧边栏会多出一个远程连接的tab. 创建一个连接以后,右键那个连接选择”connect to host using new window”会新建一个窗口连接远程服务器。右下角会弹出一个泡泡提示正在安装什么的,这时候要点击”details”看一下详情。这个步骤因为没有网络,它是永远无法完成的…除非我们人为帮他下载好了放好 留意上图红框中的commit hash,我们需要从微软官网手工把这个东西下载下来。 找个有网的机器,去下载https://update.code.visualstudio.com/commit:${commit_id}/server-linux-x64/stable,地址里面的${commit_id}用刚才红框里的代替。下载下来应该是个tar文件,然后把它传到你的远程机器上一个临时位置,这边存放的文件夹用/tmp代替.随后操作: 创建vscode-server的文件夹 解压缩 touch一个0文件,表示加载已经全部完成具体bash如下: mkdir -p ~/.vscode-server/bin/${commit_id} # assume that you upload vscode-server-linux-x64.tar.gz to /tmp dir tar zxvf /tmp/vscode-server-linux-x64.tar.gz -C ~/.vscode-server/bin/${commit_id} –strip 1 touch…