OpenWrt

2024/01/06

Tags: openwrt linux openclash kvm virt-install network

很久没折腾OpenWrt了, 囊中羞涩, 没有其他合适的设备, 这次是在KVM虚机中运行使用(ALL IN BOOM!)

先亮个当前的穷人版家庭网络拓扑图

穷人版家庭网络拓扑图

准备qcow2镜像

首先下载最新的镜像, 截止目前最新版为23.05.3, 我这里下载的是x86-64的镜像

wget https://mirror-03.infra.openwrt.org/releases/23.05.3/targets/x86/64/openwrt-23.05.3-x86-64-generic-ext4-combined.img.gz
# 解压
gunzip openwrt-23.05.3-x86-64-generic-ext4-combined.img.gz
# 这里因为我要作为KVM虚拟机的镜像, 所以转换为qcow2格式. 如果是在物理机上部署, 可以直接直接刷到U盘上.
qemu-img convert -f raw openwrt-23.05.3-x86-64-generic-ext4-combined.img -O qcow2 /var/lib/libvirt/images/openwrt.qcow2

运行虚机

我是用libvirt来管理qemu/kvm虚拟机, 如果没安装要先安装

apt install virt-manager qemu bridge-utils -y

我这里将镜像复制到了/var/lib/libvirt/disks/目录下

qemu-img create -f qcow2 -F qcow2 -b /var/lib/libvirt/images/openwrt.qcow2 /var/lib/libvirt/disks/openwrt.qcow2 1G

使用virt-install运行虚拟机, 这里网卡使用virtio类型并桥接到之前文档里创建的br0上, 选择virtio是因为性能最好, 可以达到10Gbps以上

# 运行, 这里网络指定的之前文章中创建的网桥网络br0
virt-install \
  --name openwrt \
  --memory 256 \
  --vcpus 1 \
  --network bridge=br0,model=virtio \
  --disk path=/var/lib/libvirt/disks/openwrt.qcow2,bus=ide \
  --import \
  --autostart \
  --osinfo detect=on,require=off \
  --noautoconsole

配置网络

连接console配置网络

virsh console openwrt

修改网络配置文件 /etc/config/network 只修改了lan配置和删除了br-lan网桥, 其他都是默认的, 因为我的使用场景比较简单, 虚拟机只有一个网卡, 直接使用eth0作为lan口连接器的物理网卡设备 具体修改了lan配置的ipaddr, 增加gatewaydns

config interface 'loopback'
	option device 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix 'fd5d:6ea2:93e4::/48'

# config interface is not the configuration of a physical interface, but rather the specification of a connector to some network.
config interface 'lan'
	# device is usually not the name of something configured with config interface, but the name of a physical interface.
	option device 'eth0'
	option proto 'static'
	option ipaddr '192.168.1.99'
	option netmask '255.255.255.0'
	option gateway '192.168.1.1'
	list dns '223.5.5.5'

修改之后重启网络

service network restart

测试路由和DNS解析是否正常: ping baidu.com, 一切OK再继续下面的

换源

大陆码农生存必备技能了, 这里使用的中科大的源, 配置文件位于 /etc/opkg/distfeeds.conf

src/gz openwrt_core http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/targets/x86/64/packages
src/gz openwrt_base http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/packages/x86_64/base
src/gz openwrt_luci http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/packages/x86_64/luci
src/gz openwrt_packages http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/packages/x86_64/packages
src/gz openwrt_routing http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/packages/x86_64/routing
src/gz openwrt_telephony http://mirrors.ustc.edu.cn/openwrt/releases/23.05.3/packages/x86_64/telephony

然后更新一下

opkg update

扩容根分区和文件系统

如果觉得默认的100M左右就够用了可以跳过这步

这个文档里的脚本只支持x86的ext4和squashfs镜像创建的虚机, 自动检测根分区和文件系统, 将空闲空间分给根分区和文件系统

https://openwrt.org/docs/guide-user/advanced/expand_root

扩容之后就使用起来就不用扣扣搜搜的了

root@OpenWrt:~# df -hT /
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/root            ext4          994.8M     56.9M    921.9M   6% /

安装OpenClash

主要是跟着官方wiki执行, 部分Github文件下载使用文件代理加速下载服务 https://mirror.ghproxy.com/

先卸载dnsmasq, 否则会和dnsmasq-full冲突, openclash依赖dnsmasq-full

# 如果提示dhcp配置文件(/etc/config/dhcp)没修改, 可以手动删了, 将新的(/etc/config/dhcp-opkg)覆盖过去
opkg remove dnsmasq && opkg install dnsmasq-full

下载安装安装包和各依赖

