IPsec 配置备忘 Part10 - Xfrm 与 Nftables

点击此处回到系列文章目录

Xfrm Interface 与 Route-based VPN

到目前为止,我们所有的配置都是基于 Traffic selector 来选择要加密的流量,而非路由表。这种方式被称为 Policy-based 。但是在实际配置中,我们可能更倾向于使用传统的配置思路,即,使用路由表或防火墙规则将特定流量发送至特定端口,并将流经此端口的所有数据加密。这种方法被称为 Route-based VPN。一些优点有:

  • 在路由表中统一管理转发状态而不用反复调试 Traffic selector 的匹配问题。
  • 可以直接在接口上抓明文包,以及设置 MTU。

一些常见配置使用 GRE 或 L2TP 等隧道协议来创建接口,然后用 IPSec 加密整个隧道。strongSwan 自版本 5.8.0,Linux 自版本 4.19 起支持一种新的 xfrm 接口类型,它专门用于给 IPSec 创建一个接口以方便实现 Route-based VPN,并且不像 GRE 或 L2TP 那样需要浪费额外的数据包头。Xfrm 接口可以使用 iproute2 工具包创建,也可以用 systemd-networkd 之类的网络管理工具。

1
ip link add xfrm0 type xfrm if_id 700

修改 strongSwan 配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
connections {
conn {
# 忽略其他配置字段
children {
child_sa {
# 忽略其他配置字段
local_ts = 0.0.0.0/0 # 路由表负责决定要转发什么流量,TS 可以允许所有。
remote_ts = dynamic # 如果有多个对端,仍然需要 remote_ts 匹配对端 IP
# 以应用正确的 CHILD_SA
}
}
if_id_in = 700 # 设置所有 CHILD_SA 使用的 XFRM IF_ID
if_id_out = 700 # in, out 可以不同,但一般没必要
}
}

Xfrm 接口会对所有数据包加上一个特殊的 XFRM_IF_ID 标记,内核中的 xfrm 规则会匹配这一 id,进而加密对应流量。注意路由规则和 TS 规则需要同时满足才加密流量。内核中的 if_id 配置可以用命令查看:

1
2
3
4
5
6
root# ip xfrm policy
src 0.0.0.0/0 dst 0.0.0.0/0
dir out priority 399999 ptype main
tmpl src 10.0.0.1 dst 10.0.0.2
proto esp spi 0xc4f5e6d5 reqid 1 mode tunnel
if_id 0x2bc

Netfilter

关于 IPSec 数据包与 netfilter 系统的交互,推荐阅读以下两篇文章:

此处仅作备忘:

  • 入站 ESP 包:先经过 PREROUTING 和 INPUT, 然后解密。
  • 解密后的明文包:重新通过 PREROUTING,发往 INPUT 或 FORWARD。
  • 出站明文包:在经过 OUTPUT 或 FORWARD 前进行 xfrm policy 匹配,然后发往 POSTROUTING,然后加密。
  • 加密后的密文包:经过 OUTPUT 和 POSTROUTING,离开本机。
  • 在不使用 xfrm 接口的情况下,直接在物理接口上抓包可以看到入站密文、入站明文、出站密文,但是看不到出站明文。
  • 密文包可以用 meta l4proto esp nftable 规则匹配。
  • 在 PREROUTING / INPUT / FORWARD 中,使用ipsec in <...>meta ipsec可以匹配解密后的明文包。
  • 在 FORWARD / OUTPUT / POSTROUTING 中,使用ipsec out <...>rt ipsec可以匹配将要被加密的明文包。

例子:如果因为某些原因 strongSwan 没有正确启动,明文流量可能未经加密就被发送,使用 nftables 阻止所有发往 70.0.0.1 但是未经加密的数据包:

1
ip daddr 70.0.0.1 rt ipsec missing counter drop

例子:在不使用 xfrm 接口的情况下,捕获所有发往 eth0 的尚未加密的 IPSec 出站包。抓包程序需使用 nflog 接口 tcpdump -i nflog:5。官方文档参考 Taking Traffic Dumps on Linux

1
meta oifname eth0 rt ipsec exists log group 5

在 MSI TRX40 主板上启用 SR-IOV

最近继续折腾很早之前买的线程撕裂者(装机回顾)。主板用的是MSI TRX40 PRO 10G,BIOS里有IOMMU选项,显卡直通也一直正常所以没多想。直到最近想折腾一下网卡SR-IOV,然后GG:

