前言

为什么会有这篇文章呢?其实是因为我很早之前就对“以Linux为底层的软路由系统”很感兴趣,之前在学校学的就是网络工程和系统服务部署,因此对Linux系统和网络可以说还是比较熟悉的(特别是网络,有Datacom HCIE认证)。最开始搜软路由就会出现很多的OpenWRT,iKuai,RouterOS这样的文章,不过我只玩了段时间的OpenWRT + iStoreOS。

iStoreOS虽然在某些设计上确实很方便(比如web界面配置等),但使用一段时间下来还是感觉不顺心,这玩意儿怎么这么臃肿复杂,把一些很简单的事情做的很复杂,后来想了想,可能因为OpenWRT刚开始就是为了web界面的路由器设计的,要对新手友好些,但对外来说很多功能其实没必要了,而且OpenWRT的很多功能我都可以自己手搓实现。并且,会尽可能的将每一个服务都进行最大限度的性能优化,确保软路由的运行速度和效率,对我来说这是必须的~

基于以上原因,最终选择简洁的Ubuntu Server 25.04,且安装时选择最小安装来实现,为了保证在物理机上可一次性完美安装和功能实现,所有要部署的服务都会先在虚拟机上进行实验,确认没问题后才会上物理机,确保物理机系统的干净整洁(在这方面还是有洁癖的)。

另外提一嘴,2025年09月05日晚22:00,在小黄鱼上购买了一台多网口小主机(J4512)做软路由,虽然之前买过天钡家的AMD款的天钡 WTR PRO安装飞牛用到现在,但是一直没有做过软路由,因此耗“巨资”购买了它。

甚是喜欢呢,哈哈,不过夏天被动散热效率太低了,一会就发烫了,后面会整个静音风扇(类似电脑机箱里那个)就够压住了,它主要是没风带走热量,有风的话5分钟温度就降到室温了。

配置过程

以下过程均先在虚拟机上测试后才会“搬运”到物理机上,以下是虚拟机的配置列表,正好对应J4512的配置进行实验。

image

1、系统安装

关于U盘刻录系统镜像,插入机器并通过U盘启动这一步略过,不了解的可以上网查一下,教程太多了。

开机进入系统安装界面

image

选择English,随后进入到更新安装包的阶段,如果选择第一个update to the new installer那么需要确保你的机器目前已经连上网了,否则就选择第二个

随后选择键盘格式为English (US)

选择Ubuntu Server (minimized)最小化安装Ubuntu Server,然后就可以看到网卡界面了,目前连接公网的接口已经通过DHCP获取到了地址,可正常上网,其余三个接口后续要做桥接,因此先不配置。

image

跳过代理,来到软件包更新界面,如果没有要更新的,直接选择Done就行

在存储配置这一界面,为了后期分区扩容什么的方便,选择LVM安装,无需进行LVM加密

随后分区直接Done即可,因为目前设备就一块磁盘,且对于软路由来说不会存储有太多东西,因此直接一整块磁盘都做为根分区即可。

设置账户密码,随后选择安装OpenSSH Server方便后续远程连接。

到达软件包安装界面,虽然后面会用到docker,但目前系统还无法上外网,安装docker可能不顺利,因此都不选择,直接下一步。随后系统就会开始安装,因为选择的是最小安装,因此等待时间不会太久。

远程连接

安装完成重启开机后,因刚才选择了安装OpenSSH Server,因此可直接在windows的cmd中使用下面的命令远程连接到设备上(前提是和外网接口同网络)

ssh 用户名@接口地址

image

随后要做的就是提权更改root密码,切换root用户,更改ssh配置,使得root用户可使用密钥登录

sudo passwd root						# 输入一次ubuntu密码,两次要设置的root密码
su root
vim /etc/ssh/sshd_config
# 修改以下内容
Port 22
SyslogFacility AUTH
LogLevel VERBOSE
PermitRootLogin without-password
LoginGraceTime 2m
DenyUsers xxx	                                  # 禁止xxx用户登录
MaxAuthTries 3                                     # 最大认证次数3
MaxSessions 2                                      # 最大会话数2
PasswordAuthentication no                          # 禁止密码验证登录
PermitEmptyPasswords no                            # 禁止空密码验证
UseDNS no										   # 不对客户端进行DNS泛解析验证,加快SSH连接速度
PubkeyAuthentication yes                           # 开启SSH公钥认证登录
AuthorizedKeysFile .ssh/authorized_keys            # 用户登录公钥路径,如果该用户需要多设备免密登录,可以再authorized_keys文件内另起一行写入其他设备的公钥,也可以在此配置后再跟上.ssh/xxx_keys即可
RSAAuthentication yes                              # 允许RSA算法验证

在windows终端上生成ssh-key

ssh-keygen -t rsa -b 4096 						# 一直回车即可

会在C:\users\用户名\.ssh目录下生成一个私钥文件和公钥文件(pub结尾),使用文本文档打开pub文件,复制全部内容到Ubuntu的/root/.ssh/authorized_keys文件内,重启ssh后即可,尝试使用ssh登录可看到无需输入密码就可以进入系统

systemctl restart ssh
systemctl enable ssh

image

2、安装常用工具并调整系统时区

apt update && apt install iputils-ping traceroute unzip wget curl dnsutils iproute2 net-tools -y

调整系统时区

timedatectl set-timezone Asia/Shanghai

3、命令行补全

安装bash-completion

apt install bash-completion -y

在/etc/bash.bashrc文件下添加脚本命令

if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

退出当前用户终端重新进入即可

4、开启内核的路由转发功能

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.tcp_congestion_control = bbr

5、安装NetworkManager管理网络

apt install network-manager -y

目前Ubuntu Server默认管理网络的工具是netplan,其实是不太方便的,配置network-manager管理网络