# 下载安装包
cd /tmp && wget https://mirror.ghproxy.com/https://github.com/vernesong/OpenClash/releases/download/v0.46.011-beta/luci-app-openclash_0.46.011-beta_all.ipk
# 安装所有依赖
opkg install coreutils-nohup bash iptables dnsmasq-full curl ca-certificates ipset ip-full iptables-mod-tproxy iptables-mod-extra libcap libcap-bin ruby ruby-yaml kmod-tun kmod-inet-diag unzip luci-compat luci luci-base
# 安装
opkg install /tmp/luci-app-openclash_0.46.011-beta_all.ipk

下载clash内核

# 下载
wget https://mirror.ghproxy.com/https://github.com/vernesong/OpenClash/releases/download/Clash/clash-linux-amd64.tar.gz
# 解压
tar -zxvf clash-linux-amd64.tar.gz
# 放置到执行目录下
mv clash /etc/openclash/core/clash
# 如果没有可执行权限设置执行权限
chmod +x /etc/openclash/core/clash

打开登录 OpenWrt web界面配置

默认密码为空, 第一次登录后可以修改一下

打开Services下的OpenClash进行配置即可.

此处省略1w字…

验证OpenWrt的DHCP服务没问题后, 关闭主路由器的DHCP服务.

关于为什么关闭主路由的DHCP功能: 因为我的主路由不支持设置DHCP服务器的默认网关, 所以只有设置静态ip并手动填写网关和DNS为OpenWrt的ip才能魔法上网. 不如直接不使用主路由的DHCP服务, 然后开启OpenWrt lan口的DHCP服务.

至此大功告成, 连接wifi之后即可魔法上网, (手动撒花).


分割线


其他小修改

修改dhcp分配ip范围

修改配置文件 /etc/config/dhcp

config dhcp 'lan'
        option interface 'lan'
        option start '150'
        option limit '100'
        option leasetime '12h'

修改之后重启 service dnsmasq restart, 配置之后有段时间dhcp server没正常运行, 可通过 logread -e dnsmasq 查看服务日志排查.

正常运行之后dhcp server会监听67端口

root@OpenWrt:~# netstat -anp | grep :67
udp        0      0 0.0.0.0:67              0.0.0.0:*                           27573/dnsmasq

修改br0的网关和dns

为了小主机三层网络也路由到代理网关, 这里修改之前br0的netplan配置后执行netplan apply生效

network:
  bridges:
    br0:
      dhcp4: false
      dhcp6: false
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
-         via: 192.168.1.1
+         via: 192.168.1.99
      nameservers:
        addresses: 
-         - 192.168.1.1
-         - 223.5.5.5
+         - 192.168.1.99
+       search:
+         - lan
      interfaces:
        - enp1s0
      parameters:
        stp: false

支持流量优先走主网关

因为 192.168.1.1 的网关是使用的我的流量卡的5G流量, 所以是做为备用网关, 主网关是 无线转有线网络 配置的 192.168.1.110

下面脚本实现优先使用主网关, 主网关不能访问互联网时再切换到备用网关

下面脚本放在 /root/gateway-switch.sh

#!/bin/bash

PRIMARY_GATEWAY="192.168.1.110"
SECONDARY_GATEWAY="192.168.1.1"

EXTERNAL_IP="223.6.6.6"

echo_with_time() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

test_gateway() {
    local gateway=$1
    # Add a temporary route
    ip r add $EXTERNAL_IP via $gateway
    # Test connectivity
    ping -c 2 -W 1 $EXTERNAL_IP > /dev/null 2>&1
    local result=$?
    # Remove the temporary route
    ip r del $EXTERNAL_IP via $gateway
    return $result
}

while true; do
    if test_gateway $PRIMARY_GATEWAY; then
        echo_with_time "Internet is accessible via primary gateway $PRIMARY_GATEWAY. Setting it as default."
        ip r replace default via $PRIMARY_GATEWAY
    else
        echo_with_time "Internet is not accessible via primary gateway $PRIMARY_GATEWAY. Using secondary gateway $SECONDARY_GATEWAY."
        ip r replace default via $SECONDARY_GATEWAY
    fi
    sleep 2s
done

设置crontab

openwrt的crontab不支持@reboot, 这里使用flock实现类似效果

# 设置crontab
echo "* * * * * flock -n /root/gateway-switch.lock /root/gateway-switch.sh >> /root/gateway-switch.log 2>&1" >> /etc/crontabs/root
# 运行cron并设置开机自启
/etc/init.d/cron start
/etc/init.d/cron enable

参考

  1. OpenWrt in QEMU
  2. OpenWrt: Expanding root partition and filesystem
  3. OpenWrt: DHCP and DNS configuration /etc/config/dhcp
  4. OpenWrt: Clarifying the term “Interface”
  5. OpenClash 安装