(使用VirtualBox)构建Ubuntu下的clash旁路由服务

效果图一张

截屏2020-11-16 下午10.55.42.png

几个月前写了一篇文章,讲怎么在Windows下面利用HyperV安装OpenWRT软路由。最近发现了几篇旁路由的文章,另外发现其实clash完全可以在ubuntu下面跑,不用再费那么多事情去研究OpenWRT了,于是乎就有了本文。

目标

本文的目标是利用一台Windows主机(或直接使用Linux主机)搭建一个旁路由服务器,这个服务器与我的光纤猫LAN口连接,提供网关服务,并且能够通过网页ui对clash服务进行配置修改。
需要使用旁路由服务的终端(或无线AP),可以通过手工设定网关地址与DNS地址来接驳到旁路由上;同时,需要默认路由服务的终端,只需使用默认DHCP服务即可。
施工完成后,家里的网络拓扑大致如下:

光纤猫 192.168.1.1
|- 192.168.1.21 旁路由服务器
|- 192.168.1.20 无线路由器(接驳旁路由网关192.168.1.21)
|                  |- 192.168.50.xxx 手机、iPad、笔电等终端
|- 192.168.1.19 电视机(无需旁路由服务,使用DHCP的网关192.168.1.1)
|- ...

硬件需求

任意主机,直接运行Ubuntu系统或使用Windows系统。服务器需要有一个网口。本人用来跑旁路由服务的主机是一台Intel J1900,4GB内存的主机。

VirtualBox配置

首先需要安装一个Ubuntu,我选择的是20.04LTS Server版本,所以没有图形化界面。

在系统安装好之后,关闭虚拟机,需要在VirtualBox里配置网络接口类型。默认的网络接口类型应该是NAT,这边找到主机连接光猫的那个网络接口,改为桥接。桥接的意思是,把虚拟主机看做一个独立的主机接入光纤猫的LAN网络,于是乎他就有了一个独立于物理机器的一个“平等的”IP地址了。这个IP地址也就是旁路由的网关地址。
VirtualBox-Bridge-Network.jpg

如果你的光猫可以配置静态IP地址分配的白名单,建议把这个旁路由的MAC地址对应的IP分配成静态的,避免因为光纤猫DHCP变动导致旁路由的IP地址不是一个静态值。

Ubuntu配置

允许ip转发

sudo vim /etc/sysctl.conf

找到 net.ipv4.ip_forward=1 这一行,取消掉注释。如果没有找到的话直接新增一行也可以的。随后执行

sudo sysctl -p

使修改生效。

配置iptables

依次执行下面的指令,注意注释的部分,修改成自己的网络配置

iptables -t nat -N clash
iptables -t nat -N clash_dns

# 这个是fake-ip对应的dns地址,一般不用动
iptables -t nat -A PREROUTING -p tcp --dport 53 -d 198.19.0.0/24 -j clash_dns
iptables -t nat -A PREROUTING -p udp --dport 53 -d 198.19.0.0/24 -j clash_dns
iptables -t nat -A PREROUTING -p tcp -j clash

# 这里需要注意的是,下面两行最后的 192.168.1.21 是当前旁路由的 IP 地址,请根据你自己的实际情况修改
# 如果你自己的旁路由 IP 跟下面的 IP 地址不对的话会造成无法翻墙
iptables -t nat -A clash_dns -p udp --dport 53 -d 198.19.0.0/24 -j DNAT --to-destination 192.168.1.21:53
iptables -t nat -A clash_dns -p tcp --dport 53 -d 198.19.0.0/24 -j DNAT --to-destination 192.168.1.21:53

# 绕过一些内网地址
iptables -t nat -A clash -d 0.0.0.0/8 -j RETURN
iptables -t nat -A clash -d 10.0.0.0/8 -j RETURN
iptables -t nat -A clash -d 127.0.0.0/8 -j RETURN
iptables -t nat -A clash -d 169.254.0.0/16 -j RETURN
iptables -t nat -A clash -d 172.16.0.0/12 -j RETURN
iptables -t nat -A clash -d 192.168.0.0/16 -j RETURN
iptables -t nat -A clash -d 224.0.0.0/4 -j RETURN
iptables -t nat -A clash -d 240.0.0.0/4 -j RETURN

# 注意, 这边的7892对应后续clash配置里的redir-port
iptables -t nat -A clash -p tcp -j REDIRECT --to-ports 7892

执行完上面的 iptables 命令之后,就完成了旁路由的路由功能了,但是此时 iptables 并没有永久保存,下次开机上面的配置就会丢失。为了使得重启之后 iptables 命令仍然存在,我们需要安装软件来实现:

sudo apt install iptables-persistent

安装的过程中会提示你是否需要保存 iptables 配置,直接选是就行。这时候即使电脑重启了也会应用这些路由规则。