vim /etc/NetworkManager/NetworkManager.conf
# 修改下面内容
[ifupdown]
managed=true
vim /etc/netplan/00-installer-config.yaml                # 每个系统的文件名都不一样,我这里叫00-installer-config.yaml
# 在下添加,注意开头与 version:2 对齐:
renderer: NetworkManager

应用netplay并重启NetworkManager(可能会断网,做好准备)

netplay apply
systemctl restart NetworkManager

随后查看nmcli接管情况

nmcli con show

出现下面类似的输出说明接管完成

image

修改各网卡的Connect Name为网卡名称,为方便可选择使用Network Manager的伪图形化界面快速修改

nmtui

效果如下

image

6、创建桥接网卡

现代光猫、软路由的LAN网卡其实本质上就是一个虚拟的桥接网卡,类似与Switch(交换机),通过将物理网卡绑定在桥接网卡下实现交换机二层网络接口的功能(默认网卡是三层网络,每个接口必须属于一个独立的IP段)

创建虚拟网卡LAN

nmcli con add \
 con-name lan \
 type bridge \
 ifname lan \
 ipv4.method manual \
 ipv4.addr 192.168.100.254/24 \
 ipv6.method auto \
 stp no

这里我们关闭了STP,因为当LAN接口下没有任何物理端口up时,LAN接口处于关闭状态,接入端口后STP需要经过2个Forwarding时间(30秒)才能进入UP状态,即便进入UP状态,还需要DHCP服务反应一段时间,这就会造成终端在开机或者睡眠结束后无法立马获取到地址上网,需要等待1-2分钟,这是比较痛苦的。

注意:这里如果是在虚拟机中,确保添加的三个内网网卡不属于同一个vmnet,否则,STP不开启的情况下,你将尝到广播风暴的味道~但同时,现实中我们关闭了STP也要确保软路由下接的只有三层接口(终端、路由器等),如果两个接口接同一个交换机,一定要开STP或者聚合接口,要不然也是会环路的

将三张局域网网卡绑定到桥接网卡lan下

nmcli con modify ens34 master lan
nmcli con modify ens35 master lan
nmcli con modify ens36 master lan

image

image

7、配置轻量DHCP服务器

这里有两种轻量选择,一种是dns和dhcp都具备的dnsmasq,另一种是转为dhcp准备的udhcp。后面因为要做流量分流,国内流量和国外流量分开走,需要路由分流和DNS分流,因此需要后面肯定要安装对应的dns服务,但是这里不选择dnsmasq,是因为它在处理大量域名列表的时候太过臃肿,CPU压力大,源于它的设计问题。后面再说,先说DHCP。

这里选择udhcpd是因为他非常的轻量,开发时就是为了嵌入式设备的小型化设备设计的,因此在运行时几乎不消耗资源。

安装udhcpd

apt install udhcpd -y

配置UDHCP服务器

# /etc/udhcpd.conf

# 指定要下发的地址范围
start          192.168.10.100
end            192.168.10.200

# 请确保这里是要监听DHCP请求的网络接口,例如 eth0, wlan0 等
interface       lan 

# DHCP租约文件,所有租约都将存储在这里。
lease_file     /var/lib/misc/udhcpd.leases
max_leases      101

# 指定到期时间
opt     lease   864000     # 10 days of seconds

# 指定要下发的掩码和网关
opt     subnet  255.255.255.0
opt     router  192.168.10.254

# 指定下发的DNS,如果后面要做DNS分流,一定也要指定dns是本设备
opt     dns     192.168.10.254

# 指定光播地址
opt     broadcast       192.168.10.255

# 指定下发的域
opt     domain  home

# 也可以指定静态下发地址
#static_lease  00:60:08:11:CE:4E 192.168.1.55
#static_lease  AA:BB:CC:DD:EE:FF 192.168.1.75
systemctl restart udhcpd
systemctl enable udhcpd

修改启动顺序为NetworkManager之后

由于udhcpd是在NetworkManager前启动的,而udhcpd中的lan接口又是NetworkManager创建的,因此会导致udhcpd在系统启动时无法得知lan接口导致启动失败,将其调整为NetworkManager后启动

vim /usr/lib/systemd/system/udhcpd.service
# 修改以下内容
After=NetworkManager-wait-online.service
Wants=NetworkManager-wait-online.service

重新加载配置

systemctl daemon-reload

8、配置smartdns服务

之前说了dnsmasq在处理大量域名列表的时候太过臃肿,CPU压力大。因此选用smartdns服务,smartdns在设计时就保证了即使处理万级的域名列表也很轻松,特别是我们后面要配置的域名列表内有11万的国内域名列表。11万行的列表,dnsmasq处理时会有很长时间的CPU沾满的情况,绝对不适合,而smartdns即使处理11万行域名列表也可以较为轻松应对。

为什么要进行dns分流?因为国内大厂的站点都有CDN和DNS分流解析,国内DNS服务器和国外DNS服务器解析出来的IP地址不一样,国外的DNS走他们的海外节点,国内的DNS走国内的节点。因此,要进行分流的话,必须要做DNS分流。

SmartDNS官网:

https://pymumu.github.io/smartdns/configuration/

安装smartdns

apt install smartdns -y

获取国内域名列表

cd /etc/smartdns
wget -O cn.conf https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/refs/heads/master/accelerated-domains.china.conf

可以先复制到windows电脑内用记事本打开,Ctrl + h 进行替换,把文件内的server=/换成空 ,/114.114.114.114换成空 ,确保每一行只有一个域名

将*.cn加入到列表的最上方,这样如果访问的是.cn域名的站点服务器直接从文件最上方就能匹配到,不需要往下寻找,消耗CPU资源了

*.cn

配置smartdns

vim /etc/smartdns/smartdns.conf
# 在lan接口监听dns查询
bind :53 -device lan

# 创建china组且不放入default组,在default组内的server在为明确指定域名对应的dns服务器时,会使用default组内的dns服务器
server 114.114.114.114  -group china -exclude-default-group
server 223.5.5.5  -group china -exclude-default-group
server 223.6.6.6  -group china -exclude-default-group

# 创建global组,并在default组内,当没有明确的域名对应的dns服务器时,会使用default组内的dns服务进行查询
server 8.8.8.8 -group global
server 8.8.4.4 -group global
server 1.1.1.1 -group global

# 创建一个名为cnlist的domain-set,可将cn.conf内容导入到domain-set内快速查询
domain-set -name cnlist -file /etc/smartdns/cn.conf
# -a no -speed-check-mode none确保在使用china组的时候不预先进行测速选择最优服务器,cn.conf文件内容过大的话,测速会导致速度验证下降
nameserver /domain-set:cnlist/china -a no -speed-check-mode none

# 禁用IPv6域名解析,在分流中不仅会导致流量无法分流,还会降低smartdns查询速度
force-AAAA-SOA yes
# 关闭双栈测速,节省资源
dualstack-ip-selection no
# 指定域名解析缓存大小,缓存到内存中,后续有相同的查询的话就不需要在文件内查询了
cache-size 65536
# 禁用缓存持久化。20万规则下,保存和加载缓存文件会成为启动和关闭时的性能瓶颈,且可能产生冲突。
cache-persist no
prefetch-domain yes

# 最小TTL值
rr-ttl 300
# 允许的最小TTL值
rr-ttl-min 300
# 允许的最大TTL值
rr-ttl-max 86400
# 只记录致命错误
log-level fatal
# 每个上游返回的IP数量,减少处理开销
max-reply-ip-num 4

这里解释一下:

smartdns在针对某个域名指定查询DNS服务器的时候可以使用conf-file​domain-set​两种方法,这里使用domain-set​domain-set​ 的方案在处理每个DNS查询时,CPU消耗极低且恒定,可将域名列表文件中的每一个域名作为独立的键(Key) 加载到一个高度优化的哈希表中进行哈希查找。收到查询后,SmartDNS 直接计算查询域名的哈希值,然后在哈希表中进行一次查找,立刻知道是否存在。而conf-file是线速查找,顺序遍历。收到一个DNS查询后,SmartDNS 需要从第一条规则开始,依次向下匹配,直到找到匹配项或遍历完所有20万条规则。

使用domain-set​,99% 的查询都不会因为匹配这20万条规则而增加任何可感知的延迟。而使用 conf-file​,每个查询都可能因为要遍历巨大的规则列表而产生几毫秒甚至更高的延迟,这在网络游戏中是致命的。并且domain-set​能处理的每秒查询量(QPS) 会远高于conf-file​方案,在高负载环境下更加稳定。

总而言之,在cn.conf​文件内容在万级时,使用smartdns绝对是性能优化的最优解!

使得resovectl不监听系统网卡53端口,但是还是处理上游dns服务器,防止和dnsmasq冲突

vim /etc/systemd/resolved.conf
DNSStubListener=no
systemctl restart systemd-resolved.service

由于smartdns 是在NetworkManager前启动的,而dnsmasq中的lan接口又是NetworkManager创建的,因此会导致dnsmasq在系统启动时无法得知lan接口导致启动失败,将其调整为NetworkManager后启动

vim /usr/lib/systemd/system/smartdns.service
# 修改以下内容
After=NetworkManager-wait-online.service
Wants=NetworkManager-wait-online.service

重新加载配置

systemctl daemon-reload

可选配置

DOH,加密global组内的DNS查询,防止DNS查询信息泄漏

# 创建global组,并在default组内,当没有明确的域名对应的dns服务器时,会使用default组内的dns服务进行查询
#server 8.8.8.8 -group global
#server 8.8.4.4 -group global
#server 1.1.1.1 -group global
# 注释掉原本的global组配置
server-tcp 8.8.8.8
server-tcp 1.1.1.1
server-https https://dns.google/dns-query -group global
server-https https://doh.opendns.com/dns-query -group global

9、使用OpenVPN进行科学上网和流量分流

篇幅太长,看我之前的文章

https://blog.opennw.cn/archives/openvpnde-you-hua#15%E3%80%81%E5%AE%9E%E7%8E%B0-openvpn-%E5%88%86%E6%B5%81%E5%B9%B6%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%E8%B7%AF%E7%94%B1

这里要注意,安装openvpn-dco的话,有小部分概率tun网卡使用会不顺畅,具体看文章开头,目前只在inter cpu遇到过,而且我配置了十几台服务器了,只见过这一次。

另外注意一下:

1、设置好DNS和路由分流后,苹果设备如果在iCloud中开启了专用代理​那么流量就会通过苹果的服务器再做一层VPN代理加密,不仅会导致苹果设备分流失败,还会导致数据转发效率低(因为加密和隧道做了两次),如果希望进行分流,建议关闭专用代理​后重启设备。

2、即便是关掉专用代理,有可能发现访问抖音APP还是会走隧道,但是访问其他APP就不会(比如CSDN),那么这种情况就是抖音有了海外CDN的缓存或者打了标记,删除重装一下就好了。

10、调整系统启动时间

ubuntu18以后使用netplan管理网络,会有一个毛病,就是netplan配置的网络在系统启动时systemd-networkd-wait-online这个服务无法正常监听到网络启动,导致超时启动失败,导致系统启动时间有2分钟超时时间。可以将其超时时间控制在10秒,虽然可以关闭它,但是为了以后产生不必要的麻烦,还是调整超时时间吧

mkdir /etc/systemd/system/systemd-networkd-wait-online.service.d
vim /etc/systemd/system/systemd-networkd-wait-online.service.d/override.conf
# 加入以下内容
[Service]
TimeoutStartSec=10sec

重新加载配置

systemctl daemon-reload

重启系统即可发现开机速度快了

11、配置防火墙和NAT

以下是nftables防火墙的加速数据包转发、NAT和有状态包过滤防护配置,内容太大了,不单独解释,没学过的自行查资料

netfilter官网:

https://netfilter.org/
vim /etc/nftables.conf
#!/usr/sbin/nft -f

flush ruleset

# 预定义配置
define lan_int={ lan, wlp6s0 }
define wan_int={ enp1s0 }
define vpn_ip={ 10.10.10.0/24, 10.10.20.0/24, 10.10.30.0/24  }

table inet filter {
		# flowtables,数据包卸载功能,匹配的数据包可绕过prerouting、routing、forwarding和postrouting hook直接跳出netfilter,减少cpu消耗
        flowtable myft {
                hook ingress priority filter;
                devices = { enp1s0, lan, wlp6s0 }
                counter
        }


        chain input {
                type filter hook input priority filter; policy drop;

				# 放行已建立连接和与连接相关的连接(有状态防火墙)
                ct state { established, related } accept

                iif "lo" accept

                iif $lan_int accept

                ip saddr $vpn_ip accept

                iif $wan_int ip protocol tcp tcp dport { 22 } accept
        }

        chain forward {
                type filter hook forward priority filter; policy drop;

				# 将已建立连接和与连接相关的连接调用在加速数据转发的flowtable中(要放在accept之前,否则直接放行了,不会被匹配)
                ct state { established, related } flow add @myft
				# 放行已建立连接和与连接相关的连接(有状态防火墙)
                ct state { established, related } accept

                iif $lan_int accept

                ip saddr $vpn_ip accept

        }

        chain output {
                type filter hook output priority filter; policy accept;

                ct state { established, related } accept
        }

        chain postrouting {
                type nat hook postrouting priority 100; policy accept;

				# 出接口非环回接口和LAN接口时进行SNAT伪装
                oif !={ lo, lan } masquerade

                ct state { established, related } accept
}
}

加载nftables规则并设置为开机自启动

nft -f /etc/nftables.conf
systemctl enable nftables

同样的还是修改nftabels的启动顺序在NetworkManager之后

vim /usr/lib/systemd/system/nftables.service
# 修改以下内容,并
After=NetworkManager-wait-online.service
Wants=NetworkManager-wait-online.service
systemctl daemon-reload

12、安装docker

国内安装docker会受限制,因此使用阿里云软件源进行安装

# 从阿里云镜像源下载 Docker 官方 GPG 密钥(国内访问快,无 SSL 连接问题)
# 并转换为 apt 可识别的密钥格式,保存到系统密钥目录
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 生成适配当前系统架构和版本的阿里云 Docker 源配置
# 其中:
# - $(dpkg --print-architecture) 自动获取系统架构(如 amd64)
# - $(lsb_release -cs) 自动获取 Ubuntu 系统版本代号(如 jammy、focal)
# - signed-by 指定已添加的阿里云密钥路径,确保源验证通过
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 更新软件包索引(此时会从阿里云源获取信息,速度快且稳定)
sudo apt update

# 安装 Docker 引擎及相关组件(docker-ce 为 Docker 引擎,docker-ce-cli 为命令行工具,containerd.io 为容器运行时)
sudo apt install docker-ce docker-ce-cli containerd.io

# 配置docker开机自启动
sudo systemctl enable docker

检验docker是否安装

docker info
-----------------------------------------------------------------------
Client: Docker Engine - Community
 Version:    28.4.0
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.27.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.39.2
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
.......................

关闭docker自动生成防火墙配置,后面我们自己配置,并且设置docker默认桥接网卡的ip地址

vim /etc/docker/daemon.json
{
  "iptables": false,
  "ip6tables": false,
  "bip": "192.168.17.1/24"
}

重启docker生效

systemctl restart docker

13、配置IPv6相关内容

在有IPv6地址的环境下,我们为了方便访问内网设备,肯定是要获取IPv6地址的,外网接口从运营商获取到ICMPv6的RA报文,从中提取IPv6前缀并根据eui64生成一个IPv6地址。更重要的是,我们还要通过这个获取到的前缀为局域网内的设备下发IPv6地址。

以上前提:光猫是桥接模式,由ubuntu路由器复制PPPOE拨号,得到运营商下发的PD前缀才可,大多为56或50。否则最多获取到/64的地址,/64的地址是不能继续拆分向下分发的,因为拆分的话就到/65了,而下发ipv6地址最少要求的是/64;

如果ubuntu路由器只能通过RS/RA获取到/64的地址,那么,LAN接口下的设备是无缘公网IPv6地址了,只能WAN接口获取/64地址,然后LAN接口配置/64的私网地址下发RA消息,使得局域网获取到一个私网的/64前缀生成地址。如果希望WAN侧主机通过IPv6访问内网主机,需要做DNAT才可以。

配置外网接口获取IPv6地址

nmcli con modify ens33 ipv6.method auto \
 ipv6.addr-gen-mode eui64 \
 ipv6.ip6-privacy 0
nmcli con up ens33				# 重启外网接口然后使用ip addr查看接口是否获取到IPv6地址

随后进行LAN接口配置

nmcli con modify lan ipv6.method shared \
 ipv6.address fd00:192:168:100::1/64
nmcli con up lan				# 重启内网接口

随后LAN接口下的终端主机在开启IPv6功能后即可通过ICMPv6的RS和RA报文获取对应的IPV6地址和IPv6 DNS信息

image

image

14、配置无线网络

🤔 关于无线网络调优要点:

  • 如果你的无线网卡接口是Mini PCIE的,建议不要选择Intel的,Intel的很多Mini PCIE无线网卡作为热点(AP模式) 来发射Wi-Fi信号时,对其大部分消费级网卡的驱动进行了软件锁定,而且AP模式发射的2.4G信号特别差。这是Intel 为MiniPCIE接口网卡设计时就决定了主要作为Client模式使用而非AP模式。使用其他品牌的无线网卡或者USB网卡可以得到很好的解决。

  • 通常来说WiFi信号强度和用户体验,是发射功率(单位:dBm)和天线(包括增益和覆盖模式,单位:DB)共同作用的结果。因此即使发射功率较小,但天线数量和信号覆盖范围大也有很流畅的使用体验。但最好还是功率和天线增益都高一些的好。

  • 另外,当你使用5G信号时,在不考虑无线网卡自身性能(如支持的技术标准)的前提下,信道数和信道宽度(Channel Width)是决定Wi-Fi数据吞吐量(即速度)最关键的因素之一。

上面说了Mini PCIE无线网卡接口的软路由尽量不要选择Intel无线网卡,可能踩坑,我这里使用的是联发科的MT7922网卡。在使用时,这款网卡在Linux系统能较好地支持AP模式,有较高的传输速率,6.8以上的内核无需手打驱动。再者,我后面购买了一代的无线网卡延长线和天线(增益3DB),无线信号覆盖范围已经可以将我的出租屋全方位覆盖,如果你家里很大需要更大的信号覆盖范围,建议购买8/12DB的增益天线或者外接AP组网。

软路由无线组网方式有三种,根据自己的要求进行选择

🤔 软路由无线组网的三种方法:

1、使用主板内置插槽;
大部分小主机内置了有PCIE或Mini PCIE插槽的无线网卡,可以选择一个合适的无线网卡+增益天线进行释放无线信号;

2、使用USB无线网卡;
与使用主板插槽类似,但是USB无线网卡通用性强,也省心,通常USB无线网卡的功率都比较高,自带增益天线。

3、外接AP;
使用软路由作为核心路由,下联接口插入一个家用路由器(最好支持仅AP模式),这种组网是信号覆盖范围和速率最好的。

在配置无线网络时,有三种NetworkManager方法可以进行配置(传统可能使用hostapd服务,但是过于麻烦,而NetworkManager提供了快速简便的方法进行配置)

🤔 释放无线信号的三种方法:

1、使用”个人热点“;

2、手动配置各种参数;

3、桥接到LAN网卡(推荐);

以上三种方法的区别在于:

  • 个人热点:创建后NetworkManager会使用内置的dnsmasq下发dhcp和dns,方便快捷,但是无线网卡和LAN网卡属于不同的三层网络,需要配置不同的IP段,且如果手动配置了DHCP和DNS服务,会无法下发地址,因为接口对应端口已经被监听;

  • 手动配置DHCP和DNS参数:这种方式下所有参数都需要手动配置,包括DHCP和DNS,但是无线网卡和LAN网卡属于不同的三层网络,需要配置不同的IP段。且需要独立配置第二个DHCP实例监听无线网卡的DHCP请求;

  • 桥接到LAN网卡:此模式下,LAN网卡和无线网卡共用一个三层IP和IPv6,对于无线网卡来说,它不需要管IP下发的问题,只需要发射无线信号、设置密码,随后把客户端的对应数据上送给LAN网卡,由LAN网卡统一下发DHCP、DNS等。这也是家用路由器常见的做法,无线客户端获取到的IP地址是和有线客户端一个网段的。

下面举例三种模式的创建方法(5G Channel 36),如果无法启动且报错 Error: Connection activation failed: 802.1X supplicant took too long to authenticate​,可能存在多种原因,如:配置了当前国家代码下不允许使用的配置、无线接口模式为shared但已经被别的服务监听了53和67,68端口、网卡不支持5G或高MHz等等;

首先将自己的无线网卡国家代码设置为CN,避免因为默认处于严格限制的00而使得很多功能禁止使用(80MHz信道宽度和某些提升无线安全和性能的功能)

iw reg set CN

以上命令为临时修改,使用下面的方法写入内核模块参数,创建或编辑下面的文件

vim /etc/modprobe.d/cfg80211.conf
# 添加以下内容
options cfg80211 ieee80211_regdom="CN"

更新initramfs确保在引导时加载,随后重启系统无线国家代码也是CN了

update-initramfs -u

查看附近wifi所处的大部分信道

nmcli device wifi list

查看网卡支持的信道,[ ]​外没有写disabled​和no IR​的都是可以使用的

iw list | grep -A 10 "dBm"

根据如何配置一个没有使用或最少使用的信道,信道与信道之间最少相隔5,我这里没人使用信道149

个人热点配置(shared模式确保会自动下发地址)

nmcli device wifi hotspot \
 con-name SoftRouting \
 mode ap \
 ifname wlx0013ef6f25bd  \
 ssid SoftRouting \
 802-11-wireless-security.key-mgmt wpa-psk \
 802-11-wireless-security.psk xxxx \
 802-11-wireless.band a 802-11-wireless.channel 36 \
 ipv4.method shared \
 ipv4.address 192.168.20.254/24
nmcli con up SoftRouting

手动配置:

nmcli con add con-name SoftRouting \
 ifname wlx0013ef6f25bd \
 type wifi \
 mode ap \
 802-11-wireless.ssid SoftRouting \
 802-11-wireless-security.key-mgmt wpa-psk \
 802-11-wireless-security.psk xxxx \
 802-11-wireless.band a 802-11-wireless.channel 36 \
 ipv4.method manual \
 ipv4.address 192.168.20.254/24 
nmcli con up SoftRouting

桥接到LAN网卡配置

nmcli connection add con-name SoftRouting \
 ifname wlx0013ef6f25bd \
 type wifi \
 master lan \
 wifi.mode ap \
 wifi.ssid SoftRouting  \
 wifi-sec.key-mgmt wpa-psk \
 wifi-sec.psk Ljr1873599@ \
 802-11-wireless.band a \
 802-11-wireless.channel 149 
