标签: Ubuntu

  • (使用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

    参考文献