非线性列车 - 列车中转站只允许移动端访问

非线性列车 - By. Juij 这个资源网站的行为很奇怪,默认下载链接会引导到 列车中转站 去,展示一个大大的 QR code。并且二维码内容中的 目标链接 还添加了移动端检测。

检测的原理是把 navigator.maxTouchPoints 发送到后台,如果数字大于 1 会 302 重定向到网盘地址。
fetch 响应里有段 set-cookie: _dv_data=1|true; Path=/; HttpOnly; Secure; 对应的就是这两个数值

https://to.juij.fun/CDPR
const terminal = document.getElementById("terminal");
const info = {
	hasTouch: 'ontouchstart'in window || navigator.maxTouchPoints > 0,
	maxTouchPoints: navigator.maxTouchPoints || 0
};
const text = "访问验证中...";
const cursor = document.createElement("span");
cursor.className = "cursor";
cursor.textContent = " ";
terminal.appendChild(cursor);
let i = 0;
function type() {
	if (i < text.length) {
		cursor.insertAdjacentText("beforebegin", text[i]);
		i++;
		setTimeout(type, 80);
	} else {
		setTimeout(redirect, 500);
	}
}
function redirect() {
	fetch(window.location.href, {
		method: "GET",
		headers: {
			"X-Device-Touch-Points": String(info.maxTouchPoints),
			"X-Device-Has-Touch": String(info.hasTouch)
		}
	}).then(r => r.text()).then(html => {
		document.open();
		document.write(html);
		document.close();
	}
	).catch( () => window.location.reload());
}
type();

如果在移动端往 https://to.juij.fun/ 输入错误的链接,还会被封 IP 24 小时。
无法理解这样限制的目的是什么,毕竟在桌面端绕过这个检测很容易:

扫码可以用 PixPin 截图识别;模拟苹果设备刚好有 户晨风检测设备欺骗 这种脚本能借来使用(安装后改下激活域名列表);或者开发者工具断点修改内存的值。

除了强迫掏出手机扫码恶心人一下,我想不出别的意义。

我的 WinRAR 压缩配置

创建了两个压缩配置

  • 默认配置 - 用于日常打包,未来会在 GUI 浏览和编辑的文件
设置项参数值说明
压缩方式标准均衡速度和压缩比
字典大小128 MB我内存大
更新模式添加并更新文件软件的默认值
NTFS 选项保存文件流数据从一道取证题目谈NTFS交换数据流 | Cosmic Fragments
备份打开共享文件允许访问使用中的文件
时间保存修改、创建、访问时间低精度保留三大时间戳
  • 备份配置
设置项参数值说明
压缩方式最好最大压缩比
字典大小128 MB我内存大
更新模式覆盖前询问都是创建新文件不应该触发,询问以提醒出现问题
压缩选项创建固实、添加恢复记录备份文件不会经常打开浏览
NTFS 选项保存文件流数据同上表
备份打开共享文件、按掩码产生压缩文件名模式为 .yyyymmddhhmmss,这样重复创建同名 RAR 文件会保留多个版本
时间保存修改、创建、访问时间、高精度高精度保留三大时间戳

关于选项是何意思参考内置帮助文件或者在线的 缩文件名和参数对话框 - WinRAR Documentation

另外,只有从暗链下载到的简体中文版才是天生无广告的,从这里获取 n2far2000/winrarsc: WinRAR Official Release (Simplified Chinese)

QEMU 禁用自带的软盘和光驱

在不添加 -nodefaults 启动的虚拟机会自带一个光驱和一个软盘,看不顺眼就想移除它。