nmcli con up SoftRouting
nmcli con up lan

扩展:设置加密方式为更安全的WPA2(AES),默认是TKIP和AES混用,而客户端连接时可能选择到了不安全的TKIP

nmcli con modify SoftRouting \
 802-11-wireless-security.proto rsn \
 802-11-wireless-security.pairwise ccmp \
 802-11-wireless-security.group ccmp 
nmcli con up SoftRouting
nmcli con up lan

开启AP隔离(可选),无线终端之间无法互访

nmcli con modify SoftRouting 802-11-wireless.ap-isolation true

禁用省电模式,确保无线网卡始终处于高性能状态

nmcli con modify SoftRouting 802-11-wireless.powersave disable

查看无线信息

iw dev wlx0013ef6f25bd info
-------------------------------------------------------------------------------------------------------
Interface wlx0013ef6f25bd
        ifindex 6
        wdev 0x1
        addr 00:13:ef:6f:25:bd
        ssid SoftRouting
        type AP
        wiphy 0
        channel 149 (5745 MHz), width: 20 MHz, center1: 5745 MHz
        txpower 19.00 dBm
        multicast TXQ:
                qsz-byt qsz-pkt flows   drops   marks   overlmt hashcol tx-bytes        tx-packets
                0       0       6308    0       0       0       0       995117          8377

传输功率的单位是 dBm。数值越大,信号覆盖范围越广。常见家用路由器的功率一般在 20 dBm(100mW)左右。

这里有个踩坑点,如果你使用的无线网卡是MT792x的,且系统是6.8的内核,那么你大概率会看到只有3dbm的功率,这在2025年的2月已经修复了,是内核补丁修复人员说这是误报,实际功率正常。如果你不想更换内核,且测速正常的话就不用管了(MT7921/2正常无线桥接下的5G模式80MHz信道宽度的情况下带宽应该在700Mbps左右)。

查看客户端连接信息(需要已有连接的客户端)

iw dev wlp6s0 station dump
-------------------------------------------------------------------------------------------------------
Station 5e:7c:0b:29:d6:56 (on wlp6s0)
	inactive time:	29757 ms
	rx bytes:	3435638710
	rx packets:	2569586
	tx bytes:	3683176612
	tx packets:	2643850
	tx retries:	115217
	tx failed:	63
	rx drop misc:	0
	signal:  	-29 [-34, -30] dBm
	signal avg:	-29 [-33, -30] dBm
	tx bitrate:	780.0 MBit/s VHT-MCS 9 80MHz VHT-NSS 2
	tx duration:	140452409 us
	rx bitrate:	866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2
	rx duration:	40286512 us
	last ack signal:-28 dBm
	avg ack signal:	-28 dBm
	airtime weight: 256
	authorized:	yes
	authenticated:	yes
	associated:	yes
	preamble:	long
	WMM/WME:	yes
	MFP:		yes
	TDLS peer:	no
	DTIM period:	2
	beacon interval:100
	short slot time:yes
	connected time:	3361 seconds
	associated at [boottime]:	8987.760s
	associated at:	1758546903718 ms
	current time:	1758550264908 ms

其中的tx bitrate:173.3 MBit/s​和rx bitrate:173.3 MBit/s​分别是网卡的最大上传和下载速度

更改网卡信道宽度(需要网卡支持),以获得更大的带宽吞吐量。(标准的80MHz所使用的信道为36, 40, 44, 48 而160MHz则因每一组都可能会有雷达干扰,因此除非在偏远地区,否则很多情况下甚至表现不如80MHz,使用的话推荐信道36, 40, 44, 48, 52, 56, 60, 64)

nmcli con modify SoftRouting 802-11-wireless.channel 36
nmcli con modify SoftRouting 802-11-wireless.channel-width 80mhz
nmcli con up SoftRouting 

再次查看无线网卡信息

phy#0
	Interface wlx0013ef6f25bd
		ifindex 6
		wdev 0x1
		addr 00:13:ef:6f:25:bd
		ssid SoftRouting
		type AP
		channel 48 (5240 MHz), width: 80 MHz, center1: 5210 MHz
		txpower 18.00 dBm
		multicast TXQ:
			qsz-byt	qsz-pkt	flows	drops	marks	overlmt	hashcol	tx-bytes	tx-packets
			0	0	277	0	0	0	0	38459		332

测速后发现上下行均可达650mbps左右(homebox测速)

15、部署DDNS-GO

上面我们通过RS和RA报文让WAN侧接口获得了运营商下发的公网IPv6地址,但这个地址是会随机变化的,如果希望可以远程管理不太方便。因此我们需要部署DDNS-GO,将域名与IPv6地址绑定,同时定时检测IPv6地址是否发生变化,检测到变化后自动将域名提供商内DNS的解析地址改变。前提是有域名,我已经提前买了一个域名并且完成了备案。

首先确保接口获得的IPv6地址是单个的,不存在“临时地址”

nmcli con modify ens33 ipv6.method auto \
 ipv6.addr-gen-mode eui64 \
 ipv6.ip6-privacy 0
nmcli con up ens33

docker部署

docker pull jeessy/ddns-go
mkdir /Docker_Data/ddns-go
docker run -d --name ddns-go --restart=always --network=host -v /Docker_Data/ddns-go:/root jeessy/ddns-go

随后LAN侧获取到地址后浏览器输入网关地址+9876即可进入配置界面

随后为了方便远程管理,打开WAN侧的IPv6 SSH端口,这里要注意:为了安全,一定要使用密钥登录并关闭密码登录,最好后面再配置Fail2ban防止SSH爆破。修改后的input规则如下

        chain input {
                type filter hook input priority filter; policy drop;

                ct state { established, related } accept

                iif "lo" accept

                iif $lan_int accept

                ip saddr $vpn_ip accept

                iif $wan_int ip6 nexthdr icmpv6 accept

                iif $wan_int ip6 nexthdr tcp tcp dport { 22 } accept

                iif $wan_int ip protocol tcp tcp dport { 22 } accept
        }
nft -f /etc/nftables.conf

尝试使用IPv6地址SSH登录,前提:SSH客户端已经可通过IPv6正常上网;

16、流量记录

在网上有很多专业级的开源监控系统,但是对于我们的路由器来说,过于丰富的功能是一个累赘,但我们又需要一个界面美观的流量监控。于是经过我一天的查找和部署,找到一个国内作者开发的基于docker版vnstat的网卡监控web界面,有着资源占用极小,界面美观大气的优点,下面是部署过程

制作镜像(可选)

如果你必须制作,可以使用作者已经做好的镜像me1dlinger/vnstat_dashboard​

git clone https://github.com/me1dlinger/vnstat_dashboard.git
cd /vnstat_dashboard/vnstat_assist

这里发现作者设置的镜像源不对,而且我的设备可以直接上外网,因此删除其中dockerfile中镜像源的配置后执行下面的命令

docker build -t opennw/vnstat-dashboard .

构建完成后,先使用下面的命令部署docker版的vnstat

docker run -d \
    --restart=always \
    --network=host \
    -e HTTP_PORT=9695 \
    -v /etc/localtime:/etc/localtime:ro \
    -v /etc/timezone:/etc/timezone:ro \
    --name vnstat \
    vergoh/vnstat

随后部署刚才构建好的镜像

mkdir -p /Docker_Data/vnstat/log/python
mkdir -p /Docker_Data/vnstat/backups
docker run -d \
  --name vnstat-dashboard \
  --network=host \
  --restart=always \
  -v /Docker_Data/vnstat/log/python:/app/log/python \
  -v /Docker_Data/vnstat/backups:/app/backups \
  -e VNA_AUTH_ENABLE=1 \
  -e VNSTAT_API_URL=http://127.0.0.1:9695/json.cgi \
  -e VNA_SECRET_KEY=public \
  -e VNA_EXPIRE_SECONDS=3600 \
  -e VNA_USERNAME=admin \
  -e VNA_PASSWORD=admin \
  opennw/vnstat-dashboard

如果不想进行认证,将VNA_AUTH_ENABLE=设置为1,VNA_USERNAME、VNA_PASSWORD和VNA_SECRET_KEY可以不设置,但需要你确保足够安全,只有你可以访问。(但是web界面还是需要填用户名密码,只是随便写就行)

成功运行后,浏览器输入 http://xxxx:19328进入登录界面,此时需要先点击右上角 设置图标,填入你的web界面地址和默认网卡名。注意是web界面地址,不是vnstat的json.cgi地址。

保存后输入账户名密码即可进入流量监控界面,但注意,只有vnstat-docker运行时,才能有正常的流量记录,且首次部署需要等待5分钟才能看到采集的流量记录

17、调整内核参数

ubuntu是一个通用服务器,默认的一些内核参数是为了最为服务器使用的,既然我们要做路由器肯定就需要进行一些内核配置调整

将下面的内容覆盖掉/etc/sysctl.conf​文件

# 反向路径验证,防止 IP 欺骗和 DDoS 攻击(0 为关闭,适合 VPN 服务器以避免兼容问题;若无 VPN,建议改为 1)
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0

# 启用 IPv4 和 IPv6 包转发(路由器核心功能)
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

# ECMP哈希优化
net.ipv4.fib_multipath_hash_policy=1

# 禁用 ICMP 重定向,防止 MITM 攻击
net.ipv4.conf.all.accept_redirects=0
net.ipv6.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0

# 禁用发送 ICMP 重定向,进一步增强路由安全
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0

# 禁用源路由包接受,防止 IP 欺骗
net.ipv4.conf.all.accept_source_route=0
net.ipv4.conf.default.accept_source_route=0

# 忽略广播 ICMP Echo 请求,防放大攻击
net.ipv4.icmp_echo_ignore_broadcasts=1

# 启用 IPv4 恶意 ICMP 错误消息保护
net.ipv4.icmp_ignore_bogus_error_responses=1

# 启用 TCP SYN cookies,防 SYN 洪水攻击
net.ipv4.tcp_syncookies=1

# 设置 TCP 半连接超时为 10s,提高连接建立效率
net.netfilter.nf_conntrack_tcp_timeout_syn_recv=10

# 缩短 FIN 超时时间,加速连接关闭
net.ipv4.tcp_fin_timeout=15

# 缩短 TCP CLOSE_WAIT 超时
net.netfilter.nf_conntrack_tcp_timeout_close_wait=60

# 缩短 TCP TIME_WAIT 超时,释放端口更快
net.netfilter.nf_conntrack_tcp_timeout_time_wait=40

# 增大 Conntrack 最大连接数,支持高并发路由
net.netfilter.nf_conntrack_max=1048576

# TCP Keepalive 时间为 300s(5 分钟),检测死连接
net.ipv4.tcp_keepalive_time=300

# Keepalive 探测间隔 60s
net.ipv4.tcp_keepalive_intvl=60

# Keepalive 最大探测次数 5 次
net.ipv4.tcp_keepalive_probes=5

# 本地端口范围 1024-65535,支持更多并发连接
net.ipv4.ip_local_port_range=1024 65535

# TCP 接收缓冲区(最小、默认、最大),优化高延迟网络
net.ipv4.tcp_rmem=4096 87380 16777216

# TCP 发送缓冲区(最小、默认、最大),提升发送性能
net.ipv4.tcp_wmem=4096 65536 33554432

# 网络接口接收缓冲区最大值
net.core.rmem_max=67108864

# 网络接口发送缓冲区最大值
net.core.wmem_max=67108864

# TCP 监听队列长度,支持更多并发
net.core.somaxconn=65536

