IPsec 配置备忘 Part7 - 证书 II

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

接 Part2 与 Part6。尝试折腾一下除了“以证书 DN 作为 id”以外的证书使用姿势,如果有错误或者与本文解释相冲突的情况欢迎在评论指出。

IKEv2 证书认证

在 IKEv2 里,一方需要认证另一方基本只需要两样信息IDAUTH。ID 就是之前配置文件里反复出现的那个,AUTH 一般是使用证书私钥对某些数据的签名,具体细节请参考 RFC。证书则是把两者关联了起来:如果对方给出的 AUTH 能通过证书验证,那么对方就是这份证书所表示的那个人,同时这份证书又是颁发给 ID 的,那么对方就是 ID。

验证者要取得对方的证书有几种方式:

  • 管理员可以直接把证书塞进验证者的/etc目录里
  • 被验证者可以自己把证书发送给验证者(send_cert = always参数)
  • 验证者可以向被验证者请求证书(send_certreq = yes参数)。当然被验证者也可以选择不发送证书(send_cert = never参数),只是验证会失败就是了。

另外如果验证者既不询问证书(send_certreq = no),被验证者也不主动发送证书(send_cert = ifasked),验证一样会失败。

strongSwan 在尝试匹配 ID 和证书的时候会检查 Subject DN 和 SubjectAltName (SAN)。我们之前一直在使用 Subject DN,而 SAN 则允许我们使用域名甚至 IP 作为 ID。另外,虽然我一直称呼“域名”或是“IP”,但是实际上只要 SAN 和 ID 匹配即可,这个“域名”到底是不是我们的并没有关系。(当然只有自签才能签出这种证书)

IPsec 配置备忘 Part6 - Android 客户端

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

接 Part4,终于要开始准备搭一个能用的 VPN 服务器了。另外,如果你要拿这个配置去翻墙请自便,但是不对实际效果做任何保证,本文只考虑传统的 VPN 使用场景。

基本上,服务端的配置和 Part4 中的一致,这里着重介绍如何配置客户端。配置使用 Play Store 上的 strongSwan客户端,版本为 2.3.1。

服务器配置

首先,这个客户端似乎还不支持 ed25519 证书,因此我们需要改为使用 ecdsa 证书。完整的证书生成操作请看 Part2,在生成私钥时指定--key-type ecdsa即可。现在假设你已经生成好了所有 6 个文件:ca-key.pem,ca-cert.pem,client-key.pem,client-cert.pem,server-key.pem,server-cert.pem

另外,这次我们会在服务器上配置 NAT,所以不再需要手动在服务端配置一个 IP 了。假设服务端eth0接口的公网 IP 是2000::1。首先将ca-cert.pem,server-key.pem,server-cert.pem三个文件移动到服务器上正确的地方。然后编写配置文件,同样的,这里只注释和 Part4 中不同的地方。

server.conf
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
29
30
31
32
33
34
35
36
37
38
connections {
android-connection {
version = 2
# 服务器的地址。根据官方文档,服务器内核版本需要大于等于 5.8
# 才能支持 Android 客户端使用 IPv6 地址连接
local_addrs = 2000::1
# 接受客户端来自任何地方
remote_addrs = %any
proposals = aes256gcm128-sha512-x25519
# 只分配 IPv4 的虚拟 IP
pools = ip4pool
local {
# 请按照实际情况修改 id
id = CN=server common name
auth = pubkey
}
remote {
id = %any
auth = pubkey
}
children {
child_sa {
# 允许客户端将去往所有目的地的流量发送给服务端
local_ts = 0.0.0.0/0
remote_ts = dynamic
mode = tunnel
esp_proposals = aes256gcm128-sha512-x25519
}
}
}
}

pools {
# 只保留 IPv4 池
ip4pool {
addrs = 10.10.10.100-10.10.10.150
}
}

配置完毕后systemctl restart strongswan

客户端配置

在客户端上,我决定创建一个可以直接导入的 Profile 文件,避免手工输入一大堆地址(要记得我在用 IPv6)。首先需要把 client-key.pem 和 client-cert.pem 合并成一个文件,注意 bash 本身是不支持多行命令和注释穿插写的,在执行的时候需要手动移除注释:

1
2
3
4
5
6
7
8
9
10
11
certtool \
--load-privkey client-key.pem \
--load-certificate client-cert.pem \
# 名称随意
--p12-name "Key Cert Bundle" \
# 空密码
--empty-password \
# 合并成 PKCS12 格式
--to-p12 \
# 需要指定 3des-pkcs12,否则 Android 系统无法正确导入
--pkcs-cipher 3des-pkcs12 > client-p12bundle.pem

新生成的文件是client-p12bundle.pem。然后我们参照 strongSwan 的文档创建可以直接导入应用的 Profile 文件。当然你也可以手动导入证书再手动配置 Profile。

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
29
30
31
32
33
34
35
36
37
jq -n \
# 生成一个随机的 UUID
--arg uuid `uuidgen -r` \
# Profile 的名称,可以随意写
--arg name "My server"\
# 认证类型
--arg type "ikev2-cert"\
# 需要手动指定 remote id,否则服务器的地址将被当作 id,导致认证失败
# 当然你也可以在创建证书的时候就把服务器地址写在证书里,避免手工指定 DN
# 注意:id 和服务器地址和证书有复杂的检验关系,填写不当容易造成各种奇怪的
# 身份验证错误。
--arg remoteid "CN=server common name"\
# 服务器的地址,我这里使用 2000::1 代替了实际地址,使用 IPv4 和域名也是可以的。
--arg addr "2000::1"\
# 嵌入服务器证书,注意这里我直接嵌了服务器本身的证书。嵌 CA 证书应该也是
# 可行的,但是我没试。
--arg servercert "`sed '/-----/d' server-cert.pem`"\
# 嵌入客户端私钥和证书
--arg localbundle "`sed '/-----/d' client-p12bundle.pem`"\
'{
uuid:$uuid,
name:$name,
type:$type,
remote:{
id:$remoteid,
addr:$addr,
cert:$servercert
},
local: {
p12:$localbundle
},
"ipv6-transport": true
}' > profile.sswan
# 根据官方文档,服务器内核版本需要大于等于 5.8 才能支持客户端使用 IPv6 地址
# 连接。同时需要设定 ipv6-transport 为 true。如果你使用 IPv4 则不需要此设置。
# 另外这里没有指定 local.id,根据文档,在没有指定 local.id 的情况下,客户端程序
# 会自动使用客户端证书的 DN 作为 id

最后将生成的profile.sswan文件拷贝到手机上并导入即可。然后试一下能否成功建立连接。

NAT 配置

然后这样配置完了,虽然能连上服务器,但是依然不能访问网络,我们还需要在服务器上配置一下 NAT。一般是一条防火墙的masquerade规则。这里只简单把配置放出来给自己做个备忘,不做细讲:

nftables.conf
1
2
3
4
5
6
7
8
9
10
table ip nat {
chain prerouting {
type nat hook prerouting priority 0;
}

chain postrouting {
type nat hook postrouting priority 100;
ip saddr 10.10.10.0/24 meta oifname eth0 masquerade
}
}

IPsec 配置备忘 Part4 - Virtual IP

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

第四篇主要讲一下怎么给客户端下发内网 IP ~
Part1 传送门Part2 传送门Part3 传送门

Virtual IP (VIP)

接 Part3,有了 Tunnel 模式以后我们实际使用的 IP 地址就不用受制于机器的实际 IP 了。但是手动给每个客户端手动分配一个地址显然是不切实际的。于是我们可以使用 Virtual IP 功能自动向连入的客户端分配一个内网 IP,就像 DHCP 或者 SLAAC 那样。

场景配置

与之前完全对称的配置不同,使用 Virtual IP 时需要区分服务端和客户端。先在服务端配置将要分配的 IP,然后由客户端发起连接,服务端就会将配置好的 IP 分发出去。我使用 HostA 作为服务端,HostB 作为客户端。HostA 将会给 HostB 分配 IPv4 与 IPv6 各一个。使用的 Virtual IP 段是fd01::100-fd01::20010.10.10.100-10.10.10.150

hosta$ ip -br addr
eth1         UP             fd00::1/64 fd01::1/128 10.10.10.1/32