(qemu) info block
ide0-hd0 (#block151): E:\VirtualMachines\GRUB2/root.qcow2 (qcow2)
    Attached to:      /machine/unattached/device[19]
    Cache mode:       writeback
    Backing file:     E:\VirtualMachines\debian-13-enihsyou-amd64.qcow2 (chain depth: 2)
 
ide0-hd1 (#block785): E:\VirtualMachines\GRUB2/linux.qcow2 (qcow2)
    Attached to:      /machine/unattached/device[20]
    Cache mode:       writeback
 
ide1-cd0: [not inserted]
    Attached to:      /machine/unattached/device[21]
    Removable device: not locked, tray closed
 
floppy0: [not inserted]
    Attached to:      /machine/unattached/device[31]
    Removable device: not locked, tray closed

其实有简单的办法,qdev-device-use.txt 说可以这样,只禁用特定设备。

qemu-system-x86_64 -device isa-fdc -device ide-cd

设备名称有点门道,换成 -device floppy 是不行的

Debian 缺少 mkfs.ext4

Server 镜像不自带,使用 sudo apt install e2fsprogs 自行安装

QEMU WHPX 启动时有 injection failed 的警告信息

$ qemu-system-x86_64.exe \
	-accel whpx \
	-cdrom debian-10.8.0-amd64-netinst.iso
WHPX: setting APIC emulation mode in the hypervisor
Windows Hypervisor Platform accelerator is operational
whpx: injection failed, MSI (0, 0) delivery: 0, dest_mode: 0, trigger mode: 0, vector: 0, lost (c0350005)

使用 -accel whpx,kernel-irqchip=off 启动可解,原因无法理解

另外当组合使用 -machine q35,accel=whpx 会在启动时,在 GRUB 启动 kernel 显示完 Loading initial ramdisk` 之后,输出绿色块状不可辨识的文字。 未解之谜
qemu-whpx-boot-garbled-text

容器响应 IPv6 前缀变动并更新 DDNS

之前留下的坑 新建容器后,需要从容器中以 IPv6 协议向外访问一次,才能通过 IPv6 地址从 WAN 侧访问进来 打了过来。运行一段时间后路由的前缀发生变化,因为内网设备未曾向互联网发送过 IPv6 流量,链路上的路由器设备没通过 NDP 学习到容器新的 IPv6 地址转发到哪个端口。

简单的办法是让容器定时 ping 一下公网,好在 DDNS-GO 就能做。它有个自定义指令功能,刚好我不需要 IPv4 的注册,可以利用一下

项目内容
IPv4启用
获取 IP 的方式通过命令获取
命令内容ping 2400:3200::1 -6 -c1 -q > /dev/null
域名example.com 绝对无法触动的目标

日志中会因无输出而跳过

获取IPv4结果失败! 命令: /bin/sh -c ping 2400:3200::1 -6 -c1 -q > /dev/null, 标准输出: ""
未能获取IPv4地址, 将不会更新

2026-02-01 一段时间后发现,这个方法对于新创建的 MACVLAN 网络下的容器无效。容器依然需要先以 GUA 地址向 Docker Host 外且在 LAN 内的有效网络设备地址发送一轮请求,并收到响应才能在路由表上产生邻居记录。

而且 DDNS-Go 刚启动时会因为没完成 SLAAC 产生 从网卡中获得IPv6失败! 网卡名: eth0 日志

还有一个奇怪的表现:如果是在 docker compose 中这样启动,就永远得不到 ping 的响应(或者产生 1 个 reply 就卡住),直到手动登进容器中发起另一个 ping;而直接 docker run 并没有这样的问题。

services:
  ddns:
    image: debian
    networks:
      - docker
    entrypoint: >
      sh -c "ping 2409:8a1e:6940:7c20::1"
networks:
  docker:
    external: true

命令中间加上 ip -aping -w 一番调试后发现,刚启动时就执行的 ping 还没有 GUA 地址。容器只得到了在 docker network create --ipv6 --ip-range 过程中指定的网段分配给它的 ULA 地址。因为我这里设置的是 fd00:2022:22ea:2677:d::/64,在其他设备上可没这段路由表,也就得不到响应了。

过了几秒,SLAAC 也完成了,容器获得了属于它的 GUA 地址。此时再 ping 就会使用 GUA 地址发起请求,正常建立连接。

# entrypoint: >
#   sh -xc "ip a show eth0; ping -c1 -W5 2409:8a1e:6940:7c20::1; ip a show eth0; Attaching to alist-ddns
+ ip a show eth0
+ ping -c1 -W5 2409:8a1e:6940:7c20::1
68: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 6a:b2:c3:ce:c6:be brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.128/24 brd 192.168.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fd00:2022:22ea:2677:d::/64 scope global flags 02
       valid_lft forever preferred_lft forever
    inet6 fe80::68b2:c3ff:fece:c6be/64 scope link tentative
       valid_lft forever preferred_lft forever
PING 2409:8a1e:6940:7c20::1 (2409:8a1e:6940:7c20::1): 56 data bytes
 
--- 2409:8a1e:6940:7c20::1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
+ ip a show eth0
68: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 6a:b2:c3:ce:c6:be brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.128/24 brd 192.168.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2409:8a1e:6940:7c20:68b2:c3ff:fece:c6be/64 scope global dynamic flags 100
       valid_lft 259197sec preferred_lft 172797sec
    inet6 fd00:2022:22ea:2677:d::/64 scope global flags 02
       valid_lft forever preferred_lft forever
    inet6 fe80::68b2:c3ff:fece:c6be/64 scope link
       valid_lft forever preferred_lft forever
+ ping 2409:8a1e:6940:7c20::1
PING 2409:8a1e:6940:7c20::1 (2409:8a1e:6940:7c20::1): 56 data bytes
64 bytes from 2409:8a1e:6940:7c20::1: seq=0 ttl=63 time=1737.671 ms
64 bytes from 2409:8a1e:6940:7c20::1: seq=1 ttl=63 time=737.528 ms
64 bytes from 2409:8a1e:6940:7c20::1: seq=2 ttl=63 time=1.295 ms
64 bytes from 2409:8a1e:6940:7c20::1: seq=3 ttl=63 time=1.458 ms

这个引向一个解决方法,在 设置 IPv6 ULA 创建 docker network 时就设置上 LAN 的网段

docker network create -d macvlan --ipv6 \
   --subnet 2409:8a1e:6940:7c20::/64 --gateway 2409:8a1e:6940:7c20::1 \
   --ip-range 2409:8a1e:6940:7c20:d::/80 \
   -o parent=ens19 docker

整这么一出本来就是为了解决 IPv6 Prefix 不稳定的问题,现在落到还得先搞到 Prefix 加到网络上才能顺利访问,完全本末倒置。
那是不是等等就可以了。没错,sleep 5; ping 2409:8a1e:6940:7c20::1 就有效。

下一个问题是,如何完成邻居发现过程,让链路上的设备都知道自己。
目前感觉是 Docker Network 看网段不对,吞掉了 NS 消息。那么可以找到一个 LAN 内的 GUA 地址,请求一下。好在发现一条路子,ip -6 r 的第一条记录是 RA 响应的

# ip -6 r
2409:8a1e:6940:7c20::/64 dev eth0  metric 256  expires 0sec
fd00:2022:22ea:2677::/64 dev eth0  metric 256
fe80::/64 dev eth0  metric 256
default via fd00:2022:22ea:2677::1 dev eth0  metric 1024
default via fe80::be24:11ff:fe23:202 dev eth0  metric 1024  expires 0sec

而且我所在的中国移动 AS24400 网络前缀是不变的,那么可以安全地 grep,就有下面的脚本验证目标地址对的:

sleep 5; ping $(ip -6 route | awk '/^[23]/{sub(/\/.*/, "", $1); print $1 "1"; exit}') -6 -c1 > /dev/null

完整的配置长这样,只调整 docker compose,不再需要 DDNS-Go IPv4 部分的 Hack 了:

services:
  main:
    container_name: alist
    image: xhofe/alist:latest
    networks:
      - docker
 
  ddns:
    image: jeessy/ddns-go
    container_name: alist-ddns
    network_mode: service:main
    entrypoint:
      - /bin/sh
      - -c
      # exec ddns-go only when global IPv6 is available
      - |
        while true; do
          if ip -6 addr show scope global | grep 'inet6 [23]'; then
            sleep 3
            if ping -c1 -W5 $(ip -6 route | awk '/^[23]/{sub(/\/.*/, "", $1); print $1 "1"; exit}'); then
              exec /app/ddns-go -f 600
            fi
          fi
        done
    healthcheck:
      test: ping alist.home.kokomi.site -c1 -W1
 
networks:
  docker:
    external: true

2026-02-03 并不是 Docker 吞掉了 NS 消息,而是更上层的 OpenWrt 和 PVE,见 多接口在同一个 IPv6 网段下的冲突。所以那个 ping 就没必要了,最终这样:

services:
  main:
    container_name: alist
    image: xhofe/alist:latest
    networks:
      - docker
 
  ddns:
    image: jeessy/ddns-go
    container_name: alist-ddns
    network_mode: service:main
    entrypoint:
      - /bin/sh
      - -c
      # exec ddns-go only when global IPv6 is available
      - |
        while true; do
          if ip -6 addr show scope global | grep -q 'inet6 [23]'; then
              exec /app/ddns-go -f 600
          fi
        done
    healthcheck:
      test: ping alist.home.kokomi.site -c1 -W1
 
networks:
  docker:
    external: true

2026-02-05 其实问题是 PVE 下的网桥应该关闭 multicast snooping