1
2
root# echo 1 > /sys/bus/pci/devices/0000:21:00.0/sriov_numvfs
kernel: cxgb4 0000:21:00.0: Parent bridge 20:03.1 doesn't support ARI; can't instantiate Virtual Functions

提示系统不支持 ARI (Alternative Routing-ID Interpretation)。看下PCIE根端口的状态,确实没开:

1
2
3
4
5
root# lspci -vv -s 20:03.1
20:03.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Starship/Matisse GPP Bridge (prog-if 00 [Normal decode])
Capabilities: [58] Express (v2) Root Port (Slot+), IntMsgNum 0
DevCap2: FRS- LN System CLS Not Supported, TPHComp+ ExtTPHComp- ARIFwd-
DevCtl2: Completion Timeout: 65ms to 210ms, TimeoutDis- ARIFwd-

在网上搜了一圈以后发现这个设置应该在一个叫AMD CBS的菜单里,然而这块主板并没有……

于是开始折腾“破解”BIOS设置,终于在浪费N个小时后发现一个叫 Universal AMD Form Browser (github) 的工具。尝试了一下确实可用。在CBS的NBIO菜单里把"ARI Support"和"ARI Enumeration"都Enable后就可以看到 ARIFwd 的减号变加号了。于是重新尝试,然而再次失败:

1
kernel: cxgb4 0000:21:00.0: not enough MMIO resources for SR-IOV

因为这个ARI功能是我们hack出来的,所以目测BIOS没有正确给VF预留足够的地址空间。只需要在内核参数加上pci=realloc,让Linux重新分配地址空间即可。

使用 ascii-xfr 传输 rz 程序

最近继续折腾一些嵌入式设备,需要通过 UART 传输一些文件。一般来说直接使用 rz/sz 即可,但不幸的是 rz applet 并没有编译进这个设备的 busybox。同时由于一些蛋疼的原因,我们也不能重新烧写设备的 rootfs 镜像或者是从网络安装,那么就只能自己想办法解决咯……

基本思路是自己静态编译一份 rz 程序,然后从串口发送给嵌入式设备,然后再利用这个 rz 接收 sz。然后就能双向发送文件了。

设备上至少需要有cat命令和base64 -d。如果没有base64可以试试openssl base64 -d。如果还是没有那这篇文章的方法就不适用于你了。另外在设备上最好还要有一个 gzip 之类的压缩程序,可以显著缩短初次传输时间,以及一个 checksum 程序用于检查。我这里用了xzmd5sum

在主机上你需要有ascii-xfr程序。

编译 rz

你需要有一个能用的工具链,我的设备是 AArch64,直接使用了源里的 gcc。

1
2
3
4
5
6
7
8
# 下载代码
wget 'https://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz'
# 解压
tar xaf lrzsz-0.12.20.tar.gz
cd lrzsz-0.12.20
# 静态编译
CFLAGS='-Oz -static' CC=aarch64-linux-gnu-gcc ./configure --target=arm64-linux
make

如果你有对应设备的工具链也可以动态编译,这样编译出来的文件会更小。

使用 ascii-xfr 发送 rz

我这里使用picocom连接设备,其他程序比如minicomscreen请自行查阅手册寻找使用方法。

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
26
27
28
# 接上文
cp src/lrz rz
# 进一步裁剪文件体积
aarch64-linux-gnu-strip --strip-all rz
# 计算 checksum 备用
md5sum rz
ee96d7186db0f5240040c183636a8c9d
# 压缩
xz -9 rz
# 编码成 BASE64
base64 rz.xz > rz.xz.64
# 连接设备,记得使用你自己设备的波特率
picocom -b 1500000 -s 'ascii-xfr -sn -c 1' /dev/ttyUSB0
# 在设备中准备接收
wimpy_board$ cat > rz.xz.64
# 按 Ctrl-A Ctrl-S,然后输入要发送的文件的文件名
*** file: rz.xz.64
# 等待字符滚完,然后按 回车 + Ctrl-D 退出 cat
# 传输速度是 1000Bps,我最终需要传输 420 多 KB,需要 7 分钟。
# 传输完毕后在设备上还原可执行文件
wimpy_board$ base64 -d rz.xz.64 > rz.xz
wimpy_board$ xz -d rz.xz
wimpy_board$ chmod +x rz
# 最后比较一下 md5 值,并确认可以正常运行
wimpy_board$ md5sum rz
ee96d7186db0f5240040c183636a8c9d
wimpy_board$ ./rz
# 连按 5 次 Ctrl-X 退出

使用 rz 接收 sz

有经验的朋友到这里可以直接右上角退出了,不过我还是记录一下做个备忘。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 按 Ctrl-A Ctrl-X 退出 picocom,然后再重新连接。
# 不带 -s 参数时 picocom 默认使用本机的 sz 发送文件。
picocom -b 1500000 /dev/ttyUSB0
wimpy_board$ ./rz
waiting to receive.**
# 按 Ctrl-A Ctrl-S,然后输入要发送的文件的文件名
*** file: src/lsz
$ sz -vv src/lsz
Sending: lsz
Bytes Sent:1173536 BPS:144649

Transfer complete

*** exit status: 0 ***

折腾 RISC-V 单片机 Part1

SparkFun RED-V

大约半年前在 SparkFun 上买了一块 RED-V 开发板。基本算是 HiFive1 Rev B 的克隆,比 Rev B 便宜一些,同样使用 SiFive 的 FE310-G002 处理器。SiFive 的 MCU 自带一套 SDK,不过要搭配指定的 IDE 才好用,作为有洁癖的 Linux 用户这当然是不行的,所以就有了这次的折腾。

准备工作

我一开始是打算用 SDK 的代码,不过看了一圈感觉这样和玩 Arduino 也没区别了,失去了折腾的意义,所以决定放弃 SDK 直接用汇编艹寄存器。
这里是需要准备的文档和工具:

  • SparkFun RED-V Schematic: 这是板子的电路图,用来看板子上的接口都具体连接到 MCU 的哪个针脚。
  • Freedom E310-G002 Datasheet/Manual: 这两份文件可以从 SiFive 的网站上下载到,包含几乎所有重要信息。
  • Clang: 编译器。为啥不用 GCC?因为我不想单独折腾一份 GCC 的工具链。Clang 既可以编译出 x86 程序又可以编译出 RISC-V 程序,从软件源里装好就可以直接用了。
  • LLD: LLVM Linker。这下也不用配置 RISC-V 的 binutils 了
  • OpenOCD: 负责和板子通信,烧录程序,调试等。

三份 PDF 文档需要自己下载,而其他三个程序应该能直接用包管理装。

Rclone 同步 OneDrive for Business 共享

使用 OneDrive for Business 的 WebDAV 接口访问,无需登录。先去浏览器访问你拿到的分享链接,地址栏应该会变成如下形式:

https://[YOUR-DOMAIN]-my.sharepoint.com/personal/[YOUR-EMAIL]/_layouts/15/onedrive.aspx?[一堆别的东西]

然后打开 F12 找到一个叫 FedAuth 的 Cookie:

FedAuth=77u/......

然后用命令行在 rclone 里添加一个 WebDAV 的远程地址。语法是这样的:

rclone config create <name> <type> <key>=<val> <key>=<val> ...

具体到这里就是:

rclone config create <随便> webdav 'url=https://[YOUR-DOMAIN].sharepoint.com/personal/[YOUR-EMAIL]/Documents' 'headers=Cookie,FedAuth=77u/...'

细节请根据浏览器里的信息自己调节,如果设置无误就可以在 Rclone 里查看文件了:

rclone lsd '<你之前填的>:'

几个注意事项:

  • 暂不清楚这个 Cookie 的有效期是多长,如果 Cookie 失效的话自然就不能访问了。
  • 限速是存在的,如果 sync 的时候进度不动并且网络没流量通过,那大概是被限了。rclone 自己的速度计在速度为 0 的时候不会立即归零,而是 5MB,4MB,3MB... 这样慢慢下去,非常反直觉。限速时间还挺长的,暂时没有发现好办法能绕过。
  • 暂不清楚是不是所有的分享链接都可以用这种方式访问,可能需要组织管理员开启 WebDAV 功能?

LTO-5 磁带机折腾入门

LTO-5 Cartridge
最近在 eBay 上捡了一台 HP 的 LTO-5 磁带机,型号是 BRSLA-0903-DC,这次就把折腾过程简单记录一下。
LTO 磁带机本体一般都是标准的 5.25 寸光驱位大小,接口类型一般是 Fiber Channel 或者是 SAS 加上供电用的 Molex 4Pin。
不管哪种接口你都需要一张对应的 HBA 卡插在 PCI-E 槽里,以及对应的光纤线或者是 SAS 线把磁带机接到卡上。
如果机箱带光驱位,SAS 的磁带机可以直接放在机箱里,FC 的应该就不行了,因为我还没找到接口朝内部的 FC HBA 卡。