之前在住处用 Ubiquiti 家的 EdgeRouter X,那玩意差不多是刚毕业那会买的,那时候用的是个小米路由器,在家里设备多所以天天吃满 U 和内存导致路由器重启。然后合计着就换了 ER-X,换完那是一个香啊(毕竟 100Mbps 的带宽家用能搞出啥幺蛾子)!然后再也没折腾过路由。。。

直到最近,因为疫情的关系电信给大部分地区都上了免费提速(给到 500 下 30 上),所以薅上发现家里到不了 500Mbps。看了下大概是 CPU 跑不上了,因为也想倒腾所以查也不查也决定去搞个软路由了。

一开始是直接以挑低功耗电脑为方向去挑,后来想想似乎也没有必要搞那么高的配置,而且有句话说的好「200 预算软路由,2000 已付提电脑」所以最后选了树莓派做软路由。自己以前是把玩过树莓派,也多少知道有些坑

不过 Pi 的优点也不少,比如低功耗、占地面积小(0.000000001 平方米,别介),相对于普通「硬路由」他能够提供我们比较熟悉的 Linux 环境去搞事情,也就是我们看中的软路由的「软」。

打算拿软路由做啥

先说说目前用 ER-X 的痛点吧

之前拿 ER-X 做过分流的东西,但整体因为 U 性能不太好,所以走 iptables + ipset 来解决分流规则过多的问题,然后跑个梯子有时候挺呛。

所以就目前来说,我是打算做一个精简的路由,然后适当的佐以监控能力(毕竟有时候 163 抖得很),配点 DoH、路由优化(比如部分海外流量走 CN2 出去)就差不多了。

交代下

整理后的网络拓扑(瞎鸡儿画)

top

以上有几个点

  1. USB 3.0 网卡是 eth1,为啥拿他接公网,因为公网大多小,需求量不那么大,所以选他
  2. eth1 本身是有光猫内网的,所以我们平时如果 Pi 的内网丢了可以通过光猫内网去调试。再不行只能 HDMI 大法了
  3. eth0 是 Pi 的千兆口做内网对接比较舒服
  4. 我的拓扑有多一层交换机,但从这层开始就看各自的网络情况了,并非必须。
  5. PPPoE 在光猫层做桥接模式在 Pi 上拨号是为了少一层 NAT 也更便于控制
  6. 光猫内网是 192.168.1.1/24,Pi 自己划分的内网是 10.7.1.1/24(没啥关系,主要是蛮交代下)

完成基本路由功能需要搞啥

就以上这三个就足够实现基本路由能力。

那就开搞吧,先把 eth0(Pi 自带网口)接上光猫,然后上去盲配下 eth1(毕竟一会要拿 USB 去跟光猫 py)。netplan 配置到跟下面的情况差不多就好了

[email protected]:~$ cat /etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    ethernets:
        eth0:
            addresses:
              - 10.7.1.1/24
            gateway4: 10.7.1.1
            dhcp4: false
            dhcp6: false
        eth1:
            dhcp4: true
            dhcp4-overrides:
              use-routes: false
            optional: true
    version: 2

eth0 这边我们预先写了静态 IP(因为后面 DHCP 要用,总不能厚着脸皮也要 DHCP 分配吧,它都不认你),注意不要给 eth0 加optional: true,这个参数会让 eth0 还没有 UP 的时候就认为 network.target 启动完毕导致后续 DHCP 启动的时候会读 eth0 会发现没有 IP(如果两个启动时间挨得近的话)。

eth1 这边走 DHCP 去找光猫要个地址方便管理,然后 user-routes: false 那边主要是不想路由被加上 default via 192.168.1.1 的默认路由来影响后续的控制,毕竟后续咱们默认走的都是 PPPoE 的口子出去。

然后这时候以极快的速度 netplan apply 然后把 eth0 上光猫的线切到 eth1 上,然后 eth0 接上交换机(或者你的路由器)。然后静静等光猫分配 IP 给 Pi(这时候谁也不知道 IP 是啥,自己上光猫界面或者拿 nmap 扫下)。

DHCP Server

老套路,就用 isc-dhcp-server 吧,一把梭 apt install isc-dhcp-server -y over。然后配一下配置

[email protected]:~# cat /etc/dhcp/dhcpd.conf | grep -iv '#'

option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

authoritative;

subnet 10.7.1.0 netmask 255.255.255.0 {
  option routers 10.7.1.1;
  option subnet-mask 255.255.255.0;
  option domain-name-servers 119.29.29.29, 223.5.5.5;
  range 10.7.1.100 10.7.1.254;
}

[email protected]:~# cat /etc/default/isc-dhcp-server
# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf

# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPDv4_PID=/var/run/dhcpd.pid
#DHCPDv6_PID=/var/run/dhcpd6.pid

# Additional options to start dhcpd with.
#   Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#   Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="eth0"
INTERFACESv6="eth0"

以上 dhcpd.conf 我主要是增加了一个 subnet,这块就按需调整吧。然后在 /etc/default/isc-dhcp-server 里面指定下我们做内网的口子 eth0

接着

systemctl enable isc-dhcp-server
systemctl restart isc-dhcp-servere

那 DHCP 就差不多了,找个东西插一下 eth0 看看能不能拿到 IP 就差不多了。

PPPoE

把 WAN 口接上线连到 eth1(如果不先链接 pppoeconf 扫口的时候会扫不到),装下 pppoeconf然后配置下就好。

apt install pppoeconf -y
pppoeconf  # 开始配置,然后该怎么填怎么填了

安装完后检查下确认 ppp0 这个口起来了,也拿到了公网 IP(也可能是内网)大概就像下面

5: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 qdisc fq_codel state UNKNOWN group default qlen 3
    link/ppp
    inet 8.8.8.8 peer 8.8.8.1/32 scope global ppp0
       valid_lft forever preferred_lft forever

上面 netplan 如果没有加上 use-routes: false 会导致一个结果就是你有两条 metric 相同的 default route 结果就是上不了公网。所以一定要配!

iptables/NAT

那接下来配下 NAT 就更简单了。

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

# 临时开下 IPv4 的转发,如果你要持久生效自行改下 sysctl 配置
sysctl -w net.ipv4.ip_forward=1

记得做下持久化(save 和 restore)!

我这边实际用的是 nftables,所以配置大概长这样

[email protected]:~# cat /etc/nftables.conf
#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0;
    }
    chain forward {
        type filter hook forward priority 0;
    }
    chain output {
        type filter hook output priority 0;
    }
}

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "ppp0" masquerade
    }
}

总结

那基本上一个能跑的软路由就是这样了,没啥东西,就是有些坑得踩踩。

其实在配的过程中,更多考虑了怎么做快速切备用(哪天派炸了得切走),以及一些备用的方案,但这些各自网络环境不同所以也就不赘述了。

那接下来大概还可以做什么

以上只是简单记录下配置的过程,并不是最终教程,如果是没把握尽量别按这个来,不然到时候就局域网了。