使用 clash 搭建透明网关实现旁路科学上网自由

使用 clash 搭建透明网关实现旁路科学上网自由

基于 Ubuntu 20.04.3 LTS 搭建 Clash 服务实现旁路网关功能,为局域网设备提供科学上网

前言

不知怎么的 LEDE 软路由 上的 ssv2ray 突然不能访问外网了(科学上网失败😭),与朋友沟通后发现不止我一个人这样(估计是机场的问题吧),索性就折腾一番,把之前搭建的旁路 LEDE 软路由给去掉,换成 clash 做旁路网关吧

安装 clash

  1. 下载 clash

    shell
    1
    # wget https://github.com/Dreamacro/clash/releases/download/v1.8.0/clash-linux-amd64-v1.8.0.gz
  2. 解压并安装 clash 二进制文件

    shell
    1
    2
    # gzip -d clash-linux-amd64-v1.8.0.gz
    # install clash-linux-amd64-v1.8.0 /usr/local/bin/clash
  3. 创建 clash 的 systemd 配置文件

    /etc/systemd/system/clash.service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [Unit]
    Description=Clash daemon, A rule-based proxy in Go.
    After=network.target

    [Service]
    Type=simple
    Restart=always
    ExecStart=/usr/local/bin/clash -d /etc/clash

    [Install]
    WantedBy=multi-user.target
  4. 设置 clash 为开机自动启,并启动该服务

    shell
    1
    2
    # systemctl enable clash
    # systemctl start clash
  5. 查看 clash 服务状态

    shell
    1
    # systemctl status clash
  6. 导入 clash web 管理界面

    shell
    1
    # git clone -b gh-pages --depth 1 https://github.com/Dreamacro/clash-dashboard /opt/clash-dashboard

流量转发

开启 Linux 内核的转发功能

注意:如果不开启该功能则可能存在内网设备无法访问问题


  1. 编辑配置文件 /etc/sysctl.conf 并向其中添加如下内容

    /etc/sysctl.conf
    1
    net.ipv4.ip_forward=1
  2. 保存退出后,执行以下命令使修改生效

    shell
    1
    # sysctl -p
  3. 查看 /proc/sys/net/ipv4/ip_forward 的内容,如果是 1 表示设置成功生效

nftables

使用 nftables 替代 iptables 做流量转发,如果不想用 nftables 也可以使用添加如下 iptables 规则

shell>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
iptables -t nat -N clash
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
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
iptables -t nat -A clash -p tcp -j REDIRECT --to-port 7892
iptables -t nat -A PREROUTING -p tcp -j clash
  1. 安装 nftables

    shell
    1
    # apt -y install nftables
  2. 创建 nftables 配置文件扩展目录

    shell
    1
    # mkdir /etc/nftables.conf.d
  3. 创建私有地址的定义文件

    /etc/nftables.conf.d/private.nft
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    define private_list = {
    0.0.0.0/8,
    10.0.0.0/8,
    127.0.0.0/8,
    169.254.0.0/16,
    172.16.0.0/12,
    192.168.0.0/16,
    224.0.0.0/4,
    240.0.0.0/4
    }
  4. 修改 nftalbes 配置文件,内容如下

    /etc/nftables.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/usr/sbin/nft -f

    include "/etc/nftables.conf.d/private.nft"

    table ip nat {
    chain proxy {
    ip daddr $private_list return
    ip protocol tcp redirect to :7892
    }
    chain prerouting {
    type nat hook prerouting priority 0; policy accept;
    jump proxy
    }
    }
  5. 清空 nftalbes 规则,并使新规则生效

    shell
    1
    2
    # nft flush ruleset
    # nft -f /etc/nftables.conf
  6. 查看 nftalbes 当前规则

    shell
    1
    # nft list ruleset
  7. 设置 nftalbes 开机自启动

    shell
    1
    systemctl enable nftables

配置机场订阅

