使用Openwrt作为主路由,另一台Ubuntu 18.04主机上使用Docker运行Clash来作为网关进行转发,以达到按规则智能翻墙的目的。也是很多人提到的“旁路由”方法。
注:Openwrt可以直接编译OpenClash,我这次只是纯粹为了折腾而折腾。
1. Docker 的安装
首先在Ubuntu中安装Docker,直接apt安装即可
两个包 docker和 docker-compose
sudo apt install -y docker docker-compose
2. Clash配置文件准备
如果不熟悉vi或者nano建议先在自己电脑上编辑好再SSH传上去即可。一共两个文件 docker-compose.yml和 config.yaml
docker-compose.yml 是给docker启动的配置文件,示例如下:
version: '3'
services:
clash:
image: dreamacro/clash
volumes:
- ./config.yaml:/root/.config/clash/config.yaml
ports:
- "7890:7890"
- "7891:7891"
- "7892:7892"
- "9090:9090"
- "5353:5353/udp"
- "5353:5353/tcp"
restart: always
# When your system is Linux, you can use `network_mode: "host"` directly.
network_mode: "host"
container_name: clash
其中9090端口是给web ui用的,linux可以直接使用host模式,相当于把主机的网络直接套用给容器使用。 5353给Clash内置的DNS服务使用。不使用默认53端口是防止与Ubuntu自带的systemd冲突。
config.yaml 可以直接将你的Clash托管地址输入浏览器地址栏,会自动下载好包含节点的一个简单设置文件。下载好之后用编辑器打开,我们需要修改一些设置。以下为示例:
port: 7890 # Http代理端口
socks-port: 7891 # Socks 代理端口
redir-port: 7892 # 转发端口
# 因为是局域网转发所以此项必须设置为true
allow-lan: true
mode: Rule
# 日志等级先设置为info以便debug,没问题后设置为silent
log-level: info
# 为web ui设置端口为9090, 其中0.0.0.0为所有IP都可以访问
external-controller: 0.0.0.0:9090
# web ui的链接密码
secret: "123456"
# Clash 自带的DNS 设置,如果你的规则是基于地址的则必须使用。
dns:
enable: true
listen: 0.0.0.0:5353
enhanced-mode: redir-host
nameserver:
- 114.114.114.114
- tls://dns.rubyfish.cn:853
fallback:
- tcp://208.67.222.222:443
- tls://dns.google
# 以下为节点和规则,通常clash托管会自己有
Proxy:
- name: "?????"
type: vmess
server: ?????
port: 153
uuid: ????
alterId: 64
cipher: auto
network: ???
ws-headers:
Host: ????
注:使用Fake IP模式的配置文件
dns:
enable: true
listen: 0.0.0.0:5353
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter: # fake ip white domain list
- '*.lan'
- localhost.ptlogin2.qq.com
nameserver:
- 218.4.4.4
Fake-IP模式下会自动将符合proxy规则的域名解析需求发给代理服务器,所以不需要fallback,而且可以避免DNS污染。
3. 安装Nginx为web ui提供服务
直接用docker pull最新的nginx镜像,这里我们使用yacd作为管理Clash的web ui,安装也是非常简单的。
下载yacd到本地的目录
下载地址
下载好之后解压到一个本地目录,然后直接启动nginx把这个目录挂上去即可:
$ docker container run
-d
-p 127.0.0.2:8080:80
--rm
--name mynginx
--volume "your local yacd path":/usr/share/nginx/html
nginx
4. 配置systemd-resolve
因为53默认端口被占用,所以上面我们给Clash分配了5353端口用于DNS服务。尤其在使用Fake-IP的模式下,如果将Ubuntu自带的systemd-resolved干掉,DNS将会直接由Clash返回假IP,此时则必须配置代理服务器让流量经过代理端口。见第11节添加代理的设置。 推荐根据上面的设置,将Clash的DNS设置为其他端口则不会影响宿主机器本身的网络。建议设置Ubuntu本身直接走路由器,参考下面第五节。
不推荐因为在ubuntu中,DNS的端口53默认已经被占用,所以需要使用DNS的话就不能让systemd占用这个端口。这个问题耗费了我大概一个多小时,大部分的教程都没有提到这个问题。
sudo service systemd-resolved stop
sudo systemctl disable systemd-resolved
5. 为Ubuntu设置静态地址
因为后续要更改路由器下发的网关和DNS,而且本机也需要一个固定IP地址,所以设置静态IP是必须的。 新的Ubuntu使用netplan管理本地网络,通过yaml配置文件来实现。注意yaml文件的名称每个电脑可能不同。 打开文件 /etc/netplan/01-netcfg.yaml 注意netplan对缩进有严格的要求,而且不能用tab必须打空格,以下为我的文件结构:
network:
ethernets:
ens18:
dhcp4: no
addresses: [192.168.0.10/24, ]
gateway4: 192.168.0.1
nameservers:
addresses: [192.168.0.1, 8.8.4.4]
version: 2
保存此文件后使用以下命令让设置生效:
sudo netplan apply
然后通过ifconfig来查看设置是否已经起作用。
6. 配置iptables
参考网上其他人的配置,找到一个做的比较好的,请根据自己的网络更改IP地址段和ubuntu主机地址!! 可以写一个简单的bash批处理文件一次运行完成。
#!bin/bash
iptables -t nat -A PREROUTING -p tcp -j clash
iptables -t nat -A PREROUTING -p tcp --dport 53 -j clash_dns
iptables -t nat -A PREROUTING -p udp --dport 53 -j clash_dns
# 将收到的DNS请求转至Clash监听的5353端口。监听端口在config中设置。
iptables -t nat -A clash_dns -p udp --dport 53 -j DNAT --to-destination 192.168.0.10:5353
iptables -t nat -A clash_dns -p tcp --dport 53 -j DNAT --to-destination 192.168.0.10:5353
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-ports 7892
注意当系统重启后,这些iptables的规则会消失,我们需要在测试完成之后,让这些规则还在。 默认情况下,Ubuntu没有iptables的文件,如果想要查看当前的设置,可以参考这篇文章生成一个当前设置的文件。
设置完iptables后设置转发,打开文件/etc/sysctl.conf 找到'net.ipv4.ip_forward=1'之后把注释去掉即可。保存然后运行以下命令让设置生效:
sudo sysctl -p
7. 启动Clash并测试yacd
进入在第二部放两个配置文件的目录,用以下命令启动容器:
sudo docker-compose up -d
启动后查看日志是否有错误:
docker logs clash -f
应该可以看到5个端口都正常在监听的状态:
time="2020-01-29T16:45:30Z" level=info msg="DNS server listening at: 0.0.0.0:53"
time="2020-01-29T16:45:30Z" level=info msg="Redir proxy listening at: :7892"
time="2020-01-29T16:45:30Z" level=info msg="RESTful API listening at: 0.0.0.0:9090"
time="2020-01-29T16:45:30Z" level=info msg="HTTP proxy listening at: :7890"
time="2020-01-29T16:45:30Z" level=info msg="SOCKS proxy listening at: :7891"
Clash 正常启动之后,打开yacd的地址(第三步绑定的是8080),我这里是 192.168.0.10:9091,在界面中输入你的主机IP,管理端口和密码就应该可以正常进去了。 在yacd中可以看到节点已经有正常的ping值就说明clash已经在正常运转了。
8. 测试
使用手机或者电脑将网关和DNS都设置为Ubuntu的IP地址,此时应该可以正常访问网络了。 如果无法正常访问,请查看clash的日志是否端口都已经正常监听。再查看DNS设置是否正确。 另外提醒iptables的设置,一定要按自己的网络实际情况来进行设置。
9. 保持iptables的设置
前面提到iptables重启后会被复位,所以我们需要一个额外的小工具,直接apt安装即可:
sudo apt install iptables-persistent
如果之后有对iptables进行其他更改可以使用iptables-persistent save来保存更改。
10. 更改Openwrt下发网关和DNS
设置的地方在“接口-LAN-DHCP服务器-高级设置-DHCP选项” 在这里分别填入两行内容:
3,192.168.0.10
6,192.168.0.10
第一个3代表下发的网关地址,第二个6代表下发的DNS地址。 当然如果你不想让所有局域网的设备流量都通过Clash可以不做这个更改。
11. 本机的代理设置
需要注意的是Clash不更改本机自身的网络访问模式,所以当我这台运行Docker的Ubuntu访问网络时是直接走的路由器。 特别注意在Fake IP模式下,DNS解析直接给的是一个假的IP地址,这个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即可。
我在iptables和DNS端口两个坑里面挣扎了将近三小时才搞定,建议各位遇到问题先去查一下组件运行的原理,这样才可以更快debug。 经过测试,这种转发的方法比Openwrt直接编译OpenClash的效率和稳定性要高。当然也有可能是与我Openwrt中其他的东西有冲突造成的。