如果后面你有需要重新修改 iptables 的配置,那么只需要在执行完 iptables 之后再执行:

sudo iptables-save > /etc/iptables/rules.v4

即可将最新的 iptables 规则保存下来。

下载Clash

# 下载最新版 clash,注意根据自己的系统下载对应的版本,我的是 64 位的,所以下载的是 linux-amd64 这个版本
wget https://github.com/Dreamacro/clash/releases/download/v1.3.0/clash-linux-amd64-v1.3.0.gz
# 解压并且把二进制文件放到 /usr/bin ,并且加上可执行权限
gzip -d clash-linux-amd64-v1.3.0.gz
sudo mv clash-linux-amd64-v1.3.0 /usr/bin/clash
sudo chmod +x /usr/bin/clash
# 为 clash 添加绑定低位端口的权限,这样运行 clash 的时候无需 root 权限
sudo setcap cap_net_bind_service=+ep /usr/bin/clash

DlerCloud用户需要注意,这边要下载Premium tag的版本以支持rule-set,否则启动会报配置错误。下载地址在https://github.com/Dreamacro/clash/releases/tag/premium。有兴趣了解此中区别的可以参考这篇Issue.

配置clash服务

运行 clash 之前需要先创建配置文件,否则 clash 无法启动:

# 创建文件夹
mkdir -p ~/.config/clash
cd ~/.config/clash
# 创建配置文件
touch config.yaml
vim config.yaml

在 config.yaml 文件里面填入下面的配置:

# 以下部分不要修改!
port: 7890
socks-port: 7891
redir-port: 7892
allow-lan: true

mode: Rule

log-level: info
# external-controller 主要是用于 web 端管理页面,必须监听在 0.0.0.0
external-controller: 0.0.0.0:9090

# secret 是进入管理面板所需要的密码,可填可不填,建议填上
secret: "secret-password"

# external-ui 表示管理面板的路径
external-ui: dashboard

dns:
  enable: true
  ipv6: false
  listen: 0.0.0.0:53
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - '192.168.1.1'

# 下面部分则是代理的设置跟规则的设置,这里忽略不写。
Proxy:
#...

实际操作中,如果遇到报错说53端口已经被占用了,可以把0.0.0.0这个通配的IP地址修改为主机所在的内网IP,对应我本人的情况就是192.168.1.21:53.
[更正] 这边最好不要改0.0.0.0,不然可能会遇到本机DNS出错的问题,一个办法是改用root用户启动服务.

如果需要校验配置文件是否合规,可以运行clash -t, 成功的话程序会输出”successful”字样。

(选修)DlerCloud配置文件自动下载及覆盖

一些使用DlerCloud的朋友可以拿到官方配置好的clash yaml,这边有个小的python脚本能够帮你自动下载原始的yaml然后覆盖一些配置,使得它能在服务器上的clash客户端使用。

import os
import subprocess
import shutil
import sys
import yaml

g_dler_config_url = '这边填入能够下载到yaml文件的网址'

g_items_to_update = {
    'port': 7890,
    'socks-port': 7891,
    'redir-port': 7892,
    'external-controller': '192.168.1.21:9090',
    'external-ui': 'dashboard',
    'secret': 'THE_HOLY_PASSWORD',  # 填写你的clash网页端管理密码
    'dns': {
        'enable': True,
        'ipv6': False,
        'listen': '192.168.1.21:53',
        'enhanced-mode': 'fake-ip',
        'fake-ip-range': '198.18.0.1/16',
        'nameserver': [
            '192.168.1.1',
        ],
    },
    'log-level': 'warning',
}

g_keys_to_remove = [
    'mixed-port',
]

def is_root():
    if sys.platform == 'linux':
        return os.geteuid() == 0
    else:
        raise ValueError('not linux!')

def update_yaml_and_save(input_path, output_path):
    with open(input_path, encoding='utf-8') as f:
        y = yaml.load(f, Loader=yaml.FullLoader)
    y.update(g_items_to_update)
    for key in g_keys_to_remove:
        del y[key]
    with open(output_path, 'w', encoding='utf-8') as f:
        yaml.dump(y, f, allow_unicode=True)

if __name__ == '__main__':
    # NOTE: 这边的文件路径按需修改
    input_path = '/home/ubuntu/Download/dler_orig.yaml'
    subprocess.run(['wget', g_dler_config_url, '-O', input_path])
    output_path = '/home/ubuntu/.config/clash/config.yaml'
    shutil.copy(output_path, output_path + '.bak')
    update_yaml_and_save(input_path, output_path)
    print('saved to %s, restarting service...'%output_path)
    subprocess.run(['sudo', 'systemctl', 'restart', 'clash.service'])
    print('done')

配置clash网页前端

这边选用第三方开发的yacd面板,源码在https://github.com/haishanh/yacd
具体安装方式就是把源码拷贝到上面配置文件中写好的位置:

# 先进入到配置文件的目录
cd ~/.config/clash
# 下载前端代码压缩包,如果要使用官方的管理面板则把链接替换成 https://github.com/Dreamacro/clash-dashboard/archive/gh-pages.zip
wget https://github.com/haishanh/yacd/archive/gh-pages.zip
# 解压缩并且把目录名改成 dashboard
unzip gh-pages.zip
mv yacd-gh-pages/ dashboard/

配置clash服务

sudo touch /etc/systemd/system/clash.service
sudo vim /etc/systemd/system/clash.service

然后填入下面的内容。注意把2处YOUR USER NAME的部分换成你自己的用户名
[更新] Ubuntu 18 实测如果用非root用户启动,会有DNS绑定低端口53失败的问题,最后我直接把下面的User改成User=root然后用sudo启了。不知道有没有更好的解法,希望大佬看到了能留个正解。

[Unit]
Description=clash daemon

[Service]
Type=simple
User=YOUR USER NAME
ExecStart=/usr/bin/clash -d /home/YOUR USER NAME/.config/clash/
Restart=on-failure

[Install]
WantedBy=multi-user.target

保存退出。然后启动clash服务并设置为开机启动:

# 启动 clash
sudo systemctl start clash.service
# 启动开机自启
sudo systemctl enable clash.service

如无意外的话这时候 clash 已经运行起来了,通过浏览器访问 http://192.168.1.80:9090/ui 就能看到 clash 的管理面板了。

运行Clash的机器本身无法联网?

这是因为使用了fake-ip模式,任何DNS请求都会响应成我们的fake-ip.

参考Ubuntu的代理配置,走的是bash分用户的配置文件。所以分别在自己用户和root下配置一个简单的function。打开~/.bashrc然后在最后加入以下内容:

# proxyon
proxyon() {
    export https_proxy=http://127.0.0.1:7890
    export http_proxy=http://127.0.0.1:7890
    export all_proxy=socks5://127.0.0.1:7891
    echo "HTTP/HTTPS Proxy on"
}

# proxyoff
proxyoff() {
    unset http_proxy
    unset https_proxy
    unset all_proxy
    echo "HTTP/HTTPS Proxy off"
}

保存后source ~/.bashrc让配置文件生效。 当需要使用代理时直接执行proxyon即可。

修改客户端的旁路由配置

不论是什么系统,若要使用旁路由作为网关,只要修改以下项目:

  • 手动配置IP地址(关闭DHCP),主机的IP地址可以是照抄DHCP分配给你的那个,或者在同一网段里自选一个不冲突的,按文中例子是192.168.1.X其中X!=1 && X!=21;
  • 子网掩码255.255.255.0
  • 网关地址192.168.1.21,也就是虚拟机旁路由的IP地址;
  • DNS配置198.19.0.1,如果要填次要DNS,可以填198.19.0.2

我把华为路由器接在了光猫的另一个LAN口(和旁路由平级),这边给一个华为路由器上的参考配置:
router-manual-ip.jpg

测速

家里的宽带是300Mbps,无线路由器使用旁路由作为上层网关后,亲测性能上是没问题的。Speedtest为证:
speedtest.jpg

参考文献

5 comments / Add your comment below

  1. 您好。
    fake-ip-range: 198.18.0.1/16 //这里是fake ip的网段
    DNS配置198.19.0.1,如果要填次要DNS,可以填198.19.0.2; //这里是旁路由的填写的DNS。
    都不处于同一网段下
    真的是这样写吗?

    1. 感谢回复。这两个确实不在一个网段上。

      如此配置是因为文章配置了iptables:
      iptables -t nat -A clash_dns -p udp –dport 53 -d 198.19.0.0/24 -j DNAT –to-destination 192.168.1.21:53
      iptables -t nat -A clash_dns -p tcp –dport 53 -d 198.19.0.0/24 -j DNAT –to-destination 192.168.1.21:53
      意思是经由198.19.0.0/24,端口53来的udp/tcp包全部转发至192.168.1.21:53的DNS服务器上。

      1. 谢回复

        若 DNS使用如下转发是否可以将DNS配置为198.18.0.1

        # 转发DNS请求到clash_dns链
        iptables -t nat -A PREROUTING -p tcp –dport 53 -j clash_dns
        iptables -t nat -A PREROUTING -p udp –dport 53 -j clash_dns

        # 转发tcp请求到clash链
        iptables -t nat -A PREROUTING -p tcp -j clash

        # 转发dns请求到网关
        iptables -t nat -A clash_dns -p udp –dport 53 -j DNAT –to-destination 10.0.0.200:53
        iptables -t nat -A clash_dns -p tcp –dport 53 -j DNAT –to-destination 10.0.0.200:53

        目前是和你使用的相同方案。不过我开启了tun。现阶也可以正常使用

发表评论

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

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据