订阅脚本

  1. 安装 Ruby,选用 Ruby 是为了更简单的解析 yaml 格式文件,如果选用 Python 则还需要安装 PyYAML 库才能使用,而 Ruby 则可以直接解析该格式文件

    shell
    1
    # apt -y install ruby
  2. 创建订阅脚本与配置文件存放目录

    shell
    1
    # mkdir /etc/subladder
  3. 创建 clash 基础信息配置文件,并写入如下内容

    注意:nameserverfallback 设置为如此是为解决 DNS 污染问题(参考:DNS污染对Clash(for-Windows)的影响之dns污染会怎样

    本人不幸中招过,设置 nameserveripv4 的 DNS 服务器,例如 114.114.114.114 时,作为透明网关访问 google.com 时被劫持到轮子网站上了(# ̄~ ̄#),妈的轮子死全家


    /etc/subladder/config.yaml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    # HTTP 代理端口
    port: 7890
    # SOCKS5 代理端口
    socks-port: 7891
    # Linux 和 macOS 的 redir 代理端口
    redir-port: 7892
    # 允许局域网的连接
    allow-lan: true
    # 规则模式:Rule(规则) rules/ Global(全局代理)/ Direct(全局直连)
    mode: rule
    # 设置日志输出级别 (默认级别:silent,即不输出任何内容,以避免因日志内容过大而导致程序内存溢出)。
    # 5 个级别:silent / info / warning / error / debug。级别越高日志输出量越大,越倾向于调试,若需要请自行开启。
    log-level: silent
    # Clash 的 RESTful API
    external-controller: '0.0.0.0:9090'
    # RESTful API 的口令
    secret: ''
    # 您可以将静态网页资源(如 clash-dashboard)放置在一个目录中,clash 将会服务于 `RESTful API/ui`
    # 参数应填写配置目录的相对路径或绝对路径。
    external-ui: /opt/clash-dashboard
    dns:
    enable: true
    ipv6: false
    # DNS 绑定在 5352/udp 端口上,提供给 unbound 使用
    listen: 0.0.0.0:5352
    enhanced-mode: redir-host
    default-nameserver:
    - 119.29.29.29
    - 223.5.5.5
    nameserver:
    - 'https://doh.pub/dns-query'
    - 'https://dns.alidns.com/dns-query'
    - 'tls://dns.rubyfish.cn:853'
    fallback:
    - 'https://dns.google/dns-query'
    - 'https://1.1.1.1/dns-query'
    - 'tls://1.1.1.1:853'
    - 'tcp://1.1.1.1:53'
    - 'tcp://208.67.222.222:443'
    - 'tls://dns.google'
    fallback-filter:
    geoip: true
    ipcidr:
    - 240.0.0.0/4
    - 127.0.0.1/8
    - 0.0.0.0/32
    domain:
    - +.google.com
    - +.facebook.com
    - +.twitter.com
    - +.youtube.com
    - +.xn--ngstr-lra8j.com
    - +.google.cn
    - +.googleapis.cn
    - +.googleapis.com
    - +.gvt1.com
  4. 创建 Ruby 脚本,用于合并 clash 基础信息配置文件与机场订阅配置文件,机场配置文件仅适用于 自由鲸,如使用其他机场请自行修改脚本内容

    /etc/subladder/subladder.rb
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #!/usr/bin/env ruby
    # -*- coding: UTF-8 -*-

    require 'yaml'

    raw = YAML.load_file(ENV['CLASH_SOURCE_REMOTE'] || 'remote.yaml')
    config = YAML.load_file(ENV['CLASH_SOURCE_CONFIG'] || 'config.yaml')

    update_whitelist = [
    "proxies",
    "proxy-groups",
    "rules"
    ]

    update_whitelist.each do |white|
    config[white] = raw[white]
    end

    config['proxies'].each do |proxie|
    if proxie['name'].include?'Tip' then
    config['proxies'].delete(proxie)
    end
    end

    config['proxy-groups'].each do |item|
    if item['name'] == 'Proxy' then
    item['proxies'].each do |proxie|
    if proxie.include?'Tip' then
    item['proxies'].delete(proxie)
    end
    end
    end
    end

    File.open(ENV['CLASH_RESULT_CONFIG'] || 'result.yaml', 'w') { |f| f.write config.to_yaml }
  5. 为脚本 subladder.rb 创建配置文件

    /etc/subladder/subladder.conf
    1
    2
    3
    4
    5
    6
    7
    8
    # 订阅地址
    ADDRESS="https://api.qiduo.eu.org/link/<你的私有key>"
    # 订阅的源文件缓存的文件名。被更新的字段来源的文件
    CLASH_SOURCE_REMOTE="remote.yaml"
    # clash 实际加载的配置文件。(以这个文件为基本配置文件,去更新关键的字段)
    CLASH_SOURCE_CONFIG="config.yaml"
    # 处理后的文件,更新了关键字段的结果文件
    CLASH_RESULT_CONFIG="/etc/clash/config.yaml"
  6. 创建名为 subladder.service 的 systemd 脚本

    /etc/systemd/system/subladder.service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [Unit]
    Description=Subscription Remote Configuration
    After=network.target

    [Service]
    Type=oneshot
    WorkingDirectory=/etc/subladder
    EnvironmentFile=/etc/subladder/subladder.conf
    ExecStartPre=/usr/bin/wget -O ${CLASH_SOURCE_REMOTE} ${ADDRESS}
    ExecStart=/usr/bin/ruby subladder.rb
    ExecStartPost=/bin/sh -c "systemctl restart clash.service"

    [Install]
    WantedBy=multi-user.target
  7. subladder.service 创建定时任务脚本 subladder.timer

    /etc/systemd/system/subladder.timer
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Unit]
    Description=Run Subladder Daily

    [Timer]
    #OnCalendar=daily
    OnCalendar=*-*-* 04:00:00
    RandomizedDelaySec=60m

    [Install]
    WantedBy=timers.target
  8. 启用定时器 subladder.timer

    shell
    1
    # systemctl enable subladder.timer
  9. 查看定时器

    shell
    1
    # systemctl list-timers

测试代理

  1. 运行一次 subladder.service

    shell
    1
    # systemctl start subladder
  2. 检查 /etc/clash/config.yaml 是否已生成

  3. 检查 clash 服务是否运行

    shell
    1
    # systemctl status clash
  4. 访问 clash web ui,http://ubuntu-server-ip:9090/ui

  5. 测试 http_proxy

    shell
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # export http_proxy="127.0.0.1:7890"
    # export https_proxy="127.0.0.1:7890"
    # export no_proxy="localhost, 127.0.0.1, 192.168.1.0/24, 10.0.0.0/8"
    # curl google.com
    <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
    <TITLE>301 Moved</TITLE></HEAD><BODY>
    <H1>301 Moved</H1>
    The document has moved
    <A HREF="http://www.google.com/">here</A>.
    </BODY></HTML>

配置 DNS

  • 通过 SmartDNS 查询国内 DNS 信息

  • 通过 Clash 查询国外 DNS 信息

  • 使用 dnsmasq-china-list 规则分流国内外流量

  • 使用 unbound 提供整合后的 DNS 服务

释放 udp 53 端口

  1. 检查 53 端口是否占用

    Ubuntu 上 53/udp 端口有可能被 systemd-resolve 服务占用

    shell
    1
    2
    3
    4
    # lsof -i :53
    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    systemd-r 650 systemd-resolve 12u IPv4 24448 0t0 UDP 127.0.0.53:domain
    systemd-r 650 systemd-resolve 13u IPv4 24449 0t0 TCP 127.0.0.53:domain (LISTEN)
  2. 编辑 /etc/systemd/resolved.conf 文件,取消 DNSDNSStubListener 的注释,并做如下改动

    /etc/systemd/resolved.conf
    1
    2
    3
    [Resolve]
    DNS=223.5.5.5
    DNSStubListener=no
  3. /etc/resolv.conf 创建软连接

    shell
    1
    ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
  4. 重启 systemd-resolved 服务

    shell
    1
    # systemctl restart systemd-resolved
  5. 再次查看端口占用

    shell
    1
    # lsof -i :53

SmartDNS

  1. 下载 SmartDNS

    shell
    1
    # wget https://github.com/pymumu/smartdns/releases/download/Release35/smartdns.1.2021.08.27-1923.x86_64-linux-all.tar.gz
  2. 解压压缩包

    shell
    1
    # tar -zxf smartdns.1.2021.08.27-1923.x86_64-linux-all.tar.gz
  3. 安装 SmartDNS

    shell
    1
    2
    # cd smartdns/
    # ./install -i
  4. 修改 SmartDNS 配置文件中如下内容

    可从 https://dns.iui.im/ 查询国内公共 DNS 服务器 IP 地址

    /etc/smartdns/smartdns.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 修改 dns 监听地址
    bind [::]:5351
    # 添加上游 dns 服务器
    server 223.5.5.5
    server 223.6.6.6
    server 8.8.8.8
    server 119.29.29.29
    server 182.254.116.116
    server 114.114.114.119
    server 114.114.114.114
    # 如果需要内网自定义解析域名则按如下格式
    address /git.akiya.cc/192.168.1.241
  5. 设置 SmartDNS 为开机自启动,并重启该服务

    shell
    1
    2
    # systemctl enable smartdns
    # systemctl restart smartdns

Unbound

  1. 安装 unbound

    shell
    1
    # apt -y install unbound
  2. 创建 /etc/default/unbound 配置文件,并写入如下内容

    /etc/default/unbound
    1
    2
    3
    # 这个默认会修改 /etc/resolv.conf 文件,设成 false 禁用掉
    RESOLVCONF="false"
    ROOT_TRUST_ANCHOR_UPDATE="false"
  3. 修改 unbound 配置文件

    /etc/unbound/unbound.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    server:
    verbosity: 1
    num-threads: 2
    interface: 0.0.0.0@53
    do-ip4: yes
    do-udp: yes
    do-tcp: no
    # 关掉上游 dns 才能使用本地 dns 服务
    do-not-query-localhost: no
    access-control: 0.0.0.0/0 allow
    include: "/etc/unbound/unbound.conf.d/*.conf"
    forward-zone:
    name: "."
    forward-addr: 127.0.0.1@5352
  4. 添加 unbound 到开机自动启

    shell
    1
    # systemctl enable unbound

dnsmasq-china-list

  1. 克隆 dnsmasq-china-list 项目

    shell
    1
    # git clone https://github.com/felixonmars/dnsmasq-china-list.git --depth 1
  2. 安装 make 工具

    shell
    1
    # apt -y install make
  3. 创建 unbound 配置文件

    shell
    1
    2
    # cd dnsmasq-china-list
    # make SERVER=127.0.0.1@5351 unbound
  4. 删除 /etc/unbound/unbound.conf.d/ 下默认配置文件后拷贝 dnsmasq-china-list 下创建的 unbound 配置文件该目录下

    shell
    1
    2
    # rm -f /etc/unbound/unbound.conf.d/*
    # cp *unbound.conf /etc/unbound/unbound.conf.d/
  5. 重启 unbound 服务

    shell
    1
    # systemctl restart unbound

使用透明网关

在路由器中把网关与 DNS 地址指向 Clash 服务器即可

  • 网络拓扑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
                               +----------------------+
| |
| internet |
| |
+-----------+----------+
|
|
+-----------+----------+
| |
+-------------------+ 10.10.10.254 +-------------------+
| | | |
| +----------------------+ |
| router |
| | |
| | |
+----------+-----------+ +-----------+----------+ +----------+-----------+
| | | | gateway| |
| 10.0.0.0/8 | | 10.10.254.253 +--------+ 10.10.254.254 |
| | | | | |
+----------------------+ +----------------------+ +----------------------+
PC&Server clash router
|
|
+-------------------------------+
| |
| |
+----------+-----------+ +----------+-----------+
| | | |
| 172.25.123.50 | | 172.25.123.53 |
| | | |
+----------------------+ +----------------------+
phone laptop
  • 路由器配置

  • 浏览器访问

  • 本地 dns 查询

    shell
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    $ dig google.com

    ; <<>> DiG 9.10.6 <<>> google.com
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22017
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 1280
    ;; QUESTION SECTION:
    ;google.com. IN A

    ;; ANSWER SECTION:
    google.com. 1 IN A 172.217.160.110

    ;; Query time: 2 msec
    ;; SERVER: 172.25.123.254#53(172.25.123.254)
    ;; WHEN: Wed Feb 23 15:36:25 CST 2022
    ;; MSG SIZE rcvd: 55

参考文章:

评论

:D 一言句子获取中...

加载中,最新评论有1分钟缓存...