OpenWRT 上配置 Gandi DDNS
一直想给自己的 OpenWRT 路由器添加 DDNS 功能,但 Gandi 不在官方的 ddns-scripts 列表中,自己在网上找了一些脚本,发现是 Python 写的,尝试把 Python 安装到路由器上又发现空间不够,虽然可以安装到 USB 上,但总归是麻烦。
最后找到了官方的一个脚本,非常适合我的需求。简单修改一下,然后安装一下支持 HTTPS 的 cURL:
然后把脚本添加到 crontab 即可。
一直想给自己的 OpenWRT 路由器添加 DDNS 功能,但 Gandi 不在官方的 ddns-scripts 列表中,自己在网上找了一些脚本,发现是 Python 写的,尝试把 Python 安装到路由器上又发现空间不够,虽然可以安装到 USB 上,但总归是麻烦。
最后找到了官方的一个脚本,非常适合我的需求。简单修改一下,然后安装一下支持 HTTPS 的 cURL:
然后把脚本添加到 crontab 即可。
正好上着李贺武老师的《无线移动网络技术》课,然后今天又给 ETC 比赛搭建无线网络,于是周二的时候找老师咨询了一下意见。我们大概给老师讲了一下场地的样子和尺寸(当时估计的大了),然后老师给我们提供了一个可以供参考的部署方案,包括几个 AP 分别放在哪,这些 AP 的 2.4GHz 都用哪个 channel,然后都用多少功率。并且很友善地在周五的时候让助教来场地帮我们 survey 一下无线网络的状况。我们用 Fluke Networks 的 AirCheck Wi-Fi Tester 看了一下场地的各个频道的 AP 数量和信号强度,发现虽然 AP 挺多的,但是它们的信号都比我们的小不少,而且我们也都开到了 50mW,所以干扰不大。
然后昨天下午一点半钟来到场地,用板车把设备都运到计算机开放实验室,然后开始部署无线网络。我们提前来踩过几次点,这边的网络是没有 DHCP 服务器的,通过一个指定的网关出去。我们发现可以利用已有的这些交换机从地下连到各个电脑上的网线,来连接我们的 AP 和交换机,这样我们就免去了走线的麻烦。于是我们先定下放 AP 的位置,然后用寻线器找到网线插到了交换机的哪一个端口上,标记好后换成连接到我们自己的交换机的网线上,从而可以通过 PoE 把我们的 AP 给启动起来。然后用我自己的路由器,把 LAN 口插到交换机上,给 AP 分发 DHCP 地址,然后把下发的默认网关配置为真实的网关(DHCP Option 3) ,没做但是也可以顺带做的是把 WLC 的地址分发下去(DHCP Option 43 Type 241)。
当然,这个过程也遇到了一点小坑,就是交换机还保留了之前的配置,所以这次把新的几个端口划到了一个 VLAN 下,命令自然是记不住的要现查。然后起来以后还挺稳定的,也没出现什么问题,网络带宽也足够用,离千兆还有蛮多距离,一天也才跑了接近俩 TB 的流量。
今天有同学问到我这个问题:
为啥不工作。我怎么看都觉得没啥问题,一开始以为是找不到 pthread,但马上又排除了。想了下会不会是有隐藏的字符,于是让同学 pbpaste | xxd
一下,果然发现这里的 –
是 \xe2\x80\x93
,查了下是 Unicode 里的 En Dash。由于这是从 PDF 里直接拷贝出来的,所以凉了。改成正常的短横杠即可。
老师要求我们搞 CI/CD,CI 自然是很快就搞好了,不过 CD 还得配一下。今天研究了一下它的 Deployer 架构,发现了若干易用性问题:
于是只好经常戳助教然后尝试理解这个东西。。然后遇到了很多的 BUG:
Invalid HTTP_HOST header: 'xxxx_xxx.app.secoder.net'. The domain name provided is not valid according to RFC 1034/1035.
Express 直接就 Invalid Host header
放弃治疗。。。proxy_set_header
上做手脚。。。今天从张宇翔学长那拿到了 荔枝糖(Lichee Tang) 的 FPGA 板子,于是立即开始把前段时间学到的 Verilog 应用上来。不过想到现在我手上没有多少外设,然后又必须远程到 Windows 电脑上去操作,于是先实现了一下 UART 通信。
在网上找到了 ben-marshall/uart 一个简易的实现,很快做到了一直在串口上打印 A
字符。接着我开始尝试实现一个简单的串口回显。一开始,我直接把 UART 读到的数据直接输出,果然可以了,但是一旦传输速率跟不上了,就会丢失数据。于是我添加了 FIFO IP 核,然后把读入的数据存入 FIFO,又从 FIFO 中读取数据写入到 UART 中去。不过发现了一个小 BUG:每次打印的是倒数第二次输入的字符,即丢失了第一个字符。在张宇翔学长的帮助下找到了问题:当 FIFO 的读使能信号为高时,其数据在下一个时钟周期才来,于是解决方案就是等到数据来的时候再向 UART 中写数据:
这样就解决了这个问题。完整代码在 jiegec/learn_licheetang 中。
最近从 @shankerwangmiao 学到了一个方法:通过 veth 把两个 bridge 的 IPv6 桥接起来。方法如下:
$ ip link add veth-v6-in type veth peer name veth-v6-out
$ brctl addif br-in veth-v6-in
$ brctl addif br-out veth-v6-out
$ ebtables -t filter -A FORWARD -p ! IPv6 -o veth-v6-in -j DROP
$ ebtables -t filter -A FORWARD -p ! IPv6 -o veth-v6-out -j DROP
这样就可以看到 veth 上仅有 IPv6 的流量了。
终于可以公开 writeup 了,大家也可以去看 twd2 写的 writeup 。这次是我第一次打 CTF,发现题目还挺有意思的,虽然也有一些题目做不出来,有拿钱还是美滋滋。
这次也认识了好些会打 CTF 的人吧,如 0x00, user1, igoodvegetable 等队伍的同学。一开始被蛤力橙叫来打比赛,我觉得心里挺没底的,然后花了很多时间做题目,一点一点还是做出了不少题目来。最精彩的还是结束以后,当知晓没做出来的题目的做法时候,会不自觉感叹题目的巧妙。也学到了一些梗:
接着就参与了一下 Teaser Dragon CTF 2018,是个在线赛,许多人一起做题,只有 24 小时。看了下题目,除了签到题,其它题都比 THUCTF 2018 难多了,我只能围观他们做题。最后看到别人写的 writeup,真是太巧妙了,一环接一环,真的想不到。不过也有很麻烦的题目,特别是有的逆向的题目,太考验人的耐心了。
接下来就等待官方的 writeup 和别人的 writeup,学习一下别人的做法吧。
听闻北京移动给 LTE 配置了 SLAAC,但现在需要手动打开,方法如下:
Settings -> Network & Internet -> Mobile Network -> Advanced -> Access Point Names -> 中国移动 GPRS (China Mobile) -> 把 APN procotol 和 APN roaming protocol 两项都改成 IPv4/IPv6
然后在 test-ipv6.com 上可以看到确实分配了 IPv6 地址,不过目前评分只有 1/10。也就是说可用性还不佳。
而在 iOS 上,通过 HE 的 Network Tools 能看到,确实拿到了 IPv6 的地址,但是出不去,怀疑是运营商没有下发相关配置,所以还不能使用,只能继续等。
2018-11-06 更新:现在 iOS 用户也有 LTE 的 v6 了。评分是 9/10。目前可用性已经可以了,就是国内互联还不大好。
前段时间 GPGMail 宣布不再免费,在三十天的试用期后就不给用了。唉,可能是官方实在没钱维护了,也可能是官方想赚钱了。不过,既然 GPGMail 采用的是自由的许可证,意味着我们可以自己对代码进行更改。和许可证验证相关的代码如下:
- (BOOL)hasActiveContract {
NSDictionary *contractInformation = [self contractInformation];
return [contractInformation[@"Active"] boolValue];
}
我们只要改成 return TRUE
,在自己的电脑上手动编译、并复制到 /Library/Application Support/GPGTools/GPGMail
下即可。
另:还有一个直接对二进制打 patch 的方法(仍然符合许可证),利用了最近打 CTF 学到的一些知识。找到以上这个函数,然后把返回值修改成非零即可。这里就不提供方法了。最后的更改:
当然了,还需要额外 codesign --remove-signature
一下。
谨慎对非自由软件采用这个方法。可能有法律风险。
做了一个 Windows 10 安装 U 盘,想测试一下能不能启动,于是想用 VirtualBox 起一个虚拟机。但是发现,一般情况下要从 ISO 或者把 U 盘克隆成一个 vdi/vmdk etc 再启动。不过找到了 Cem Arslan 的 VirtualBox - Booting From USB (MAC) 实验了一下,确实可以用,以 /dev/disk2
为例方法如下:
$ diskutil unmountDisk /dev/disk2
$ sudo chown $(whoami) /dev/disk2
$ VBoxManage internalcommands createrawvmdk -filename PATH_TO_VMDK -rawdisk /dev/disk2
$ # Now boot from VirtualBox
对于其它平台,可以参考 Tu Nguyen 的 How to boot from USB in VirtualBox 。
研究了一下生成的 vmdk 文件,大概是这样的:
# Disk DescriptorFile
version=1
CID=12345678
parentCID=ffffffff
createType="fullDevice"
# Extent description
RW 12345678 FLAT "/dev/disk2" 0
# The disk Data Base
#DDB
ddb.virtualHWVersion = "4"
ddb.adapterType="ide"
ddb.geometry.cylinders="1234"
ddb.geometry.heads="1234"
ddb.geometry.sectors="1234"
ddb.uuid.image="12341234-1234-1234-1234-123412341234"
ddb.uuid.parent="00000000-0000-0000-0000-000000000000"
ddb.uuid.modification="00000000-0000-0000-0000-000000000000"
ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000"
ddb.geometry.biosCylinders="1234"
ddb.geometry.biosHeads="1234"
ddb.geometry.biosSectors="1234"
由于本机算力不足,想要在远程编译 LineageOS ,其中有一步需要连接到已有的设备,于是突发奇想:
方法如下:
$ adb shell ip -f inet addr show wlan0
$ # remember the ip address here
$ adb tcpip PORT1
$ ssh -R PORT2:ANDROID_IP:PORT1 REMOTE
(remote)$ adb connect localhost:PORT2 # trust this device on Android
参考文档:
由于 MongoDB 只支持当前版本和上一个版本的数据库格式,然后刚刚滚系统升级的时候升级到了 3.6.x,而数据库格式仍然是 3.2.x 的,于是需要先安装回 3.4.x 版本的 MongoDB,输入命令把数据库升级到 3.4.x 版本后,再用 3.6.x 的数据库进行升级。
以 从 Ubuntu 14.04 LTS 升级到 Ubuntu 18.04.1 LTS 为例,方法如下:
$ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.4.17.tgz
$ tar xvf mongodb-linux-x86_64-ubuntu1604-3.4.17.tgz
$ cd mongodb-linux-x86_64-ubuntu1604-3.4.17/bin/
$ sudo ./mongod --config /etc/mongodb.conf &
$ mongo
> db.adminCommand( { setFeatureCompatibilityVersion: '3.4' } )
{ "ok" : 1 }
$ fg
^C
$ sudo chown -R mongodb:mongodb /var/lib/mongodb
$ sudo systemctl start mongodb
$ mongo
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ "featureCompatibilityVersion" : { "version" : "3.4" }, "ok" : 1 }
> db.adminCommand( { setFeatureCompatibilityVersion: '3.6' } )
{ "ok" : 1 }
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ "featureCompatibilityVersion" : { "version" : "3.6" }, "ok" : 1 }
$ # Okay now
WPAD(Web Proxy Auto-Discovery Protocol)是一个可以利用 dhcp 分发 pac 配置的协议。方法如下:
$ # ssh to router first
$ vim /etc/dnsmasq.conf
dhcp-option=252,"http://router_ip/wpad.dat"
$ vim /www/wpad.dat # put pac here
$ service dnsmasq restart
$ # ensure proxy is available to lan
$ # enable wpad on devices
参考文档:
作为一个不用 vim 编辑会死星人,用 Xcode 总是止不住自己想 Escape 的心。于是找到了 XVimProject/XVim2 进行配置。
大致方法如下:
git clone
然后 make
,第一次打开 Xcode 的时候选择 Load Bundle
即可。终于可以满足我 Escape Xcode 的欲望了。
之前想看看自己各个盘的情况,但是发现只能看电脑内置的 SSD 的 S.M.A.R.T 信息,而移动硬盘的都显示:
$ smartctl -a /dev/disk2
smartctl 6.6 2017-11-05 r4594 [Darwin 17.7.0 x86_64] (local build)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org
/dev/disk2: Unable to detect device type
Please specify device type with the -d option.
Use smartctl -h to get a usage summary
一开始我怀疑是个别盘不支持,但换了几个盘都不能工作,问题应该出现在了 USB 上。查了下资料,果然如此。根据 USB devices and smartmontools ,获取 S.M.A.R.T 信息需要直接发送 ATA 命令,但是由于经过了 USB,于是需要进行一个转换,导致无法直接发送 ATA 命令。这个问题自然是有解决方案,大概就是直接把 ATA 命令发送过去(pass-through)。上面这个地址里写到,如果需要在 macOS 上使用,需要安装一个内核驱动。可以找到,源码在 kasbert/OS-X-SAT-SMART-Driver 并且有一个带签名的安装包在 External USB / FireWire drive diagnostics support 中可以下载。丢到 VirusTotal 上没查出问题,用 v0.8 版本安装好后就成功地读取到了移动硬盘的 S.M.A.R.T 信息了。
然后我又简单研究了一下各个 S.M.A.R.T 各个值的含义是什么。 VALUE
代表当前的值, WORST
代表目前检测到的最差的值, THRESH
代表损坏阈值。这些值都是从 RAW_VALUE
进行计算后归一化而来。然后 TYPE
分为两种,一是 Pre-fail
,代表如果这一项的值小于阈值,代表这个机器很危险了,赶紧拷数据丢掉吧。二是 Old_age
,代表如果这一项小于阈值,代表这个机器比较老了,但还没坏。真正要看是否坏了,可以看 When_Failed
一栏。
前几天无聊闲逛看到了一个很有趣的 RFC8367 - Wrongful Termination of Internet Protocol (IP) Packets ,看到日期大家应该都懂了,这是个粥客,不过里面还是反映了一些事情,咳。
之前看到闪客实现了 shankerwangmiao/xt_PROTO ,想到自己也可以做一个 iptables 扩展,于是就写了 jiegec/xt_EQUALIZE 。它是这样使用的:
$ git clone git@github.com:jiegec/xt_EQUALIZE.git
$ make
$ sudo make install
$ sudo iptables -t filter -A INPUT -j EQUALIZE
$ sudo dmesg -w &
$ # Make some random network requests to see the effect!
$ ping 1.1.1.1
$ ping 8.8.8.8
$ ping ::1
目前还没有把参数都变成可以配置的。如果真的有人需要这个模块的话,我再改吧(逃
由于 macOS 对 TAP Interface 不会自动出现一个设置中对应的服务,所以需要手动进行配置。一番测试后,发现可以通过:
启用系统自带的 dhcp 和 ra 功能。也许有方法可以把这些 tap 搬到系统的设置中去。
UPDATE:
可以把 TAP Interface 加到系统的设置中去。方法参考Virtual network interface in Mac OS X。完成以后可以直接通过系统设置界面进行配置。
由于没有找到 macOS 下现成的 GRETAP 实现,我就想到自己实现一个。由于tuntaposx提供了一个和 Linux 下基本一样的 TAP Interface,于是自己利用 raw socket 和 TAP Interface 实现了一下,主要方法:
主要的难度是在 raw socket 部分,macOS 继承了 BSD,与 Linux 不大一样。于是参考了SOCK_RAW Demystified,成功地实现了这个功能。
代码放在jiegec/gretapmac。写得并不高效,仅仅可用,用了一百多行。
UPDATE: 之后又随手实现了一个类似的协议,L2TPv3 over UDP。代码在jiegc/l2tpv3udptap。
受 Run Babeld over Wireguard - Fugoes's Blog 和 Route-based VPN on Linux with WireGuard 启发,自己也想尝试一下,在一个有多个结点的网络中,如何通过 WireGuard 构建一个 overlay network,并通过 babel 自动进行结点发现和路径选择。
首先建立点对点的 WireGuard Tunnel。由于我们用 babel 进行路由,所以我们不能采用 Wiregurad 本身基于目的地址的端口复用,所以每一个 WireGuard interface 都只有一个 Peer。
配置一个点对点的 WireGuard Tunnel:
$ # for wg-quick
$ cat wg0.conf
[Interface]
Address = IPV4/32, fe80::ID/64
PrivateKey = REDACTED
ListenPort = PORT1
Table = off # ask wg-quick not to insert peer address into routing table
[Peer]
PublicKey = REDACTED
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = REDACTED:PORT2
这里的 IPV4 和 ID 在同一设备上的不同 WireGuard Tunnel 上相同。只是通过 wg interface 编号来区分。
接着配置 babeld:
$ cat babeld.conf
router-id ID
local-port 33123 # for babelweb2
# one line for each wg interface
interface wg0 type tunnel rtt-max 512
redistribute ip PREFIX/LEN ge LEN le 32 local allow # tunnel neighbors
redistribute proto 42 # routes installed by babeld
redistribute local deny
# consult babeld man page for more
然后通过 BabelWeb2(很难用)进行可视化,然后通过手动触发一些网络波动即可达到效果。
由于我打开了「Invert Fn」功能,所以需要调亮度的时候,是采用 Fn+F1/F2 的方法。但是,我的机械键盘则是,不按 Fn 时为 1-9,按着 Fn 时为对应的 F1-F9,但是就无法调整亮度和声音了。
然后捣腾了一下,发现可以用 ScLk 和 Pa/Br(名称在各个键盘上不大一样)调整亮度。不过,还没发现如何更改音量。。。
首先参照OpenWRT Wiki - Lenovo Y1 v1找到刷固件教程:
然后就是常规的密码设置,opkg 源设置为 tuna 的源,配置 ssh 和 公钥。
接下来,我们为了使用学校的 SLAAC,采用 ebtables 直接把学校的 IPv6 bridge 进来,而 IPv4 由于准入系统,需要 NAT。
参考 Bridge IPv6 connections to WAN,下载 v6brouter_openwrt.sh 到某个地方,然后修改一下里面的一些参数:
然后跑起来之后,自己的电脑可以成功拿到原生的 IPv6 地址了,不需要用难用的 NAT66 技术。
下一步是采用z4yx/GoAuthing。
$ go get -u -v github.com/z4yx/GoAuthing
$ cd $GOPATH/src/github.com/z4yx/GoAuthing/cli
$ env GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build main.go
$ mipsel-linux-gnu-strip main
$ scp main root@192.168.1.1:~/GoAuthing
$ ssh root@192.168.1.1
$ opkg install ca-certificates
$ ./GoAuthing
这里参考了解决 GO 语言编译程序在 openwrt(mipsle 架构) 上运行提示 Illegal instruction 问题,配置了 GOMIPS 环境变量。为了访问 HTTPS 网站,参考了OpenWRT Wiki - SSL and Certificates in wget。有毒的是,这个环境变量,在 macOS 上不能正常工作,而在 Linux 机子上是没有问题的。
然后就可以成功地跑起来 GoAuthing,解决了上校园网认证的问题。
感谢宇翔编写的 GoAuthing 小工具。
更新:简化了一下 v6brouter 脚本:
#!/bin/sh
BRIDGE=br-lan
WAN_DEV=$(/sbin/uci get network.wan.ifname)
WHITELIST1="00:11:22:33:44:55"
WHITELIST2="55:44:33:22:11:00"
brctl addbr $BRIDGE 2> /dev/null
brctl addif $BRIDGE $WAN_DEV
ip link set $BRIDGE down
ip link set $BRIDGE up
brctl show
ebtables -F
ebtables -P FORWARD ACCEPT
ebtables -L
uci set dhcp.lan.ra='disabled'
uci set dhcp.lan.dhcpv6='disabled'
uci commit
/etc/init.d/odhcpd restart
echo 2 > /proc/sys/net/ipv6/conf/$BRIDGE/accept_ra
ebtables -t broute -F
ebtables -t broute -A BROUTING -i $WAN_DEV -p ! ipv6 -j DROP
ebtables -t broute -A BROUTING -s $WHITELIST1 -p ipv6 -j ACCEPT
ebtables -t broute -A BROUTING -d $WHITELIST1 -p ipv6 -j ACCEPT
ebtables -t broute -A BROUTING -s $WHITELIST2 -p ipv6 -j ACCEPT
ebtables -t broute -A BROUTING -d $WHITELIST2 -p ipv6 -j ACCEPT
ebtables -t broute -A BROUTING -p ipv6 -j DROP
ebtables -t broute -L
注意,这里添加了两个 WHITELIST 的 MAC 地址,表示只让这两个 MAC 地址的设备访问 v6。一般来说,外面网关的 MAC 地址也要放进来,不然可能接收不到 RA。如果不需要白名单的话,可以去掉 ebtables 的后几行规则。
一直对 Linux 的启动很感兴趣,但对 initrd 和 initramfs 等概念不大了解,于是上网找了资料,自己成功地看到了现象。
参考资料:
具体步骤:
$ cat hello.c
#include <stdio.h>
#include <unistd.h>
int main() {
for (;;) {
printf("Hello, world!\n");
}
}
$ gcc -static hello.c -o init
$ echo init | cpio -o -H newc | gzip > initrd
$ qemu-system-x86_64 -kernel /boot/vmlinuz-linux -initrd initrd -nographic -append 'console=ttyS0'
# Use C-a c q u i t <Enter> to exit
可以看到过一会(三四秒?),可以看到满屏的 Hello world 在输出。
Debian Stretch 9.5 刚刚更新,自己手上有不少 stretch 的机器,于是顺手把他们都升级了。不过,这个过程比较繁琐,于是我采用了 MuSSH 的方法,让这个效率可以提高,即自动同时 SSH 到多台机器上进行更新。
首先编写 hostlist 文件,一行一个地址,分别对应每台机器。
然后采用 MuSSH 对每台机器执行同样的命令
此时要求,ssh 上去以后有相应的权限。这个有许多方法,不再赘述。然后就可以看到一台台机器升级,打上安全补丁,爽啊。
参考网站:
Ubuntu 使用 fbterm 无法打开 fb 设备的解决及 fcitx-fbterm 安装 Fcitx - ArchWiki 完美中文 tty, fbterm+yong(小小输入法) 让 linux console 支持中文显示和 fcitx 输入法
考虑到 lemote yeeloong 机器的 cpu 运算性能,跑一个图形界面会非常卡,于是选择直接用 framebuffer。但是,显示中文又成了问题。于是,采用了 fbterm 和 fcitx 配合,加上 gdm 的方法,完成了终端下的中文输入。
首先,安装相关的包:
接着,基于以上参考网站第一个,编写 zhterm 文件:
$ echo zhterm
#!/bin/bash
eval `dbus-launch --auto-syntax`
fcitx >/dev/null 2>&1
fbterm -i fcitx-fbterm
kill $DBUS_SESSION_BUS_PID
fcitx-remote -e
$ chmod +x zhterm
$ zhterm
# Use C-SPC to switch input source
另:找到一个映射 Caps Lock 到 Escape 的方案: