Ubuntu 20.04 Server软路由配置折腾记录

记录一下最近的一次折腾,使用一台安装了Ubuntu 20.04 Server的工控机搭建软路由,并成功配置家庭NAS的内网访问。计算机网络没好好学,全靠本能debug,感谢lcy同志的全程技术科普(

本文主要参考了https://blog.lcy.im/2017/09/14/%E4%BB%8Eubuntu-server-%E5%BC%80%E5%A7%8B%E9%85%8D%E7%BD%AE%E8%87%AA%E5%8A%A8%E5%88%86%E6%B5%81%E7%9A%84%E8%BD%AF%E8%B7%AF%E7%94%B1/

网络拓扑设计

瞎画的,是这意思就行(逃

根节点是联通的WO-67光猫路由一体机,管理子网192.168.1.x(24是子网掩码的长度,意思是前24位是这个子网固定的地址前缀),其中包括一台桥接模式运行的电力猫,提供WIFI覆盖。我们希望安装一部软路由,管理192.168.2.x子网。软路由后面桥接一台TP-LINK路由器,该路由器提供WIFI覆盖(因为软路由没有无线功能)。此外,还需要在软路由上接一台群晖NAS,并希望在整个网络中提供对NAS的访问。

软路由系统准备

我买的主机就长这样。参数是,x86-64系统,4张网卡,4G内存,32G硬盘。下文中用“软路由”称呼这台机器。

一般这种软路由都是装lede/openwrt之类的系统,不过我要装一个比较正常的ubuntu,原因是后面还要配置自动分流。和店家交流后,他们表示能装ubuntu 16.04,是正常的桌面系统。不过我在一开始折腾的时候把这个系统搞挂了,于是决定换成ubuntu 20.04 server,这样的另一个好处是没有图形系统比较省电,跑桌面系统会肉眼可见地烫手,但是ubuntu server就不会。

这个软路由是带USB+HDMI+VGA接口的,也就是说插上屏幕键盘就能当台电脑用,所以装系统就是很普通的流程:从ubuntu官网上下载amd64版本的.iso文件,用win32diskimager把它刻进U盘,然后把这个安装盘插到软路由的USB接口上,接屏幕键盘启动,启动时按F7进入启动选项,选择由U盘启动,然后跟着流程走即可。这样软路由就装上了ubuntu 20.04 server。

这时需要解决一个奇怪的问题:系统不插VGA监视器无法启动,插HDMI都不行(似乎)。不确定是我软路由硬件的原因还是ubuntu server的原因。这个必须得处理,至少VGA那个分辨率看着也太费劲了……方法是按照这个教程:https://askubuntu.com/questions/825687/what-could-prevent-an-ubuntu-server-from-booting-without-a-vga-connected-monitor,在/etc/default/grub把GRUB_TERMINAL=console一行取消注释,指示系统启动时无需有图形界面。然后用sudo update-grub更新引导选项。在折腾的时候我还在BIOS里面把启动选项设置成了legacy,关闭UEFI,估计应该没用。

至此软路由在系统层面已经准备完毕(按需用apt装包略去不表),接下来开始配置网络。

网络接口配置

在较早的linux系统中,网络接口配置是通过/etc/network/interfaces文件完成的,但在18.04以后改成了一个叫做netplan的东西。netplan的问题是,它没有“allow-hotplug”选项的简单对应,因此还是换回了原来的配置方法:https://askubuntu.com/questions/1031709/ubuntu-18-04-switch-back-to-etc-network-interfaces,主要应该就是安装ifupdown包,然后卸载掉netplan相关的东西:

# systemctl stop systemd-networkd.socket systemd-networkd networkd-dispatcher systemd-networkd-wait-online
# systemctl disable systemd-networkd.socket systemd-networkd networkd-dispatcher systemd-networkd-wait-online
# systemctl mask systemd-networkd.socket systemd-networkd networkd-dispatcher systemd-networkd-wait-online
# apt-get --assume-yes purge nplan netplan.io

然后设置文件/etc/network/interfaces:

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto enp1s0
allow-hotplug enp1s0
iface enp1s0 inet static
    address 192.168.1.10/24
    gateway 192.168.1.1

iface enp2s0 inet manual
iface enp3s0 inet manual
iface enp4s0 inet manual

auto br0
iface br0 inet static
    bridge_ports enp2s0 enp3s0 enp4s0
        address 192.168.2.1/24

这里面lo就是localhost,不用管。enp1s0~enp4s0是软路由的四个网口,似乎有些机器上,它们的名字会叫作eth0,eth1之类,总之可以用命令ip a查询。我们用enp1s0作为WAN口,其他三个作为LAN口,把这三个桥接起来。

enp1s0需要有allow-hotplug,这个意思是,在软路由启动的时候即使WAN口没插线也能启动。如果不加,它自己倒是没什么问题,只是重启的时候会因为一个什么网络服务没有就绪等待两分钟。但麻烦的是,后面的dhcp服务器会无法正常启动,至少我是这样。可以看到,把WAN口在一级子网中的地址固定为了192.168.1.10,网关是光猫路由一体机。enp2s0~enp4s0的配置都是manual,因为它们的具体地址需要靠网桥br0完成。

auto br0这一句必不可少,它保障了在软路由启动的时候可以自动创建网桥(作为一个虚拟设备,好像是这么个意思),并且恰当地初始化三个LAN口。后面可以看到,bridge_ports这一句把三个LAN口桥接起来,并且规定地址(也就是软路由在二级子网中的地址)是192.168.2.1.

这样配置完/etc/network/interfaces之后,可以sudo service networking restart重启网络服务,然后用ifconfig查看网络信息,应该能看到lo,网桥和四个网口。可以重启软路由验证设置的正确性,重启之后不需要进行任何操作,networking服务会自动读取这个文件里面的配置,并创建相应的接口。

配置sysconf

在/etc/sysctl.conf里面添加如下内容,然后重启机器

net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

配置dhcp服务器

首先装包sudo apt install isc-dhcp-server

然后配置/etc/default/isc-dhcp-server,把ipv4和ipv6的接口都设置成我们的虚拟网桥br0:

INTERFACESv4="br0"
INTERFACESv6="br0"

然后设置具体的dhcp规则:

host synology-nas {
    hardware ethernet 00:11:32:93:0d:23;
    fixed-address 192.168.2.9;
}

subnet 192.168.2.0 netmask 255.255.255.0 {
    range 192.168.2.20 192.168.2.100;
    option routers 192.168.2.1;
    option domain-name-servers 192.168.2.1;
}

我这里添加了两条规则。第一条,是群晖NAS的ip地址固定为192.168.2.9,当然后缀2.9也没啥深意,只要不是192.168.2.1(软路由的ip地址)都行。hardware ethernet后面接的是NAS的MAC地址,这个如何查看呢?答案是把NAS用网线连到软路由上之后,用arp -n查看软路由的连接信息,其中的HWaddress项就是MAC地址。

第二条则是子网内的dhcp服务,地址池为192.168.2.20~192.168.2.100,网关是192.168.2.1,而最后一句dns服务器,这里是因为我使用了freedns-go:https://github.com/tuna/freedns-go,所以可以把dns服务器设置成软路由自身。如果没有,那就设成114.114.114.114,1.1.1.1,8.8.8.8之类的。

这样dhcp服务器设置完成,sudo service isc-dhcp-server restart重启dhcp服务器。这时候用网线连到路由器上,用ifconfig就能看到自动分配的地址。

配置自动nat访问互联网

然后还需要nat以访问互联网。命令是:

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

当然不能每次重启都敲这么一句,需要把它设置成一个自动启动的服务。ubuntu 20用systemd完成这件事情:https://www.howtogeek.com/687970/how-to-run-a-linux-program-at-startup-with-systemd/

首先我们创建一个文件start_nat.sh,内容如下:

#!/bin/sh
iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE

并且用sudo chmod +x start_nat.sh赋予执行权限,然后把它放到/usr/local/bin目录下。然后再创建一个文件/etc/systemd/system/start_nat.service,内容为

[Unit]
Description=Start NAT

[Service]
ExecStart=/usr/local/bin/start_nat.sh
RemainAfterExit=true

[Install]
WantedBy=multi-user.target

Description随便填。如果需要在.sh里面启动tmux(并且有可能在tmux里面运行某个程序),这个RemainAfterExit就必须要有。ExecStart是这个服务在启动的时候执行什么命令,也就是前面那个脚本start_nat.sh。然后我们把它的权限改成640:

sudo chmod 640 /etc/systemd/system/start_nat.service

这样我们就创建了一个名叫start_nat的服务。然后把它注册为启动时运行:

sudo systemctl daemon-reload
sudo systemctl enable start_nat
sudo systemctl start start_nat

最后那个start是现在就启动的意思。你也可以重启一次软路由。如果一切配置恰当,重启之后,连接软路由的电脑应该能直接连接到一个LAN并且正常访问互联网,无需进行任何操作。

NAS端口转发配置

到现在为止我们拥有了一个正常功能的路由器。但是我还希望在整个家庭局域网内访问NAS的各项服务,所以还需要额外折腾一下。具体来说有四个:web控制页面5051端口,webdav远程硬盘5006端口,synology drive群晖本地云6690端口,smb共享文件(比如说在‘我的电脑’里敲个\\192.168.2.9访问共享文件夹)445端口。

因此我们需要在软路由上配置四个端口转发,前三个随便更改了一下端口名称:

  • 软路由的16000端口转发至NAS的5051端口
  • 软路由的16006端口转发至NAS的5006端口
  • 软路由的16090端口转发至NAS的6690端口
  • 软路由的445端口转发至NAS的445端口

注意之前把NAS的ip地址固定为192.168.2.9了。每一个转发可以通过两条iptables命令实现,因此总共是八条,把它们添加到之前/usr/local/bin/start_nat.sh的末尾,这样每次软路由一启动就会自动完成转发设置。总的下来,start_nat.sh如下:

#!/bin/sh
iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 16000 -j DNAT --to-destination 192.168.2.9:5051
iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.9 --dport 5051 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 16006 -j DNAT --to-destination 192.168.2.9:5006
iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.9 --dport 5006 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 16090 -j DNAT --to-destination 192.168.2.9:6690
iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.9 --dport 6690 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 445 -j DNAT --to-destination 192.168.2.9:445
iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.9 --dport 445 -j MASQUERADE

这样,比如说,在家庭局域网任意位置访问192.168.1.10:16000即可访问NAS的5051端口。

路由器桥接,收尾工作

在折腾之前家里的路由器不是桥接模式而是路由模式。需要更改一下。总的来说,从路由模式切换成桥接模式需要做三件事:

  • 把WAN口网线拔掉插到LAN口
  • 登录路由器管理界面,关闭dhcp
  • 在路由器管理界面手动设置一个LAN口ip地址,不要冲突

其中我遇到了一件奇怪的事情,就是设置TP-LINK路由器的时候,一开始忘了关dhcp,后来才关掉,但此时连接它WIFI的电脑会始终显示网关是192.168.2.2,也就是这台路由器的地址,而非正确的软路由地址192.168.2.1。然后通过在电脑上手动设置ip,dns服务器和网关(设为软路由地址),然后再把ip改回自动模式,解决了问题,这个方法有点奇怪但总之work了,原理不明。

最后结果如图:

发表评论

电子邮件地址不会被公开。 必填项已用*标注