# SYN 后备队列长度,防 SYN 洪水
net.ipv4.tcp_max_syn_backlog=8192

# 网络接口输入队列最大长度,防高负载丢包
net.core.netdev_max_backlog=65536

# TCP 窗口缩放启用,提高长距离网络性能
net.ipv4.tcp_window_scaling=1

# TCP 拥塞控制算法为 BBR,适合高带宽延迟网络
net.ipv4.tcp_congestion_control=bbr

# 启用 TCP Fast Open,减少连接建立 RTT
net.ipv4.tcp_fastopen=3

# 默认队列纪律为 CAKE,减少缓冲膨胀,优化路由公平性
net.core.default_qdisc=cake

# IPv6 路由缓存最大大小
net.ipv6.route.max_size=131072

# IPv6 路由垃圾回收阈值
net.ipv6.route.gc_thresh=1024

# IPv6 接受RA消息,可以通过SLAAC获取到IPv6地址
net.ipv6.conf.all.accept_ra=2

# 文件系统事件通知队列最大数,提高监控性能
fs.fanotify.max_queued_events=65536

# 每个用户最大监控文件/目录数
fs.inotify.max_user_watches=524288

# 系统最大文件描述符数
fs.file-max=2097152

# ARP 缓存垃圾回收阈值,防止 ARP 风暴
net.ipv4.neigh.default.gc_thresh1=1024
net.ipv4.neigh.default.gc_thresh2=2048
net.ipv4.neigh.default.gc_thresh3=4096

# 允许 TIME_WAIT 套接字复用新连接;加速端口回收 15-20%。
net.ipv4.tcp_tw_reuse=1

# 增大 TIME_WAIT 桶限,防端口耗尽;高并发必需
net.ipv4.tcp_max_tw_buckets=1440000

# 启用 MTU 探测,支持 Jumbo Frames;提升大包吞吐 10%
net.ipv4.tcp_mtu_probing=1

# 增大 ancillary 缓冲,支持 UDP/TCP 选项;低开销优化
net.core.optmem_max=1048576

# 哈希桶数匹配 conntrack_max/4;加速查找,减少cpu消耗
net.netfilter.nf_conntrack_buckets=262144

# 增大路由最大条目数
net.ipv4.route.max_size=1048576

# 设置路由缓存垃圾回收(GC)的超时时间
net.ipv4.route.gc_timeout=60

# ARP缓存条目有效期
net.ipv4.neigh.default.base_reachable_time=30000

# 过期ARP缓存条目的垃圾回收检查时间间隔
net.ipv4.neigh.default.gc_stale_time=75000

# 禁止内核指针暴露,提高安全
kernel.kptr_restrict=2

# softirq 每次轮询处理的包数上限
net.core.netdev_budget=1500

# softirq 轮询时间上限(微秒)
net.core.netdev_budget_usecs=9000

net.core.rmem_default=16777216

# 减少交换使用,优先内存(适用于内存充足的路由器)
vm.swappiness=10

刷新内核参数

sysctl -p

18、拦截广告

smartdns可以拦截广告域名并把解析地址指向0.0.0.0,从而达到拦截广告的目的。可以手动捕捉广告域名,也可以在这个项目里提取:

https://github.com/217heidai/adblockfilters
cd /etc/smartdns/
touch blacklist.txt

将广告域名添加进blacklist.txt中

将下面的内容加入到smartdns.conf​文件中,记得放在cnlist的前面,确保在匹配到分流域名前先匹配到黑名单列表

# 广告域名domain-set,将解析结果指向0来阻止广告,使用domain-set加快查询
domain-set -name blacklist -file /etc/smartdns/blacklist.txt
address /domain-set:blacklist/0 -a no -speed-check-mode none

重启smartdns,随后,在blacklist列表中的广告域名就会被拦截。主要表现为:

1、部分页面广告消失;

2、无法拦截站点作者嵌入页面的图片链接或弹窗样式;

还有一种Adgurad项目拦截广告的,更为高级,但是对我来说用处不大,需要的可以在Github搜索这个项目

19、查看SSH登录成功和失败信息

在Ubuntu24.04及之前,我习惯使用last和lastb输出ssh登录成功和失败信息,用于查看是否有人尝试爆破,但不知为何,在Ubuntu24.10开始不在提供last和lastb命令。last还可以安装wtmpdb实现,但是lastb已经无法安装了,也没有替代命令。可以选择读取auth.log文件内容或写一个脚本,但注意,如果脚本是实时监控的,在遇到SSH爆破时每秒百次的爆破就可能耗尽CPU资源,因此还是建议筛选auth.log文件内容。

为了方便使用,我们可以在环境变量中设置别名,将以下内容加入到/etc/bash.bashrc文件内

alias last='echo ""; echo "------------------登录成功信息------------------"; cat /var/log/auth.log | grep -a Accepted | grep -a from | awk '\''{ gsub(/T/, " ", $1); sub(/\..*/, "", $1); print $1, $4, $7, $9 };'\''; echo ""'

alias lastb='echo ""; echo "------------------登录失败信息------------------"; cat /var/log/auth.log | grep -a Failed | grep -a from | awk '\''{ gsub(/T/, " ", $1); sub(/\..*/, "", $1); print $1, $4, $7, $9 }'\''; echo ""; echo "-----------------无效用户登录信息-----------------";  cat /var/log/auth.log | grep -a Invalid | grep -a from | awk '\''{ gsub(/T/, " ", $1); sub(/\..*/, "", $1); print $1, $4, $6, $8 }'\''; echo ""'

退出当前用户后再次登录,即可使用last命令和lastb命令

20、使用Fail2ban进行防护

篇幅过长不再讲述,可以看我原文,里面详细介绍了Fail2ban防止SSH爆破、Nginx CC攻击等行为的处理

https://blog.opennw.cn/archives/fail2ban