分类: Linux & homelab

  • 虚拟机检测绕过和nvme性能优化的libvirt配置

    虚拟机检测绕过和nvme性能优化的libvirt配置

    免责声明:我只是为了在自建的云游戏串流虚拟机上进行远程游戏,用虚拟机是因为All-in-boom宿主机还要跑别的东西。请勿用于非法用途,当然对于非法用途的人也早就知道这些了。

    参考自:https://github.com/zhaodice/qemu-anti-detection ,但这个配置会极大影响直通nvme硬盘的4k多线程性能,会从700MB/s跌倒20MB/s,导致游戏加载非常慢。因此研究了一些不影响通过检测的优化,使其恢复到200~300MB/s左右,不再成为瓶颈。

    以下是xml配置文件关键段落:

    <domain type='kvm' id='62' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
      ... 略 ...
      <features>
        <acpi/>
        <apic/>
        <kvm>
          <hidden state='on'/>
        </kvm>
        <vmport state='off'/>
        <smm state='on'/>
        <ioapic driver='kvm'/>
      </features>
      <cpu mode='host-passthrough' check='none' migratable='off'/>
      <clock offset='localtime'>
        <timer name='rtc' tickpolicy='catchup'/>
        <timer name='pit' tickpolicy='delay'/>
        <timer name='hpet' present='no'/>
        <timer name='kvmclock' present='no'/>
      </clock>
      
      <devices>
        ... 略 ...
        <memballoon model='none'/>
      </devices>
      
      <qemu:commandline>
        <qemu:arg value='-smbios'/>
        ... 略(请参考最上面的链接) ...
    
        <qemu:arg value='-cpu'/>
        <qemu:arg value='host,family=6,model=167,stepping=1,l3-cache=on,model_id=Intel(R) Xeon(R) E-2378 CPU @ 2.60GHz,vmware-cpuid-freq=false,enforce=false,host-phys-bits=true,hypervisor=off,+x2apic,hv-time,hv-relaxed,hv-vapic,hv-spinlocks=0x1fff,hv-vendor-id=GenuineIntel,tsc-frequency=2600000000'/>
      </qemu:commandline>
    </domain>

    NVME硬盘4k多线程性能差主要是因为时钟源问题,为通过检测我们无法使用常用的虚拟机高性能时钟源,导致中断性能问题。(是的,pcie直通并非一定没有性能损耗)

    其中最为关键的是qemu:arg中的-cpu段落,family=6,model=167,stepping=1,l3-cache=on,model_id=Intel(R) Xeon(R) E-2378 CPU @ 2.60GHz根据实际修改。经过反复测试,必须使用这种方式(libvirt原生配置不完全),同时不能加入migratable=no以打开+invtsc,哪怕加入更多参数修正也会有cpu feature细微差异,导致检测不过。但我们可以设置tsc-frequency=2600000000,强行使用tsc,数值为你的CPU基频(我这里是2.6GHz),睿频不影响。另外这里依然保留了一些hv特性,这对于开启了 Hyper-V 功能(如 VBS/WSL2)的物理机也是存在的,对于Win11机器很常见。

  • UCG Fiber 主路由器 + OpenWrt 透明代理 + 高可用 方案和评测(对比ROS)

    UCG Fiber 主路由器 + OpenWrt 透明代理 + 高可用 方案和评测(对比ROS)

    背景和需求

    直连流量尽量通过主路由直连,同时内网所有设备透明代理。为了代理性能和方便管理,OpenWrt 可以跑在再服务器的虚拟机中,因此有必要在其离线时实现自动 failover,将内网降级为正常全直连网络。

    过去用 RouterOS (ROS) 主路由(CCR2004) + OpenWrt 网关 + VRRP 实现,不过 ROS 的问题是设备管理不直观,不像 Unifi 的系统一样有着很好的大屏,以及 DPI、IDS/IPS 等功能。同时 ROS 没有 PPPoE 硬件 offload 支持,在这一点上甚至不如几百块的家用无线路由器。

    因此我购入了一台 Unifi Cloud Gateway Fiber(UCG Fiber),三个10G口(2光1电)+ 4个2.5G电口,本文将探讨将其代替 ROS 作为高可用魔法(代理)家用网络环境的主路由器的方案和局限性。

    TLDR:Unifi与ROS优缺点对比

    (这里的优缺点仅针对本场景)

    Unifi UCG Fiber
    优点:

    • 界面美观,对客户端识别更智能(比如常见手机型号),DPI 功能还能分析流量种类和记录客户端的网络活动历史
    • PPPoE hardware offload 支持,千兆宽带满速下载时 CPU 占用没什么变化,据其他人测试能完全跑满 10G PPPoE
    • 小体积、高颜值,非常静音的主动散热,还有个小屏幕能看实时网速

    缺点:

    • 灵活性很低,不支持 VRRP(就算是Unifi的机架式设备也只能自己跟自己组HA),高可用代理方案配置麻烦,目前没找到可用的方法实现高可用的IPv6代理,只能强制让代理都走 IPv4
    • 自带功能有些很不完善:
      • IPv6 支持烂,任何情况下 IPv6 只会走主要 WAN,哪怕 IPv6 地址下发的都是备用 WAN 的 v6,且主要 WAN 都没启用 v6
      • 策略路由(PBR)不支持 IPv6
      • 策略路由只能指定出口 WAN,没法指定下一跳到内网机器。而且 Fallback 功能残废,只有在 WAN 接口 Down 了时才会生效,哪怕系统都检测到该 WAN 不可用了也不会切换
      • Wireguard Server + 双 WAN 支持差,无法在备用 WAN 上接受连接(回程路由有 bug),除非主要 WAN 不可用
    • 其他一些问题:端口转发的 NAT Loopback(在内网通过映射到公网的地址访问内部服务时)无法硬件加速,只能跑到1~3GBps,跑不满内网带宽
    • 开启 Smart Queue QoS 后 PPPoE offload 失效,只能跑到 600Mbps 不到,且无法只在一个方向上开启(比如只在上行开启 QoS)
    • 客户端管理功能很强,但没有一个地方能看当前所有的网络连接(Conntrack)和实时速度(类似ROS的IP -> Firewall -> Connections)

    RouterOS

    • 优点:灵活性很高,可以直接跟 OpenWrt 组VRRP,且 VRRP 支持脚本,ROS 的脚本可以便利的修改所有网络设置,可以实现各种自动化功能
    • 缺点1:对于管理客户端流量不直观,Connections 里虽然能看到一个内网 IP 连了一个外网 IP,但还得去 DHCP 分配里查这个内网 IP 的主机名或MAC地址,可能还得上网查一下这个 MAC 地址的 vendor,才能确定这个客户端是谁;对于外网 IP 也没法跟 DNS 查询记录里的域名做关联,很不直观。
    • 缺点2:MikroTik 家的硬路由性能有限,在我的 CCR2004 上 PPPoE 硬跑倒是能跑满千兆宽带下行,但一开双向的 Cake QoS 就不行了(哪怕开了fasttrack),不过可以只开上行的 QoS,下行带宽够大也不需要 QoS 了

    UCG Fiber 硬件分析

    通过dmesg和拆解图分析得到内部拓扑:

    SoC 为高通 IPQ9574,拥有 NSS / PPE 硬件加速功能,CPU 为4x A73 @ 2.2GHz,不算太强,还是比较依赖硬件加速的。

    拓扑方面,两个 10G 光口直连 SoC,所有电口(4×2.5G + 10G)连接到内部的 RTL8372 交换芯片,共享一个 10G 链路到 SoC。由于有硬件加速,光口和电口的交换不会占用CPU,但电口侧确实存在带宽瓶颈(虽然一般遇不到)。

    硬件方面,内存物理大小共4G,OS中可用3G(包括Unifi宣传的也是3G),大概是有1G被SoC其他组件占用,也可能是ECC。

    另外UCG Fiber还有一个加速度传感器用来检测摆放姿态,可以根据姿态调整小屏幕的显示方向。(有时间搞这些能不能把 IPv6 搞完善点啊喂)

    方案概述

    为实现 Unifi 主路由 + OpenWrt 全局透明代理 + 高可用,首先 Unifi 作为主路由器,连接光猫进行 PPPoE 拨号,OpenWrt 连接到 Unifi 的 LAN 上作为客户端(类似二级路由,但不同的是终端设备不去连接 OpenWrt),然后利用 Unifi 的双 WAN 主备切换的功能,让 OpenWrt 再作为 Unifi 的一个 WAN,即OpenWrt WAN Loopback,具体如下:

    • 将 Unifi 的 WAN1 (使用DHCP,IPv6关闭)连接 OpenWrt 的 LAN ,OpenWrt 的 WAN 再连接到 Unifi 的 LAN
    • 将 Unifi 的 WAN2 接光猫拨号,开启IPv6,并把内网的 IPv6 前缀来源也设置为 WAN2
    • Unifi 上设置 WAN1(OpenWrt)为 Primary,WAN2(PPPoE)为 Backup,模式为Failover Only
    • 26/02/15 补充:Unifi 上需要给 WAN1(OpenWrt)手动设置 DNS 服务器为 OpenWrt IP,不能勾选“Auto DNS”,不然Unifi 会偷偷给你塞一个1.1.1.1
    • Unifi 上设置策略路由:
      • 1. 目标 Region 为 China 的都走 WAN2(不用勾 Kill Switch,没啥用且会跟下面的DNS hijack有奇妙的冲突);
      • 2. 来自 OpenWrt 的流量都走 WAN2(避免循环,勾上Kill Switch)
    • OpenWrt 上和标准的路由+代理设置基本相同,WAN 为 DHCP,连接 Unifi 内网。然后要将 WAN 和 WAN6 接口高级设置中的“自动获取 DNS 服务器”禁用,并填入运营商的 DNS 地址,避免循环
    • 效果:正常情况下,客户端的 DNS 请求先到 Unifi 的 DNS 服务器上(对于 DPI 功能有帮助),然后走 WAN1 -> OpenWrt 的无污染 DNS,解析得到国外地址继续走 OpenWrt 做代理(OpenWrt 再通过 Unifi LAN -> PPPoE 连接代理服务器),国内地址直接走 PPPoE 发出。一旦 OpenWrt 挂掉,Unifi 检测到 WAN1 不通,会自动把全部路由和 DNS 都切换到 PPPoE,实现自动降级直连
    • (可选)此时 Unifi 上可以再设置一个 DNS hijack,让不遵守 DHCP 下发的 DNS 服务器的设备的所有 UDP 53 端口流量都强制发到 Unifi DNS 服务器:增加 DNAT 规则,匹配来源 IP 非 OpenWrt,目标 IP 非 Unifi,目标 UDP 53,将目标 IP 改写为 Unifi 的 IP

    IPv6 与 WireGuard Server 问题

    按上述方案配置后,你会发现两个问题:

    IPv6 不通:哪怕客户端已经具有了来自 PPPoE 的 v6 地址,但 v6 网络就是不通。这里来到了 Unifi 最逆天的地方了:除非主 WAN 断开,不然在任何情况下都试图让 IPv6 走主 WAN,哪怕主 WAN 都没配 IPv6,导致网络不通。

    Unifi 上运行的 WireGuard Server 不通:哪怕 WireGuard Server 上设置了监听的是 WAN2 (PPPoE),只要主 WAN 还在,所有回包都会走主 WAN,导致外界的客户端连不上。最新的Unifi OS 5.0.12 + Network 10.1.84版本已经修复此问题

    ==> 对于Unifi OS 5.0.12 + Network 10.1.84或更新的版本(2026年2月):

    已经无WireGuard的问题,仅有IPv6问题,而IPv6修复也可以通过Unifi内置的静态路由来实现,不再需要SSH+脚本魔改:

    如上图:新建Policy,选择Route,类型选择静态,接口选择WAN2(真正连运营商的WAN),地址填写2000::/3(全球公网v6单播地址)

    ==> 对于早于Unifi OS 5.0.12 + Network 10.1.84的版本,若在Unifi上使用WireGuard Server,需要通过脚本修复WireGuard Server不通的问题,下方提供了旧版方案的脚本,能一并修复IPv6问题和WireGuard Server问题

    点击展开旧版方案+脚本

    需要 SSH 进去并设置自启脚本来修正:

    编辑 /data/internet_as_backup_wan_fix.sh ,内容为(按需调整IFACE和WG_PORT):

    #!/bin/sh
    
    # ================= Configuration =================
    # backup WAN Interface (real Internet, e.g. PPPoE to ISP)
    IFACE="ppp1"
    # Routing Table ID for backup WAN (Usually 202 for WAN2)
    TABLE="202"
    # WireGuard Server Listen Port
    WG_PORT="16384"
    # Log Tag for syslog
    LOG_TAG="UniFi_Network_Fixer"
    # =================================================
    
    # Function to clean up rules on exit or restart
    cleanup() {
        # Remove IPv6 default route
        ip -6 route del default dev "$IFACE" metric 1 2>/dev/null
    
        # Remove Policy Routing rule based on Source Port
        ip rule del sport "$WG_PORT" lookup "$TABLE" 2>/dev/null
    
        # Remove Force-SNAT rule from NAT table
        iptables -t nat -D POSTROUTING -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE 2>/dev/null
    }
    
    # Run cleanup on start to ensure a clean slate
    cleanup
    
    logger -t "$LOG_TAG" "Starting network fix script..."
    
    while true; do
        # Check if the interface exists
        if ip link show "$IFACE" > /dev/null 2>&1; then
    
            # -----------------------------------------------------
            # Task 1: Fix IPv6 Direct Access
            # Problem: Unifi doesn't add a default IPv6 route for Secondary WAN.
            # Fix: Manually add a default route to Main Table via ppp1.
            # -----------------------------------------------------
            HAS_V6_ROUTE=$(ip -6 route show default dev "$IFACE" metric 1)
            if [ -z "$HAS_V6_ROUTE" ]; then
                ip -6 route add default dev "$IFACE" metric 1
                logger -t "$LOG_TAG" "IPv6: Added default route via $IFACE"
            fi
    
            # -----------------------------------------------------
            # Task 2: Fix WireGuard VPN Server on Secondary WAN
            # Problem: Local UDP traffic uses Primary WAN gateway & source IP.
            # Fix A: Policy Routing based on Source Port (Directs traffic to WAN2 Table)
            # -----------------------------------------------------
            if ! ip rule show | grep -q "sport $WG_PORT lookup $TABLE"; then
                # Priority 98 ensures it runs before Unifi's default rules
                ip rule add sport "$WG_PORT" lookup "$TABLE" priority 98
                ip route flush cache
                logger -t "$LOG_TAG" "VPN: Added Policy Routing for Source Port $WG_PORT"
            fi
    
            # -----------------------------------------------------
            # Fix B: Force SNAT (Masquerade)
            # Problem: Source IP might be internal (e.g., 192.168.x.x) even if routed correctly.
            # Fix: Force NAT on egress to ensure Source IP matches the Public IP.
            # -----------------------------------------------------
            if ! iptables -t nat -C POSTROUTING -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE 2>/dev/null; then
                # Insert at top (1) to override any conflicting rules
                iptables -t nat -I POSTROUTING 1 -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE
                logger -t "$LOG_TAG" "VPN: Added Force-SNAT rule for port $WG_PORT"
            fi
    
        fi
    
        # Check every 30 seconds to handle re-dials or IP changes
        sleep 30
    done
    

    加上执行权限:chmod +x /data/internet_as_backup_wan_fix.sh

    然后使用 crontab -e 并添加以下内容,设置开机自启:

    @reboot /data/internet_as_backup_wan_fix.sh > /dev/null 2>&1 &

    注意:每次底层 Unifi OS 升级后需要重新添加 crontab,因此建议关闭自动更新

    为什么一定要用这种方案?

    1. 为什么不能 OpenWrt 直接做二级网关(LAN 侧)? Unifi 不支持 VRRP。如果把 OpenWrt 设为 DHCP 下发的默认网关,一旦 OpenWrt 挂了,Unifi 无法自动把网关切回自己,全家断网。
    2. 为什么不能 OpenWrt 做旁路网关配合 PBR? Unifi 的策略路由(Traffic Routes)只能选 WAN 接口作为出口,不能指定 LAN 侧的某个 IP(OpenWrt)作为下一跳。
    3. 为什么必须让 OpenWrt 充当 Primary WAN?
      如果反过来让 PPPoE 作为 Primary WAN,OpenWrt 作为 Backup WAN,则无法利用双 WAN 的 Failover 功能来应对 OpenWrt 下线的情况,通过策略路由则会有以下问题:
      • 策略路由的 Fallback 功能残废:需要设置策略路由让海外流量走 Backup WAN,但问题是策略路由的 Fallback 与双 WAN Fallback 机制不通,后者会用 ping 检测是否真正可用,而前者只会在相应接口 Down 掉时才会被禁用,导致就算 OpenWrt 挂掉或死机,但接口还在,海外可直连的流量依然无法 Fallback
      • DNS 配置麻烦:默认的 DNS 行为会直接走 PPPoE,造成 DNS 无法抗污染。而若指定走 OpenWrt 的话又难以 Failover,需要 SSH 进去 Unifi 来配置 dnsmasq 为 strict-order 模式,然后使用主-备 DNS 服务器,也很麻烦

    附录:或许还有一种更简单但更不优雅的方案,就是 OpenWrt 或者其他运行代理插件的主机再跑一个 WireGuard Server,然后在 Unifi 上用 VPN Client 连接并用策略路由进行分流,但对UCG孱弱的CPU是个挑战,尤其是千兆梯子已经普遍的今天。

    另外还有网友提到,组一个 OSPF 并向 Unifi 广播需要代理的网段也是一种办法。

  • OpenWrt上AdGuardHome前置配置的一些小坑

    OpenWrt上AdGuardHome前置配置的一些小坑

    为了配合一些上网插件并达到最好的过滤效果,需要将AdGuardHome前置于OpenWrt自带的dnsmasq:

    [设备] -> [AdGuardHome 53端口] -> [dnsmasq 54端口] -> 一些插件 -> 多种DNS服务器

    AdGuardHome在这里作为第一级DNS服务器,运行在标准53端口上,直接接受客户端连接。然后其上游为OpenWrt的自带dnsmasq的DNS服务器,这里需要将其端口改为端口54以避免冲突。之后一些上网插件会自动将dnsmasq的上游设置为它的一些程序,最终连接到大陆或外网的DNS。

    这一套似乎没什么问题,但其实有一些坑:

    坑1: DHCP v4 不下发DNS服务器配置

    OpenWrt dnsmasq的DNS服务若运行在未53端口上时,其DHCP v4 服务就不会默认发送DNS选项。导致部分支持IPv6的设备依然可以通过IPv6连接DNS,表现正常,但仅支持IPv4的设备就会无法上网。

    解法很简单,需要在OpenWrt -> 网络 -> lan -> DHCP 服务器 -> 高级设置 处,手动强制加入一个DHCP选项来下发DNS服务器配置:6,<路由器IP>

    坑2: 在一些插件内,勾选DNS重定向会绕过AdGuardHome

    如果你勾选了这个选择,那DNS请求会被强制直接转达到dnsmasq的地址,也就是54端口上,导致AdGuardHome被绕过了。那如果你仍然需要类似的功能呢?可以在 OpenWrt -> 网络 -> 防火墙 -> 端口转发中手动创建一条规则

    具体如下:

    # /etc/config/firewall
    config redirect 'dns_int'
    	option name 'Intercept-DNS'
    	option family 'any'
    	option proto 'tcp udp'
    	option src 'lan'
    	option src_dport '53'
    	option target 'DNAT'

  • Unraid 7.2+ WebUI美化主题和自定义CSS插件

    Unraid 7.2+ WebUI美化主题和自定义CSS插件

    由于 Unraid 升级到 7.2+ 版本后,原本常用的 “Theme Engine” 插件已不再兼容,为了继续自定义 WebUI 的样式,我开发了一个轻量级的 CSS 注入插件,并在此基础上发布了一套我个人使用的 “Modernization” 主题。

    1. Custom WebUI CSS 插件

    这是一个专门为 Unraid 7.2+ 设计的轻量级插件。我的需求很简单:将自定义 CSS 代码注入到网页中。既然旧插件无法使用,我便编写了这个替代方案。

    主要功能:

    • 全局 CSS 注入: 将 CSS 代码自动加载到每个页面的 <head> 中。
    • 深色主题附加CSS: 可输入仅在 Unraid 主题设置为 ‘black’ 时加载的额外CSS,用于方便在黑/白主题间兼容和切换。
    • 额外资源文件: 支持从 Flash 到 Web 目录同步额外的静态资源(如背景图片等),可在CSS中引用。

    项目地址: https://github.com/WuSiYu/unraid-custom-css

    Unraid论坛地址:https://forums.unraid.net/topic/195276-plugin-simple-custom-webui-css-plugin-for-unraid-72

    注意: 本插件仅在 Unraid 7.2+ 上测试通过。如果你使用的是 7.1.4 及以下版本,建议继续使用 Theme Engine。

    2. Modernization Theme

    配合上述插件,我整理了个人使用的 CSS 样式,命名为 Modernization Theme。

    设计特点:

    • 现代化外观: 重新设计了 Dashboard 和 Main 等核心页面的视觉体验。
    • 按钮风格: 改善了Unraid原本比较丑的圆角渐变边框设计,现在具有完美的圆角,并在支持的浏览器上还有渐变文字。
    • 黑/白主题兼容: 适配 Unraid 原生的 White 和 Black 两种基础主题。
    • 稳健性: 克制了 CSS 的修改范围,尽量避免破坏第三方插件的显示效果。

    3. 安装与使用指南

    第一步:安装插件

    进入 Unraid 的 PLUGINS -> Install Plugin 页面,输入以下 URL 进行安装:

    https://raw.githubusercontent.com/WuSiYu/unraid-custom-css/refs/heads/master/custom.css.plg

    (正在等待CA应用商店审核,不出意外等之后也可以直接在上面装)

    第二步:输入主题CSS

    1. 安装完成后,前往 SETTINGS -> Custom WebUI CSS
    2. 打开下方链接,复制其中的 CSS 代码: https://github.com/WuSiYu/unraid-custom-css/blob/master/example.css
    3. 将代码粘贴到插件的配置框中,点击应用即可。

    本主题有意限制了自定义样式的生效范围,以最大程度避免破坏第三方插件的样式。但如果你在使用过程中依然了遇到任何第三方插件的兼容性问题,欢迎反馈。

  • 杂谈:libvirt/qemu Windows游戏VM的一些优化配置

    杂谈:libvirt/qemu Windows游戏VM的一些优化配置

    一些libvirt配置备忘,针对Windows guest,虚拟机游戏场景

    虚拟化功能选项

    取自cockpit-machine生成的Windows 10 guest配置

      <features>
        <acpi/>
        <apic/>
        <hyperv mode='custom'>
          <relaxed state='on'/>
          <vapic state='on'/>
          <spinlocks state='on' retries='8191'/>
          <vpindex state='on'/>
          <runtime state='on'/>
          <synic state='on'/>
          <stimer state='on'/>
          <frequencies state='on'/>
          <tlbflush state='on'/>
          <ipi state='on'/>
          <evmcs state='on'/>
          <avic state='on'/>
        </hyperv>
        <vmport state='off'/>
      </features>

    CPU feature设置

    在CPU节加入一些神奇的选项可以提高CPU-Z跑分,在我的E-2378的单核从450提升到500,物理机为540左右

      <cpu mode='host-passthrough' check='none' migratable='on'>
        <topology sockets='1' dies='1' clusters='1' cores='8' threads='2'/> <!--以实际情况为准-->
        <feature policy='require' name='topoext'/>
        <feature policy='disable' name='vmx'/>
        <feature policy='disable' name='svm'/>
        <feature policy='require' name='apic'/>
        <feature policy='require' name='hypervisor'/>
        <feature policy='require' name='invtsc'/>
      </cpu>

    超线程和 CPU Pinning

    首先使用lscpu -e查看宿主机超线程CPU序号拓扑,一般是前半都是t0(每个物理核的0号线程),后半都是t1,然后将同一物理核心的宿主机CPU序号分配到相邻的vcpu上,似乎这样在Windows虚拟机中顺序才是正确的(有待进一步验证):

      <vcpu placement='static'>16</vcpu>
      <cputune>
        <vcpupin vcpu='0' cpuset='0'/>
        <vcpupin vcpu='1' cpuset='8'/>
        <vcpupin vcpu='2' cpuset='1'/>
        <vcpupin vcpu='3' cpuset='9'/>
        <vcpupin vcpu='4' cpuset='2'/>
        <vcpupin vcpu='5' cpuset='10'/>
        <vcpupin vcpu='6' cpuset='3'/>
        <vcpupin vcpu='7' cpuset='11'/>
        <vcpupin vcpu='8' cpuset='4'/>
        <vcpupin vcpu='9' cpuset='12'/>
        <vcpupin vcpu='10' cpuset='5'/>
        <vcpupin vcpu='11' cpuset='13'/>
        <vcpupin vcpu='12' cpuset='6'/>
        <vcpupin vcpu='13' cpuset='14'/>
        <vcpupin vcpu='14' cpuset='7'/>
        <vcpupin vcpu='15' cpuset='15'/>
      </cputune>

    宿主机优化(可选)

    tuned profile选择virtual-host

    qemu自动用透明内存大页,也可以显示用手动内存大页,但不足时虚拟机无法启动

  • Fedora + libvirt 下在宿主关机时安全关闭虚拟机

    Fedora + libvirt 下在宿主关机时安全关闭虚拟机

    很简单的一个问题,但过程比较难绷,所以特此记录

    为了能方便的既跑虚拟机,又跑Docker容器,我经常使用Fedora Server来作为宿主系统,配合红帽官方的Cockpit面板进行管理,其对虚拟机(基于libvirt/qemu/kvm)和容器(官方只支持Podman)的支持尚可。

    但其在关机时虚拟机会直接被强制停止,并不安全。我们希望在直接对宿主机进行关机或重启时,其能够像PVE、EXSi等虚拟化系统一样发起并等待虚拟机的安全关机。

    首先这个功能libvirt是提供了的,由libvirt-guests.service实现,但不知为何在Fedora并没有被默认启用。

    进一步的,我们发现其配置文件/etc/sysconfig/libvirt-guests从某个版本起被移除了(你还能搜到关于这件事的相关讨论,暴躁用户 vs 倔强maintainer),更不方便我们配置了,因此首先恢复其内容:

    # URIs to check for running guests
    # example: URIS='default xen:/// vbox+tcp://host/system lxc:///'
    #URIS=default
    
    # action taken on host boot
    # - start   all guests which were running on shutdown are started on boot
    #           regardless on their autostart settings                                 
    # - ignore  libvirt-guests init script won't start any guest on boot, however,     
    #           guests marked as autostart will still be automatically started by      
    #           libvirtd                                                               
    #ON_BOOT=start                                                                     
    
    # Number of seconds to wait between each guest start. Set to 0 to allow            
    # parallel startup.
    #START_DELAY=0
    
    # action taken on host shutdown
    # - suspend   all running guests are suspended using virsh managedsave
    # - shutdown  all running guests are asked to shutdown. Please be careful with
    #             this settings since there is no way to distinguish between a
    #             guest which is stuck or ignores shutdown requests and a guest
    #             which just needs a long time to shutdown. When setting
    #             ON_SHUTDOWN=shutdown, you must also set SHUTDOWN_TIMEOUT to a
    #             value suitable for your guests.
    ON_SHUTDOWN=shutdown
    
    # If set to non-zero, shutdown will suspend guests concurrently. Number of
    # guests on shutdown at any time will not exceed number set in this variable.
    #PARALLEL_SHUTDOWN=0
    
    # Number of seconds we're willing to wait for a guest to shut down. If parallel
    # shutdown is enabled, this timeout applies as a timeout for shutting down all
    # guests on a single URI defined in the variable URIS. If this is 0, then there
    # is no time out (use with caution, as guests might not respond to a shutdown
    # request). The default value is 300 seconds (5 minutes).
    #SHUTDOWN_TIMEOUT=300
    
    # If non-zero, try to bypass the file system cache when saving and
    # restoring guests, even though this may give slower operation for
    # some file systems.
    #BYPASS_CACHE=0

    注意我这里设置的是ON_SHUTDOWN=shutdown,因为对于有PCIe设备直通的虚拟机suspend可能无法使用。

    然后启用libvirt-guests.service服务:

    sudo systemctl enable --now libvirt-guests

    然后在虚拟机关机时(或libvirt-guests服务关闭时)正在运行的虚拟机应当能正常关机,并且这些虚拟机会在宿主机下次启动时自动启动(恢复状态)。

    这里不得不吐槽一下红帽经常搞一些breaking change,之前升级就被Network UPS Tools (NUT)的服务配置坑过一次

  • 群晖ddrescue与暂时禁用USB外接硬盘自动挂载

    群晖ddrescue与暂时禁用USB外接硬盘自动挂载

    来自每天一个没用的小知识

    对一个挂掉SATA固态做数据恢复,症状大概是可以读,但一旦进行写入就会掉盘。在对数据做镜像时,直接通过USB3.0转SATA线插在群晖NAS机器上,并将镜像保存在其中的大容量硬盘上是个方便的做法。

    首先安装ddrescue,添加SynoCommunity软件源,并安装SynoCli Disk Tools软件包即可。(如果你的网不是很好,也可以从这里手动下载:https://synocommunity.com/package/synocli-disk

    接下来,由于群晖会自动挂载USB外接硬盘等设备,会对其产生写入,这是我们不希望发生的。群晖没有选项可以关闭自动挂载功能,但经过一些尝试发现,我们可以通过暂停(SIGSTOP)/usr/syno/sbin/hotplugd进程的方法暂时阻止其自动挂载的行为。

    登入SSH后执行:

    sudo pkill -STOP -f /usr/syno/sbin/hotplugd

    注意不要直接将其杀死,否则其会自动重启。若再去阻止其自启就太过麻烦了,我们只需要暂时用SIGSTOP信号暂停其执行,让其失去功能即可。之后使用sudo pkill -CONT ...或直接重启机器后便可恢复。

    而后便可以接入硬盘并使用ddrescue进行数据恢复。

  • 白群晖之 在“不受支持”的机型上启用btrfs和快照功能

    白群晖之 在“不受支持”的机型上启用btrfs和快照功能

    400多块买了个便宜的单盘位DS118白群晖当容灾备份机器用,到手发现这个机型居然不支持创建btrfs的存储空间,这就十分难绷了,毕竟数据校验、快照等功能都用不了。

    然后发现,尽管最近一代的新品在售的机器都支持btrfs了,但直到2020年群晖NAS的很多低端型号都不支持btrfs,其中20、19、18系列就包括:DS420j,DS220j,DS120j,DS419slim,DS119j,DS418j,DS218play,DS218j,DS118

    尽管这些机型的配置确实不高,但btrfs其实也不是会费太多资源的东西,DS118这种机型完全能够支持,毕竟同为RTD1296 CPU的DS218或者同为1G内存的机器DS216+都是支持btrfs的,这么搞大概只是为了差别对待。

    实际上,群晖在这些型号上用的系统都是差不多的,底层其实都带有btrfs功能,只是在Web UI上被隐藏了,这些功能的差异被定义在了/etc.defaults/synoinfo.conf中,因此只需要打开SSH功能,连接后执行sudo vim /etc.defaults/synoinfo.conf,加入以下内容即可:

    support_btrfs="yes"
    support_btrfs_dedupe="yes"
    support_iscsi_btrfs_lun="yes"
    support_share_snapshot="yes"
    support_share_quota="yes"
    support_share_user_quota="yes"
    support_dr_snap="yes"
    support_dr_replica="yes"
    max_btrfs_snapshots="65536"
    max_snapshot_per_lun="256"
    max_snapshots_per_share="1024"
    max_dr_replica="64"
    max_sdr_replica="64"

    若不会使用vim,也可以使用winscp等软件。此时btrfs存储池便可以被创建和使用,但若想使用群晖的快照套件还需要继续操作。

    快照功能

    DSM 7的快照功能需要使用套件SnapshotReplication和其依赖ReplicationService,然而这两个套件默认无法在不支持btrfs的机型上安装,但我们可以通过暂时修改机型的方式来强行安装,然后修改软件包信息。

    1. 首先找到一个相似架构且支持btrfs的机器,比如对于我的DS118,我找到了DS218,然后在 群晖官网 -> DS218下载中心 -> DSM 套件 中找到SnapshotReplication和ReplicationService的安装包,上传到home目录中。

    2. 编辑/etc.defaults/synoinfo.conf,修改synobios和unique字段中的机型,例如synobios=”ds118″和unique=”synology_rtd1296_ds118″中的“ds118”改为“ds218”,然后保存。注意:修改机型后,一定要在稍后改回来,期间不要重启,否则系统会无法启动。

    3. 安装软件包,在终端中执行(.spk文件的文件名按实际修改):

    sudo synopkg install ReplicationService-ds218-1.3.0-0409.spk
    sudo synopkg start ReplicationService
    sudo synopkg install SnapshotReplication-ds218-7.4.5-1698.spk
    sudo synopkg start SnapshotReplication

    4. 重要:恢复synoinfo.conf中的机型修改

    5. 此时套件虽然已经安装,但机型不匹配,会提示套件损坏,需要我们修改已安装软件包的信息,依次修改下面两个文件:

    /var/packages/ReplicationService/INFO
    /var/packages/SnapshotReplication/INFO

    找到类似model="synology_rtd1296_ds218"的行,修改为机器的真实型号,然后重启,即可正常使用SnapshotReplication进行快照。

    疑难解答

    如果你这样做后依然无法创建快照,请尝试以下命令(homes为共享文件夹名称,可修改),观察快照能否被创建,或是否有报错:

    sudo sh -x synosnapschedtask.sh local share homes

    番外

    玩过黑群晖的都知道,除了SA6400机型用的Linux内核版本是5.10.55(2021年发布)外,其他机型都还在使用上古4.4.302内核(2016年发布),然而在4.4老内核下,btrfs的压缩功能并不支持zstd算法,因此99%的白群晖NAS的文件系统压缩功能都是快速但效果较差的lzo,包括那些同样上万的机型(不100%确定,群晖毕竟对btrfs进行了不少魔改,也有可能backport了zstd的功能,其他机型的朋友可以看下synoinfo.conf是否包含btrfs_default_compression="zstd"的配置)。

    对于黑群晖而言,也有多了一个用SA6400机型的理由。

  • 解决群晖Photos iOS客户端备份大视频时报错“备份已暂停-空间不足”

    解决群晖Photos iOS客户端备份大视频时报错“备份已暂停-空间不足”

    2024/07/24 UPDATE: 最新版的群晖Photos APP似乎已经修复/缓解了此问题

    这是由于iOS设备(比如iPhone)的空间不足,使App无法转存较大文件导致的。在iCloud中照片/视频大小较大时,尽管在设置中可能会看到还有大量的剩余空间,但实际上是一种“已占用但可被释放”的状态。卸载一些大App或删除一些照片/视频能够解决,但如果不想这样做的话,可以使用下方的方法强制iOS去释放一些空间(iPhone 13 Pro测试可用):

    手机打开 相机,切换到视频,开启“ProRes HDR”录制,此时会提示一个很短的“最长时间”和“正在释放资源”。等待一段时间后,当“最长时间”上升到5分钟左右时,群晖Photos即可正常工作。

  • 备忘:OpenWrt在旁路由下Ping通但TCP不通的解决办法

    备忘:OpenWrt在旁路由下Ping通但TCP不通的解决办法

    这里的背景是OpenWRT作为旁路由(aka. 旁路网关,单臂路由,透明网关等),没有一个太准确的叫法,具体的指另一台“主路由”连接公网并作NAT,OpenWrt不启用NAT,用户设备的上行流量先经过OpenWrt旁路由转发到“主路由”,下行时流量直接通过由主路由发送到用户设备,不经过OpenWrt旁路由。主要优点在于下行带宽不会受OpenWrt性能的影响,且OpenWrt设备故障或维护时,可手动(或配置自动)切换到主路由。(OpenWRT旁路由可以是单臂路由,也可以有另一根独立的线路连接到主路由,避免带宽限制,如我之前的文章)

    但由于上行和下行的通路不同,仅有部分流量会经过OpenWrt,会导致TCP的conntrack出现问题。

    具体表现是:已经正确设置了路由,且能用户设备能ping通外网,但对外进行TCP不通,若在用户设备上抓包分析会看到:

    • (从用户设备,客户端)发送SYN
    • 收到(来自公网设备,服务器)SYN + ACK
    • 发送ACK
    • 发送通信内容(payload)
    • (未收到回应ACK)
    • 重复收到SYN + ACK(多次)
    • (重传)发送通信内容(payload)
    • (还是没有回应ACK)

    不难看出,这是由于客户端发送的ACK在中途被丢弃了,使得虽然客户端认为TCP连接已经建立,但在服务端看来没有,因此客户端发送的payload不会被确认,而服务器则会重传SYN + ACK,继续等待客户端的ACK。

    这种现象和OpenWrt的conntrack有关,由于服务器回应的SYN + ACK没有经过OpenWrt,使得OpenWrt没有正确追踪TCP连接。在一些特定情况下,OpenWrt认为客户端后续的数据包是“无效数据包”,并丢弃,包括客户端发送的ACK。

    在OpenWrt中解决的方法也很简单,首先在“防火墙”页面中关闭“丢弃无效数据包”

    其次,若OpenWrt通过独立线路(在防火墙的WAN Zone)连接主路由,则在一些特定情况下(比如因为一些组网需求,对一些内网网段开启了masquerade),还要打开WAN Zone – 编辑 – 连接追踪设置 – 允许“无效”流量,如下图:

    具体conntrack的工作方式和该问题的出现条件,有待进一步验证

  • RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址

    RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址

    Update:较新的RouterOS v7.11已经带有了此功能(未测试),或许无需再使用该脚本

    摘要:这篇文章给出了一种对于Router OS的更“优雅“的WireGuard Peer Endpoint(动态)域名自动刷新脚本,提出了一种在配置项的COMMENT中填写变量(比如域名)的方法,而不是hardcode在脚本中。这种思想也可用于其他对于RouterOS功能扩展的脚本。

    背景:这个需求来源于Router OS的一个bug或者毛病,即当配置WireGuard Peer的连接地址(Endpoint)时,你虽然可以使用域名,但其仅会在启动时被解析,之后如果域名的IP发生变化,是不回重新解析的。这就导致如果你使用DDNS域名作为Endpoint,那在其IP变化后连接就会丢失,不会自动恢复,直到你重启接口或者机器。

    解决上述问题的方式就是编写一个Router OS的脚本来解析域名,并将其IP更新到WireGuard Peer的Endpoint项中,然后将这个脚本添加在Schedule中,定时自动执行。由于Endpoint项会被脚本填写的IP覆盖,因此要在别的地方记录其域名。这个脚本目前网络上流传的版本如下:

    # 网络上流传的版本,灵活性较差
    :local wgInterface
    :local wgPeerDns
    
    :set wgInterface "wireguard1"
    :set wgPeerDns "xxxxxxx.xxx-ddns.net"
    
    :if ([interface wireguard peers get number=[find interface="$wgInterface"] value-name=endpoint-address] != [resolve $wgPeerDns]) do={
      interface wireguard peers set number=[find interface="$wgInterface"] endpoint-address=[/resolve $wgPeerDns]
    }

    可以看出其WireGuard的接口和域名都hardcode(写死)在了脚本中,并且其默认一个接口只有一个Peer,无法适用于一个接口有多个Peer的情况。虽然我们很容易就能对其进行修改让其支持,但仍是繁琐的,比如要根据pubkey或设置特定的Comment用于区分不同Peer,并在脚本中对照配置项进行填写,带来了维护上的繁琐。

    方法:既然这类脚本的目的是对Router OS本身的功能进行扩展,那么对于配置时最自然的方式,就是可以在配置项原有的界面中一并填写相关的变量(比如此处的域名),虽然Router OS中我们不能给配置项再添加一个字段,但我们其实可以充分利用Comment字段来存放我们的变量,有点像加在linux命令前的环境变量。并且Comment本身就和每个配置项直接关联,不需要我们再去维护其对应关系。

    例如,我们就可以在Comment里写上DOMAIN_ENDPOINT=xxxxxxx.xxx-ddns.net来表示域名,像下面这样:

    相应的这种更优雅一些的脚本如下:

    /interface/wireguard/peers
    
    :local CommentPrefix "DOMAIN_ENDPOINT="
    
    :foreach i in=[find where comment~"^$CommentPrefix.*\$"] do={
        :local comment [get number=$i comment]
        :local ip [:resolve [:pick $comment [:len $CommentPrefix] [:len $comment]]]
        
        :if ([get number=$i endpoint-address] != $ip) do={
            set number=$i endpoint-address=$ip
        }
    }

    由于所有配置相关的信息都在Comment中填写了,哪怕之后还需要修改Peer的地址或者添加新的Peer和接口,也不需要对脚本进行任何更新。同时,如果Comment中没有“DOMAIN_ENDPOINT=”这样的字符串,脚本不回对其做任何操作;比起直接将整个Comment区域作为特定的变量值,这样不会有任何副作用,并且对于维护时该变量的含义是“自解释”的。

    结论:这是对于WireGuard Peer动态域名的一个实用的脚本,但对于这种“通过Comment区的特定语法来配合一个通用的脚本来对Router OS的功能进行扩展”的思想,这只是一个简单的例子。实际上,还可以实现如:兼容与普通Comment一起使用,可以填写多个变量等,就“交给读者作为练习”了。

  • 解决更新Fedora 37后新版NUT(Network UPS Tools)无法连接UPS设备的问题

    解决更新Fedora 37后新版NUT(Network UPS Tools)无法连接UPS设备的问题

    时效性提醒:本文首次编写发布于3 年前。

    在Fedora老版本上配置了NUT,每次开机后NUT服务均能正常与UPS连接;但在将系统更新至Fedora 37后,开机后NUT服务提示无法连接UPS,会周期性在终端广播报错,如果通过upsc指令查询UPS状态就会报错,如题图所示。

    这个原因是因为在新版的nut软件包中,对于nut-driver服务的systemd配置文件发生了变化,旧的nut-driver.service被移除了[1],取而代之的是nut-driver-enumerator.service,后者再去启动nut-driver@<ups_name>.service(其中<ups_name>为配置文件中的UPS名称)[2]

    由于原本配置时enable的是nut-driver.service,现已不存在,而更新后nut-driver-enumerator.service并未被enable,因此nut-driver服务没有启动,导致nut-server、upsd和upsc等组件无法连接UPS。

    解决方法也很简单,执行以下命令把nut-driver-enumerator.service启用即可:

    systemctl enable --now nut-driver-enumerator.service

    不得不说这个更新有点坑,但这也是系统跨版本更新时没办法的事情。

    [1] https://packages.fedoraproject.org/pkgs/nut/nut/fedora-36.html
    [2] https://packages.fedoraproject.org/pkgs/nut/nut/fedora-37.html

  • Mikrotik CCR2004-1G-2XS-PCIe 简单带宽测试

    Mikrotik CCR2004-1G-2XS-PCIe 简单带宽测试

    时效性提醒:本文首次编写发布于4 年前。

    CCR2004-1G-2XS-PCIe是一个有趣的设备,准确的讲它是一个“PCIe网卡形式的路由器”,与普通路由器不同的是,它除了挡板上的两个SFP28 25G网口和一个RJ45千兆管理口这些“物理网口”,其还通过PCIe 3.0 x8有着4个直连主机的25G虚拟网络接口,在主机看来,这相当于4个固定直连到路由器上的“普通”网络接口;而与一些Smart NIC不同的是,CCR2004-1G-2XS-PCIe并不能为主机提供任何offload功能,RDMA和sr-iov等功能应该也是不支持的,它也没有内置交换机芯片,所有从主机到物理网口的数据都需要CCR2004-1G-2XS-PCIe的CPU来转发,换句话说,如果你只是把它当网卡用,那它还不如普通网卡,它的合理用途应当是组成一个服务器和路由器的All-in-one方案。不过无论是作为“集成路由器”还是“普通网卡”的用途都值得我们实践测试一下,这便是这篇文章接下来的部分。

    由于没有25G环境,本文在10G内网下测试,CCR2004-1G-2XS-PCIe通过SFP+ DAC连接至CRS305 10G交换机上,交换机上的另一台机器使用x540双万兆电口网卡。CCR2004-1G-2XS-PCIe被安装在一台Core i9-10850k迷你主机(以下简称为host)的PCIe 3.0 x16槽上(CPU直连通道),系统为Fedora Workstation 36。

    在host上的一些关于此设备的信息节选:

    # lspci
    01:00.0 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
    01:00.1 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
    01:00.2 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
    01:00.3 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
    
    # dmesg
    [    1.971577] atl1c 0000:01:00.0: enabling device (0000 -> 0002)
    [    1.994014] atl1c 0000:01:00.1: enabling device (0000 -> 0002)
    [    2.014003] atl1c 0000:01:00.2: enabling device (0000 -> 0002)
    [    2.034983] atl1c 0000:01:00.3: enabling device (0000 -> 0002)
    [    2.057479] atl1c 0000:01:00.1 enp1s0f1: renamed from eth1
    [    2.073979] atl1c 0000:01:00.0 enp1s0f0: renamed from eth0
    [    2.090921] atl1c 0000:01:00.2 enp1s0f2: renamed from eth2
    [    2.105991] atl1c 0000:01:00.3 enp1s0f3: renamed from eth3
    [    8.700933] atl1c 0000:01:00.0: atl1c: enp1s0f0 NIC Link is Up<25000 Mbps Full Duplex>
    [    8.703098] atl1c 0000:01:00.1: atl1c: enp1s0f1 NIC Link is Up<25000 Mbps Full Duplex>
    [    8.705370] atl1c 0000:01:00.2: atl1c: enp1s0f2 NIC Link is Up<25000 Mbps Full Duplex>
    [    8.707589] atl1c 0000:01:00.3: atl1c: enp1s0f3 NIC Link is Up<25000 Mbps Full Duplex>
    
    # ethtool enp1s0f0
    Settings for enp1s0f0:
    	Supported ports: [ TP ]
    	Supported link modes:   10baseT/Half 10baseT/Full
    	                        100baseT/Half 100baseT/Full
    	Supported pause frame use: No
    	Supports auto-negotiation: Yes
    	Supported FEC modes: Not reported
    	Advertised link modes:  Not reported
    	Advertised pause frame use: No
    	Advertised auto-negotiation: Yes
    	Advertised FEC modes: Not reported
    	Speed: 25000Mb/s
    	Duplex: Full
    	Auto-negotiation: on
    	Port: Twisted Pair
    	PHYAD: 0
    	Transceiver: internal
    	MDI-X: Unknown
    	Supports Wake-on: pg
    	Wake-on: d
            Current message level: 0x0000003f (63)
                                   drv probe link timer ifdown ifup
    	Link detected: yes
    
    # ethtool -i enp1s0f0
    driver: atl1c
    version: 5.17.9-300.fc36.x86_64
    firmware-version:
    expansion-rom-version:
    bus-info: 0000:01:00.0
    supports-statistics: no
    supports-test: no
    supports-eeprom-access: no
    supports-register-dump: yes
    supports-priv-flags: no

    可以看出其在Linux下使用atl1c驱动,连接速度和功能正常,但lspci下型号识别是有问题的。

    交换性能测试(“软交换机”模式)

    这个模式下所有接口都在一个bridge中,在host上只启用第一个虚拟网口,一个SFP28口接入房间交换机。remote为房间交换机上的主机。测试线路的带宽上限是10G,这里使用iperf3进行测试,也就是大包测试,RouterOS的Fast Forward为默认的开启状态。

    测试描述带宽CPU占用
    #1单向host -> remote9.39 Gbits/sec15%
    #2单向remote -> host9.41 Gbits/sec30%

    表格中的CPU占用指CCR2004-1G-2XS-PCIe的,默认RouterOS是开启bridge的Fast Forward,手动关闭后的结果没有明显变化。

    路由+NAT性能测试(“集成路由器”模式)

    这个模式下,模拟常见的家用路由器环境,但WAN侧使用DHCP,通过一个SFP28接口接入房间交换机,从上级路由器获得地址,remote主机也在房间交换机上。其余接口在一个bridge中,为LAN侧。像普通家用路由器一样,LAN侧有自己的地址段,打开DHCP服务器,开启WAN上的NAT masquerade。

    首先是开启Fast Path时的性能:

    测试描述带宽CPU占用
    #1单向host -> remote9.35 Gbits/sec21%
    #2单向remote -> host9.37 Gbits/sec31%

    然后是关闭Fast Path时的性能:

    测试描述带宽CPU占用
    #1单向host -> remote9.37 Gbits/sec28%
    #2单向remote -> host2.80 Gbits/sec29%

    可以看到在关闭Fast Path后,remote -> host,也就是WAN to LAN方向的性能不佳。虽然此时CPU占用率并未达到100%,但一共4个核心中,仅有一个核心使用率接近100%,估计是有单核瓶颈,此时的CPU占用情况如下:

  • MacBook的高速网卡(>1000Mbps)方案踩坑

    MacBook的高速网卡(>1000Mbps)方案踩坑

    时效性提醒:本文首次编写发布于4 年前。

    本文是MacBook超过千兆网络的连接(比如2.5G/5G/10G)方案的探索,我的设备是MacBook Pro 13,2020年,M1芯片,系统为macOS Monterey 12.4。其他MacBook也可参考,主要的坑在于macOS。

    首先是MacBook自带的网络方案:内置Wi-Fi,但目前MacBook的WiFi6仅为2×2,且不支持160M频宽,PHY速度只能到1200M,实测在中高端路由器下,实际速度最大也仅为800Mbps左右,无法超过千兆。

    工作:常见的2.5G USB有线网卡(RTL8156芯片)

    示意图

    目前市场上有很多2.5G USB网卡,通常都是RTL8156芯片,这种芯片在macOS下工作良好,开箱即用(免驱)

    实测速度(iperf3):TX:2.35Gbps,RX:2.35Gbps,双向TX+RX:2.26Gbps+2.26Gbps,能跑满2.5G。

    还测试了长时间跑满2.5G,网卡外壳仅为温热,未出现明显降速,效能挺不错的。

    不工作:QNA-UC5G1T等5G USB有线网卡(AQC111u芯片)

    QNAP QNA-UC5G1T

    这里的5G指5Gbps,而不是5GHz WiFi的无线网卡,这基本是USB 3.x gen1(5Gbps)的最快速度,也是目前市面上最快的USB协议网卡(不包括雷电),USB 3.x gen2的USB网卡还未出现。

    不幸的是,AQC111u的官方驱动仅支持“macOS Catalina 10.15 or older”,在较新的MacBook上至少都是BigSur(11.x)以后的版本,无法使用。

    在较新的macOS版本下,虽然QNA-UC5G1T可以被识别,但仅能工作在1Gbps下,实际使用体验和满大街的千兆USB网卡没区别,没有意义,也不够稳定,有时甚至会握手为100Mbps。

    同时这种网卡在其他系统下也不建议使用,实测在Windows和Linux下也只能达到3Gbps左右的速度,比2.5G网卡强不了多少,考虑到其价格,完全没有性价比。

    大概率不工作:雷电硬盘盒转接普通PCIe万兆网卡

    市面上有售雷电3的万兆网卡,但都价格昂贵(1000+),使用几百块的雷电m2硬盘盒+普通PCIe万兆网卡似乎是更有性价比的方案,但实际并不能工作。通过雷电m2硬盘盒+m2转pcie座+外置12v电源,MacBook是可以实际识别到PCIe设备,但都因为驱动问题无法使用。我尝试了AQC107和Intel x540两种网卡,均无法使用。

    对于普通AQC107 PCIe万兆网卡,macOS虽然有AQC107的驱动,但其是仅为Mac Mini的内置网卡服务的,对于ID不同的普通AQC107网卡,macOS会拒绝加载驱动,虽然有破解方案,但对于白苹果繁琐且不值得。

    对于Intel x540PCIe万兆网卡,根本没有驱动,无法识别。

    因此市售的成品雷电3的万兆网卡,或许是MacBook万兆的唯一方案了,但因不是很值得(笔记本用个2.5G也够用,10G不是刚需),我没有购买测试。

  • 2022年,对于爱快(iKuai)路由系统本身网络活动的简单抓包分析

    2022年,对于爱快(iKuai)路由系统本身网络活动的简单抓包分析

    时效性提醒:本文首次编写发布于4 年前。

    iKuai路由系统,一个基于Linux的国产路由系统,特点是带有DPI流控并且免费,有一定审计功能,目前在国内似乎是除OpenWrt外最常用的软路由系统。

    不过和部分其他的专用路由系统类似,iKuai本身相对封闭,不开放Linux shell,甚至rootfs也是加密的,在商业上这自然无可厚非,但iKuai系统在几年前曾被爆出有过劫持用户网络的DNS和HTTP请求用于广告盈利的行为,虽然据传言已被去除,但仍然令人担忧其“私货”。

    所以这次,我将iKuai路由系统作为二级路由,连接到RouterOS主路由上。RouterOS有着方便的防火墙配置和抓包功能,可以设置filter进行抓包并保存到文件,然后导入Wireshark中查看。

    所用iKuai系统为“免费版3.6.0 x64 Build202202101800 体验版”,与目前的3.5.4正式版在网络活动行为上应该区别不大。在iKuai中并未开启“爱快云”和SD-WAN功能,仅打开默认的自动更新,意味爱快自身着其除了“download.ikuai8.com”外,理应不去访问任何外网。

    截止2022.02,iKuai系统在“爱快云”页面有一个隐私政策文档的链接,但其只描述了爱快云的隐私政策,并未说明在不使用“爱快云”的情况下iKuai路由系统本身会上传哪些信息。

    DNS抓包

    截取DNS请求是用于发现其试图访问哪些域名的方便方法,本次首先禁止了iKuai对除了“download.ikuai8.com”和114.114.114.114 DNS外的任何连接,然后截取了其开机几十分钟内的所有DNS请求:

    经过整理,其查询的所有域名如下:

    NTP服务,正常行为:
    0.centos.pool.ntp.org
    1.centos.pool.ntp.org
    2.centos.pool.ntp.org
    ntp.aliyun.com
    
    软件更新,正常行为:
    download.ikuai8.com
    
    意义不明的名字,但IP与download.ikuai8.com相同:
    302.ikuai8.com
    
    爱快云:
    yun.ikuai8.com.w.kunlungr.com (CNAME自 yun.ikuai8.com)
    
    疑似使用情况上报,存在疑问(如:上传了哪些信息?):
    report.ikuai8.com.w.kunluncan.com (CNAME自 report.ikuai8.com)
    
    阿里云-日志服务SLS,存在疑问(如:上传了哪些信息?):
    alpha-cloud-log.cn-hangzhou.log.aliyuncs.com
    
    疑似阿里广告服务(友盟),存在疑问:
    secgw-na61-na62.wagbridge.alibaba.alibabacorp.com (CNAME自 umdc.aliapp.org)
    
    用途未知,存在疑问,对应IP都属于阿里的AS37963:
    as1.ikuai8.com
    as2.ikuai8.com
    dis.ikuai8.com
    pkgmanager.ikuai8.com
    
    江苏电信的IP,疑似用于宽带加速服务,存在疑问:
    fastgame.ikuai8.com
    
    可能用于网络检测:
    baidu.com
    qq.com

    注:以上为单次简单实验收集到的域名查询和个人的主观推测,不为其正确性负责,不做出任何评价。若官方或第三方能提供更多信息,欢迎在评论区留言。

    在上级路由中使用的规则如下(192.168.88.2为iKuai的IP):

    未完待续,等有空时准备进行一次全天抓包。