hostb$ ip -br addr
eth1         UP             fd00::2/64

和 Part3 相比,HostA 这里有一些与之前不同的地方,一是内部 IP 全部放在了 eth1 上(而不是 lo 上);二是内部 IP 的前缀长度都是最大值;三是增加了一个 IPv4 的内部 IP,用于和分配的 IPv4 Virtual IP 通信。同时 HostB 也不再手工分配fd01开头的内部 IP 了,将由 strongSwan 自动配置。

当连接建立后,我们应该能看到在 HostB 的 eth1 上出现两个新的,自动分配的 IP。且分配到的 IPv4 地址与 10.10.10.1 之间的通信是加密的,分配到的 IPv6 地址与 fd01::1 之间的通信是加密的。

[娱乐向] Samsung 980 Pro RAID 性能测试

三星的新 SSD 980 Pro 已经发售一段时间了,前两天看到 Amazon 上 1TB 有货,赶紧下单两条。今天到货,于是装机测一波速度。打算用来做系统盘,所以自然就是用来组 RAID-0 咯。于是用 fio 分别测试了一下 btrfs 和 mdadm 组 RAID 的性能。测试完全不严谨,参数是用脸滚键盘滚出来的,放出来仅供各位一乐,为什么是娱乐向你看数据就知道了。同时拉上了打酱油的 960 Evo(我现在的系统盘),以及完全是搞笑用的/dev/shm

场景 连续读取(MiB/s) 连续写入(MiB/s) 4K 随机读取(kIOPS) 4K 随机写入(kIOPS)
980 Pro 单盘 EXT4 6370 4725 330 125
980 Pro 单盘 BTRFS 6264 2720 137 63.7
980 Pro mdadm RAID-0 EXT4 12186 9426 298 115
980 Pro BTRFS RAID0 5937 3932 133 63.3
/dev/shm 6290 5541 792 571
960 Evo 单盘 XFS 2963 410 199 31.3

Emmmm, mdadm RAID0 比内存快……这很合理……以及 btrfs 你的 RAID 性能还能更烂一点吗?

IPsec 配置备忘 Part3 - Tunnel 模式

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

第三篇简单介绍一下 IPsec 的 Tunnel 模式,没看过前两篇的快去看~
Part1 传送门Part2 传送门

Tunnel 模式简介

Tunnel mode header layout 前两篇中我们使用的都是 Transport 模式,但是实际使用中,更常用的是 Tunnel 模式。Transport 模式只加密四层及以上数据,而不修改 IP 头,原始的 IP 头将会原样传输。这意味着我们只能进行点对点传输,因为只有一个 IP 头,我们无法告知对方服务器我们实际要访问的地址。Tunnel 模式则是连原始的 IP 头也一起加密,然后再在前端添加一个新的 IP 头,这样服务器在收到数据包后,可以解密并读取内部的 IP 头,再转发给实际的目标服务器。

IPsec 配置备忘 Part2 - 证书

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

作为系列的第二篇文章,讲解基本的证书原理和配置方法。没看过第一部分的快去看~
传送门:IPsec 配置备忘 Part1

证书认证基础

我们在 Part1 中看到,PSK 认证的基本思路是使用一个只有通信双方才知道的暗号,如果能确认对方确实知道这个暗号,那么认证就成功了。证书认证的思路非常不同:假设 A 需要向 B 证明自己的身份,同时 A 知道 B 信任 C,那么 A 可以向 C 索取一份“介绍信”,当 B 询问 A 的身份时,A 可以向 B 展示这份 C 出具的“介绍信”,如果 B 能够确认这份“介绍信”确实是由 C 出具的,那么认证就成功了。注意这个认证是单向的,假设 A 也信任 C,那么 B 也可以通过向 C 索取“介绍信”来向 A 证明自己的身份。在 PKI 体系中,A 和 B 持有各自的“私钥”,C 作为 Certificate Authority (CA) 向 A/B 颁发证书(即“介绍信”)。同时,CA 也会向自己颁发一份证书并分发给 A/B,A/B 使用 CA 的证书来确认 B/A 出示的证书确实为 C 所颁发。