Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

软路由折腾记 #22

Open
fanchangyong opened this issue Feb 7, 2020 · 0 comments
Open

软路由折腾记 #22

fanchangyong opened this issue Feb 7, 2020 · 0 comments

Comments

@fanchangyong
Copy link
Owner

前言

很早之前就听说过软路由,但一直没折腾,最近花了几天时间把很多年之前的一台旧主机做成了软路由系统,供家里的设备科学上网使用。整个过程大概耗费了40小时以上,比我预想的麻烦很多,可以说历经坎坷,所以用一篇文章来记录一下。

架构

首先说一下我这台主机,这是一台10年前的老机器了,本来打算当废品卖掉的,但根本没人收,所以一直在角落里扔着。几个月之前,突然想搞一台下载机,我本来是有一台群晖NAS的,但那个配置太低,很多操作非常卡,也不支持docker安装一些下载服务。在网上看了些资料之后,就打算找台电脑来做NAS+下载机。这时候就想到了我那台旧主机,开机之后发现配置还不算低,2核CPU+2G内存+2T硬盘。用来做NAS可以说绰绰有余了。接下来就给那台电脑装了openmediavalt系统,加一些下载服务。

这次的软路由就是基于那台电脑的。本来以为要想用电脑做路由必须要有双网口,后来研究发现可以用旁路由的方式,来使用"硬路由+软路由"的方案,避免改动现有的网络环境,就可以直接让局域网内的所有设备都走软路由。这种方式对我来说是最完美的,可能也是适合于大多数人的方案。

我不想动现有的系统,所以软路由系统想基于虚拟机来装。现在的系统架构如下:

  • 物理机系统是openmediavault,这是一种NAS用的系统,基本可以理解为Debian系统上添加了一些NAS用的应用服务,所以基本可以当作一台Debian来用。我的Debian版本是 Debian GNU/Linux 9.11 (stretch),以下的介绍都是基于我的系统版本。
  • 虚拟机我使用KVM,严格来讲是KVM+QEMU
  • 软路由系统我是用的OpenWRT
  • 有了软路由,当然要装一些服务。我这台软路由主要用来科学上网用,我用的是V2RAY
  • 通过DHCP的设置,使局域网中的所有设备网关都指向软路由(这也就是旁路由的意思)

下面我们就依次讲一下这几个部分的安装以及中间可能遇到的坑

KVM虚拟机

简介

按照我的系统架构,我需要把软路由系统OpenWRT安装在虚拟机之上,首先我需要的就是一个虚拟机管理系统。Linux上可选择的虚拟机系统有VMWare的相关产品、VirtualBox等,我最终选用的是KVM+QEMU的方案。由于我这台主机没有安装GUI界面,所以所有操作都是用命令行来完成的。要想使用KVM虚拟机,我们需要安装以下几个包:

# 添加--no-install-recommends是避免安装额外的GUI程序
apt-get install --no-install-recommends qemu-kvm libvirt-clients libvirt-daemon-system 

KVM是内核中的一个模块,可以使用命令lsmod|grep kvm来检查KVM模块是否已经加载。如果未加载,可以使用modprobe kvm来加载KVM模块。

KVM最令人迷惑的地方在于,它要和很多其他的命令配合才能工作。在这里我简单介绍一下KVM虚拟机体系中的几个主要的组成部分(我自己的理解,不一定准确,如果想深入研究KVM推荐一本书<KVM虚拟化技术-实战与原理解析>):

  • KVM - 是一个内核模块,运行在内核空间,主要与硬件打交道,比如打开CPU的虚拟模式、捕获CPU的一些指令,然后有KVM决定如何处理等。
  • QEMU - 是一个开源的虚拟机软件,它是一个纯软件的实现,所以性能低下。但是可以与KVM相互配合以实现硬件的虚拟化,从QEMU的角度看,也可以说KVM帮QEMU实现了硬件加速。严格来说我们使用的是qemu-kvm,这是QEMU针对KVM专门做了修改和优化的一个分支。
  • libvirt - 是一套用于管理虚拟机的API和管理工具,不仅支持KVM,还支持Xen、VMWare、VirtualBox等虚拟机。我们之后使用到的管理虚拟机的命令包括virt-install、virsh等都是基于libvirt的。
  • virt-install - 用于创建一个新的虚拟机(provision new virtual machines),具体参见man virt-install
  • virtsh - 用于虚拟机的管理,比如启动(start),关机(shutdown),连接控制台(console)等。

桥接网络(Bridging)

在创建KVM虚拟机之前,我们还需要在物理主机上配置一下网络。由于我们这台虚拟机是用来安装软路由的,这就要求虚拟机的网络可以被局域网中的其他主机访问到。这里就需要用到桥接网络(Bridging)。我们可以编辑/etc/network/interfaces文件,然后写入以下内容(具体内容可能需要根据你的实际情况发生改变,以下内容来自:https://wiki.debian.org/KVM,经过修改):

auto lo
iface lo inet loopback

# The primary network interface
auto enp2s0

#make sure we don't get addresses on our raw device
iface enp2s0 inet manual
iface enp2s0 inet6 manual

#set up bridge and give it a static ip
auto br0
# 这里一定要用static地址,因为后面我们会停掉硬路由上的DHCP服务
iface br0 inet static
        address 192.168.0.3
        network 192.168.0.0
        netmask 255.255.255.0
        bridge_ports enp2s0
        bridge_stp off
        bridge_fd 0
        bridge_maxwait 0
        # dns-nameservers 8.8.8.8

#allow autoconf for ipv6
iface br0 inet6 auto
        accept_ra 1

编辑好文件之后,执行/etc/init.d/networking restart,等待命令执行完,再执行ifconfig,如果出现一个br0的网络接口,并且有正常的inet地址,而原先的enp2s0(或者其他名字,视你自己的系统而定)上没有inet地址了,就说明配置正常了。我的输出如下:

root@openmediavault:~# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.3  netmask 255.255.255.0  broadcast 192.168.0.255
        ether 1c:6f:65:75:48:07  txqueuelen 1000  (Ethernet)
        RX packets 985513  bytes 137311798 (130.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 225589  bytes 38455627 (36.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 1c:6f:65:75:48:07  txqueuelen 1000  (Ethernet)
        RX packets 49645765  bytes 50472427908 (47.0 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 47479005  bytes 47178385246 (43.9 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 305509  bytes 65444098 (62.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 305509  bytes 65444098 (62.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vnet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether fe:54:00:45:a5:2f  txqueuelen 1000  (Ethernet)
        RX packets 47243655  bytes 47139285303 (43.9 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49504310  bytes 50418051105 (46.9 GiB)
        TX errors 0  dropped 615 overruns 0  carrier 0  collisions 0

创建虚拟机

配置好桥接网络之后,我们就可以创建OpenWRT虚拟机了。
命令如下:

# 去OpenWRT官网下载系统文件
wget https://downloads.openwrt.org/releases/19.07.1/targets/x86/64/openwrt-19.07.1-x86-64-combined-ext4.img.gz
# 解压.gz文件,得到.img文件
gzip openwrt-19.07.1-x86-64-combined-ext4.img.gz -d
# 创建虚拟机
# --ram和--vcpus分别指定虚拟机的可用内存和CPU数量,可以按你自己的情况修改
# --disk path指定虚拟机系统文件的地址
# --network bridge=br0指定桥接网卡的名字
# 这个命令可能不会自动退出,可以ctrl-c退出命令
virt-install --name=openwrt --ram=1024 --vcpus=2 --os-type=linux --disk path=openwrt-19.07.1-x86-64-combined-ext4.img,bus=ide --network bridge=br0,model=e1000 --import

执行完上述命令后,虚拟机应该就创建完成了,可以查看一下:

root@openmediavault:~# virsh list
 Id    Name                           State
----------------------------------------------------
 1     openwrt                        running

如果有上面的输出,说明虚拟机已经成功创建并启动,可以进行下一步

连接虚拟机

虚拟机创建好之后,我们可以通过virsh console openwrt命令来连接虚拟机的控制台。然后可以通过ifconfig命令查看openwrt系统的网络配置,这时候在浏览器中访问它的IP地址应该就可以打开OpenWRT的管理页面了。如图所示:
OpenWRT管理页面

密码默认为空,直接点击Login按钮就可以进入OpenWRT系统了。到这里虚拟机和OpenWRT的安装就完成了。

旁路由

旁路由有以下几个特点:

  1. 系统中两个路由,一个主路由和一个旁路由,且主路由和旁路由是同一个网段
  2. 局域网中的设备的上网路径为:

网络IP配置

现在就要来说一下网络的连接和配置了,这很重要而且比较容易出错,我就拿我自己的网络配置来举例:

  1. 我的硬路由地址是192.168.0.1,这是个无线路由,家里所有设备都通过这台路由来上网(其实它的上级还有一个光猫自带的路由,地址是192.168.1.1,但我没有直接用它上网,而且上级路由的配置对我们这里没有影响,所以可以忽略)。
  2. 软路由所在的机器通过网线连接到路由器的LAN口,网络通过桥接接口上网,地址为:192.168.0.3
  3. OpenWRT所在虚拟机通过物理机的桥接接口上网,地址为:192.168.0.2

其中OpenWRT的配置在下面章节中会有介绍。

通过上面的步骤,安装好OpenWRT之后,局域网内的设备默认还是通过硬路由来上网的。这个时候我们找一台设备,将它的网络设置为手动设置地址,然后改为以下配置:

# IP:192.168.0.10,或者和软路由同网段的任意其他地址
# Netmask: 255.255.255.0,网络掩码
# Gateway: 192.168.0.2,这里是关键,指定网关为软路由OpenWRT的地址
# DNS: 8.8.8.8

然后我们通过traceroute命令看一下网络连接的路径:

> traceroute baidu.com
 1  192.168.0.2  1.990 ms  1.588 ms  1.522 ms
 2  192.168.0.1  2.417 ms  1.802 ms  1.760 ms
 3  192.168.1.1  2.457 ms  2.254 ms  2.413 ms
 4  123.171.14.1  100.916 ms  6.028 ms  5.843 ms
 ...

通过以上命令,我们会发现,网络包会先走192.168.0.2(软路由),然后再到192.168.0.1(硬路由),说明OpenWRT以及网络配置可以正常工作。如果这一步出问题,就要先检查一下是哪一步出了问题,再往下进行。这一步是软路由可以正常工作的核心。

自动走软路由

通过上述配置,可以实现想要走软路由的设备就走软路由,其他设备还是直接走硬路由上网。但如果我们想要让局域网中的所有设备都自动走软路由,就需要另外一步设置,关闭硬路由中的DHCP服务,并打开软路由上的DHCP服务。
首先进入硬路由的管理页面,关闭它的DHCP服务。然后进入OpenWRT的管理页面,进入:Network->Interfaces->LAN->Edit,如下图:

OpenWRT Interfaces

OpenWRT的具体配置如下图:

OpenWRT Interfaces General Settings

OpenWRT的DHCP服务配置如下图:

OpenWRT Interfaces DHCP Setting

通过这一步的设置,局域网内的设备都会自动将网关地址指向软路由,实现先走软路由再走硬路由的网络路径。至此旁路由的设置完毕。

V2Ray

安装

通过之前的设置,我们已经可以将网络的路径转移到软路由上,由软路由将网络包处理之后再通过硬路由发到Internet。也就是说我们的软路由可以看作是一个"应用路由器",也就是可以跑应用的路由。

OpenWRT上可以安装众多的软件,对我来说比较有吸引力的功能主要就是科学上网。我这次选择的软件是V2Ray,下面说一下安装过程:

  1. 安装v2ray-core,也就是v2ray的执行程序:
# 命令来自于:https://github.com/kuoruan/openwrt-v2ray

wget -O kuoruan-public.key http://openwrt.kuoruan.net/packages/public.key
opkg-key add kuoruan-public.key
echo "src/gz kuoruan_packages http://openwrt.kuoruan.net/packages/releases/$(. /etc/openwrt_release ; echo $DISTRIB_ARCH)" \
  >> /etc/opkg/customfeeds.conf
opkg update
opkg install v2ray-core  
  1. 安装luci-app-v2ray,luci指的就是OpenWRT的网页管理页面,这个包是v2ray在网页上的一个插件,安装了它就可以实现在网页中配置V2RAY,而不需要手动去系统中配置。
# 命令来自于:https://github.com/kuoruan/luci-app-v2ray
wget -O kuoruan-public.key http://openwrt.kuoruan.net/packages/public.key
opkg-key add kuoruan-public.key
echo "src/gz kuoruan_universal http://openwrt.kuoruan.net/packages/releases/all" \
  >> /etc/opkg/customfeeds.conf
opkg update
opkg install luci-app-v2ray
# 下面命令用于汉化,非必须
opkg install luci-i18n-v2ray-zh-cn

安装完成之后,在OpenWRT的顶级菜单中应该会出现一个Services菜单,下拉选项中会有一个V2Ray的选项,如下图:
Services

点击V2Ray就可以进入V2Ray的管理页面。

配置

V2Ray的工作原理和基本概念我们这里就不讲了,直接看一下我的具体配置:

  1. 首先是General Settings页面:
    V2Ray General Settings

  2. V2Ray Inbound的配置:
    V2Ray Inbound

  3. V2Ray Outbound的配置:
    V2Ray Outbound

  4. V2Ray DNS配置:
    V2Ray DNS

  5. Routing用来决定哪些请求走proxy,哪些不走,所以也是比较重要的:
    V2ay Routing

  6. 接下来配置V2Ray的透明代理,这一步也非常重要,因为只有配了这里,网络请求才会通过V2Ray做处理,否则V2Ray是没有效果的。
    我之前由于没有看到这个选项框,跟着V2Ray官网用iptables命令手动配置的透明代理,会导致每次重启V2Ray服务iptables都会被清空,都需要重新执行。后来通过看luci-app-v2ray的源码才追踪到原来在网页上就可以如此简单的配置(坑太多了,说多都是泪..)

Transparent Proxy

通过以上配置,我们应该就可以科学上网了。

总结

在这篇文章中,我们依次安装配置了KVM虚拟机,并在其上创建了OpenWRT虚拟机系统。通过配置OpenWRT以及硬路由的DHCP,实现自动"绕路软路由"的旁路由设置。再通过安装配置V2Ray,实现了软路由的最终目的:科学上网。

经过这几天的体验,使用路由器科学上网有几个好处:

  1. 所有设备自动走代理,包括电视盒或其他一些不方便设置代理的设备,都可以无缝科学上网了。
  2. 所有软件都会走代理,当然这只限于基于TCP/UDP协议的软件,比如git clone/push,brew等,之前一直非常慢。如果代理软件是跑在本机上的,这些软件是不会自动使用代理的,如果想使用代理就需要手动去配置,非常麻烦。现在可以非常顺畅地使用了。这里注意由于V2Ray是在Transport Layer(TCP/UDP)做代理,所以类似于ping这种命令是不会走代理的。

最后,致敬李文亮医生:一个健康的社会,不应该只有一种声音。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant