需求分析
手上有台 J4125 的机子:
- 4x 1Gbps RJ45(i211)
- 8G RAM
- 32G mSATA
- 1T SATA HDD
单纯的做软路由有点性能过剩,单纯的做 NAS 又浪费了网口。网络上有不少装 ESXi 跑虚拟机的教程,但我追求的是资源利用最大化,J4125 这小身板和 8G 的内存顶不住啊。所以我使用 Arch Linux 做宿主系统,在纯 QEMU 上运行 iKuai 路由,不涉及内核且能在 Linux 上运行的服务则用 LXC 进行隔离。
为什么选择 Arch Linux 做宿主系统:
- 更新激进,可以体验最新的特性。
- 拥有内容丰富的 Wiki 你所遇到的疑难杂症基本都能在这里面找到。
- 软件包丰富。
网络结构:
1
2
3
4
5
6
7
8
9
|
----------------------
| iKuai |LXC|
---|------|----|---|---------
| PCI | PCI |br-lan| Sys |
---|------|-------|------|---
| eth0 | eth1 | eth2 | eth3 |
---|------|-------|------|---
| WAN | LAN |
----------------------
|
eth3 不使用并启动 DHCP 客户端,防止虚拟机崩溃时无法进入系统,届时直接用此接口连接其他路由器即可。
安装 Arch Linux 并配置
下载官方的 Arch Linux 镜像,按 Wiki 中的教程安装。
所需的组件:linux linux-firmware base intel-ucode sudo grub efibootmg openssh
你也可以去以下镜像下载:
修改网卡名称并为 eth3 配置 DHCP:
Arch Linux 会默认将网卡识别并命名为 enp1s0
、enp2s0
、eno1
、enp4s0
,我们将其命名为 ethx
会更好辨认。创建并编辑以下文件:
/etc/systemd/network/10-eth0.link
1
2
3
4
5
6
|
[Match]
MACAddress=00:e2:69:27:da:a3
[Link]
Description=Ethernet 0
Name=eth0
|
/etc/systemd/network/11-eth1.link
1
2
3
4
5
6
|
[Match]
MACAddress=00:e2:69:27:da:a4
[Link]
Description=Ethernet 1
Name=eth1
|
/etc/systemd/network/12-eth2.link
1
2
3
4
5
6
|
[Match]
MACAddress=00:e2:69:27:da:a5
[Link]
Description=Ethernet 2
Name=eth2
|
/etc/systemd/network/13-eth3.link
1
2
3
4
5
6
|
[Match]
MACAddress=00:e2:69:27:da:a6
[Link]
Description=Ethernet 3
Name=eth3
|
/etc/systemd/network/23-eth3.network
1
2
3
4
5
|
[Match]
Name=eth3
[Network]
DHCP=yes
|
系统启动后应当使用以下指令启动三个服务:
1
2
3
|
sudo systemctl enable --now systemd-networkd
sudo systemctl enable --now systemd-resolved
sudo systemctl enable --now sshd # 启动 SSH 服务
|
准备虚拟机环境
创建网桥:
创建网桥 br-lan
并将 eth2
加入网桥
/etc/systemd/network/br-lan.netdev
1
2
3
4
|
[NetDev]
Name=br-lan
Kind=bridge
MACAddress=00:e2:69:27:da:a7
|
/etc/systemd/network/22-eth2.network
1
2
3
4
5
|
[Match]
Name=eth2
[Network]
Bridge=br-lan
|
br-lan
将从 ikuai 的 DHCP 服务获取 IP 地址,建议在 ikuai 中设置静态 IP 方便进入管理。
/etc/systemd/network/br-lan.network
1
2
3
4
5
|
[Match]
Name=br-lan
[Network]
DHCP=yes
|
需重启 systemd-networkd
: sudo systemctl restart systemd-networkd
安装 QEMU 和 OVMF :
直接使用包管理器安装
1
|
sudo pacman -S qemu-headless edk2-ovmf
|
启用 IOMMU:
修改 /etc/default/grub
在 GRUB_CMDLINE_LINUX_DEFAULT=
条目内添加 intel_iommu=on iommu=pt
。
修改完成后使用 sudo grub-mkconfig -o /boot/grub/grub.cfg
生成新配置文件。
使用以下脚本可以查看 IOMMU 分组:
1
2
3
4
5
6
7
|
#!/bin/bash
shopt -s nullglob
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done;
|
加载 virtio 内核模块:
编辑 /etc/modules-load.d/virtio-net.conf
1
2
3
|
virtio-net
virtio-pci
virtio
|
重启生效,加载这些模块后,在主机上执行 lsmod | grep virtio
不应返回空。
加载 vfio 内核模块:
编辑 /etc/modules-load.d/vfio-net.conf
1
2
3
4
5
|
vfio_iommu_type1
vfio-pci-core
vfio-pci
vfio
vfio_virqfd
|
网络相关设置
启用 IP 转发:
启用内核转发,顺便设置一下其他参数最大连接数。
编辑 /etc/sysctl.d/60-net.conf
1
2
3
4
5
6
7
8
9
10
|
net.ipv4.ip_forward = 1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
# 最大连接数
net.netfilter.nf_conntrack_max = 65535
# TCP fastopen
net.ipv4.tcp_fastopen = 3
# BBR
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr
|
sudo sysctl -p /etc/sysctl.d/60-net.conf
立即生效。
不确定配置文件中的注释对系统运行是否有影响,请在复制时自行清除。
创建虚拟机
创建磁盘:
1
|
qemu-img create -f raw ikuai.img 4G
|
首次安装: 通过 spice://hostname:5930
进入安装
1
2
3
4
5
6
7
8
9
|
qemu-system-x86_64 \
-enable-kvm \
-bios /usr/share/ovmf/x64/OVMF_CODE.fd \
-smp 4 -m 3456 \
-cdrom iKuai8_x64_3.5.11_Build202112031159.iso \
-hda ikuai.img \
-vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing \
-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 \
-chardev spicevmc,id=spicechannel0,name=vdagent
|
分离设备并进行首次运行设置:
从主机分离并 bind 到 vfio
1
2
3
|
echo "0000:01:00.0" > /sys/bus/pci/devices/0000\:01\:00.0/driver/unbind
echo "0000:02:00.0" > /sys/bus/pci/devices/0000\:02\:00.0/driver/unbind
echo "8086 1539" > /sys/bus/pci/drivers/vfio-pci/new_id
|
修改 ACL :
1
2
3
|
sudo mkdir -p /etc/qemu
sudo touch /etc/qemu/bridge.conf
sudo chown 0640 /etc/qemu/bridge.conf
|
修改 /etc/qemu/bridge.conf
:
启动虚拟机:
1
2
3
4
5
6
7
8
9
10
11
|
qemu-system-x86_64 \
-enable-kvm \
-bios /usr/share/ovmf/x64/OVMF_CODE.fd \
-smp 4 -m 2048 \
-device vfio-pci,host=01:00.0 \
-device vfio-pci,host=02:00.0 \
-net nic,model=virtio -net bridge,br=br-lan \
-hda ikuai.img \
-vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing \
-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 \
-chardev spicevmc,id=spicechannel0,name=vdagent
|
其中 -net nic,model=virtio -net bridge,br=br-lan
可以换成以下写法。
1
2
|
-netdev bridge,id=hn0,br=br-lan \
-device virtio-net-pci,netdev=hn0,id=nic0 \
|
设置开机自启:
需要软件包:gnu-netcat
/opt/ikuai/env
1
2
3
4
5
6
7
8
9
10
11
|
args="-enable-kvm \
-bios /usr/share/ovmf/x64/OVMF_CODE.fd \
-smp 4 -m 2048 \
-device vfio-pci,host=01:00.0 \
-device vfio-pci,host=02:00.0 \
-net nic,model=virtio -net bridge,br=br-lan \
-hda /opt/ikuai/ikuai.img -vga none \
-serial telnet:localhost:7000,server,nowait,nodelay \
-monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"
haltcmd="echo 'system_powerdown' | nc localhost 7100"
|
/opt/ikuai/vfiobind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#!/bin/bash
if [ ! -e "/dev/vfio/14" ];
then
if [ -e "/sys/bus/pci/devices/0000:01:00.0/driver/unbind" ];
then
echo "Unbind from system..."
echo "0000:01:00.0" > /sys/bus/pci/devices/0000\:01\:00.0/driver/unbind
echo "0000:02:00.0" > /sys/bus/pci/devices/0000\:02\:00.0/driver/unbind
echo "8086 1539" > /sys/bus/pci/drivers/vfio-pci/new_id
else
echo "Bind to vfio..."
echo "0000:01:00.0" > /sys/bus/pci/drivers/vfio-pci/bind
echo "0000:02:00.0" > /sys/bus/pci/drivers/vfio-pci/bind
fi
else
echo "Nothings to do."
fi
|
/etc/systemd/system/ikuai.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[Unit]
Description=iKuai virtual machine
[Service]
Group=root
User=root
Environment="haltcmd=kill -INT $MAINPID"
EnvironmentFile=/opt/ikuai/env
ExecStartPre=/opt/ikuai/vfiobind
ExecStart=/usr/bin/qemu-system-x86_64 -name ikuai $args
ExecStop=/usr/bin/bash -c ${haltcmd}
ExecStop=/usr/bin/bash -c 'while nc localhost 7100; do sleep 1; done'
[Install]
WantedBy=multi-user.target
|
sudo systemctl enable --now ikuai
共享磁盘设置
所需软件包:hdparm
磁盘测速:
sudo hdparm -Tt /dev/sda
设置磁盘休眠: 磁盘 sda
将在 10min 后休眠
sudo hdparm -B 127 -S 120 /dev/sda
持久化设置:
/etc/udev/rules.d/69-hdparm.rules
1
|
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sda", RUN+="/usr/bin/hdparm -B 127 -S 120 /dev/sda"
|
挂载磁盘:
创建挂载文件夹:sudo mkdir -p /mnt/share
手动挂载:sudo mount /dev/sda1 /mnt/share
自动挂载:修改 /etc/fstab
:
1
|
UUID=74e9771c-be8d-43aa-8355-f8f1b6141c3b /mnt/share btrfs rw,relatime,space_cache,subvolid=5,subvol=/ 0 0
|
SMB 共享
Arch Linux 自带 ksmbd
模块。但是我们仍需要手动编译 ksmbd-tools,所需软件包:base-devel
1
2
3
4
5
6
|
curl https://download.fastgit.org/cifsd-team/ksmbd-tools/releases/download/3.4.3/ksmbd-tools-3.4.3.tar.gz -o ksmbd-tools-3.4.3.tar.gz
tar -xzf ksmbd-tools-3.4.3.tar.gz
cd ksmbd-tools-3.4.3
./configure
make
sudo make install
|
配置:
1
2
3
4
|
sudo mkdir -p /etc/ksmbd
sudo touch /etc/ksmbd/smb.conf
sudo ksmbd.adduser -a $USER
sudo ksmbd.addshare -a share -o "writable = yes, path = /mnt/share"
|
启动测试:
加载模块:sudo modprobe ksmbd
启动:sudo ksmbd.mountd
关闭:sudo ksmbd.control -s
卸载模块:sudo rmmod ksmbd
开机自启:
/etc/systemd/system/ksmbd.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[Unit]
Description=ksmbd userspace daemon
Wants=network-online.target
After=network.target network-online.target
[Service]
Type=oneshot
User=root
Group=root
RemainAfterExit=yes
ExecStartPre=-/usr/local/sbin/modprobe ksmbd
ExecStart=/usr/local/sbin/ksmbd.mountd -s
ExecReload=/bin/sh -c '/usr/local/sbin/ksmbd.control -s && /usr/local/sbin/ksmbd.mountd -s'
ExecStop=/usr/local/sbin/ksmbd.control -s
[Install]
WantedBy=multi-user.target
|
sudo systemctl enable --now ksmbd
NFS 共享
所需软件包:nfs-utils
添加分享路径:
/etc/exports
若修改了配置文件需要执行 sudo exportfs -arv
使其生效。
启动:
sudo systemctl enable --now nfs-server
调优:
修改 /etc/nfs.conf
将线程数设置为 8 及以上:
重启服务:sudo systemctl restart nfs-server
torrent 下载服务
所需软件包:transmission-cli
覆写启动用户:
创建文件夹 sudo mkdir -p /etc/systemd/system/transmission.service.d/
,修改 /etc/systemd/system/transmission.service.d/$USER.conf
$USER
改为自己的用户名
1
2
3
|
[Service]
Group=$USER
User=$USER
|
sudo systemctl enable --now transmission
403: Forbidden 错误:
停止服务,编辑 ~/.config/transmission-daemon/settings.json
,向 rpc-whitelist
中添加白名单 IP 或将 rpc-whitelist-enabled
设置为 false
关闭白名单模式。随后重新启动服务即可。
原版界面过于简陋:
停止服务,使用 https://github.com/ronggang/transmission-web-control 项目中的 src/
替换 /usr/share/transmission/web/
随后重新启动服务即可。(注意文件权限)
设置 UDP 缓冲区:
编辑 /etc/sysctl.d/61-transmission.conf
1
2
|
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
|
sudo sysctl -p /etc/sysctl.d/61-transmission.conf
立即生效。
LXC 旁路由
所需软件包:lxc
1
2
|
sudo lxc-create -n clash -t download -- -d archlinux -a amd64 \
-r current --server mirrors.bfsu.edu.cn/lxc-images --no-validate
|
/var/lib/lxc/clash/config
1
2
3
4
5
6
|
lxc.mount.auto = proc:mixed sys:mixed cgroup:mixed
lxc.net.0.type = veth
lxc.net.0.link = br-lan
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:e2:69:27:da:a8
|
sudo systemctl enable --now lxc@clash