使用 Gentoo Linux 手搓路由器之二 -- 透明代理

继之前的两篇文章

这两个做完了之后,你的路由器基本满足了上网和看IPTV的需求了。 但是对于程序员来说 GitHub 加速, Google 查资料还是非常有必要的。在OpenWRT中实现这些功能非常简单,直接使用插件就好了

  • Shadowsocksr Plus
  • Passwall
  • OpenClash

等均可简单配置即可使用,当然,这些对你来说都是黑盒。

Lede 分支的源码不包含 passwall AND OpenClash, 添加插件的方法可以参考 《软路由(OpenWRT)进阶编译,深度裁剪》 文章中的添加插件的方法。

Linux 中, 主要是利用 xraytproxy 功能和 iptables 来实现。具体的方法 xray 的文档中已经写的非常清楚了 《透明代理(TPROXY)》 我再狗尾续貂一下。

Xray的配置文件的 inbounds中添加以下配置, 需要配置成 tproxy, 这里的作用是使得后续将路由器的流量通过iptables转进来。

 1"inbounds": [
 2        {
 3            "port": 10123,
 4            "protocol": "dokodemo-door",
 5            "settings": {
 6                "network": "tcp,udp",
 7                "followRedirect": true
 8            },
 9            "streamSettings": {
10                "sockopt": {
11                    "tproxy": "tproxy",
12                    "mark": 255
13                }
14            },
15            "sniffing": {
16                "enabled": true,
17                "destOverride": [
18                    "http",
19                    "tls"
20                ]
21            },
22            "tag": "in-tproxy"
23        }
24    ]

"mark": 255 的作用是把数据包标记成 255,作用:我们利用 iptables mangle表把数据包打上mark:1 的标记, 并把所有 mark: 1的数据包路由到 Xray 里, 如果不修改标记, 最后 Xray 出来的数据包还是 1, 这样就死循环了。当然本文会采用另一个取巧的办法来实现 gid, 也就是说给 xray 指定一个gid,iptables 里指定这个gid的流量都不走代理也可以解决这个死循环的问题。

前面已经说过, 使用gid的方式避免数据流的死循环。

先给xray添加一个用户xxray, 注意,需要 uid: 0, gid 23333

1echo "xxray:x:0:23333:::" >> /etc/passwd

启动xray, 把路径替换成你自己的

1sudo -u xxray /xraypath/xray run -confdir /xrayconf/conf.d

配置iptables 和 路由规则

  1#!/bin/bash
  2
  3export IPSET_CN_IP=cntcpip
  4export IPSET_CN_UDP_IP=cnudpip
  5
  6iptables -t mangle -F
  7iptables -t mangle -X XRAY
  8iptables -t mangle -X XRAY_MASK
  9ip route del local 0.0.0.0/0 dev lo table 100
 10ip rule del fwmark 1 table 100
 11
 12ip rule add fwmark 1 table 100
 13ip route add local 0.0.0.0/0 dev lo table 100
 14
 15iptables -t mangle -N XRAY
 16iptables -t mangle -N XRAY_MASK
 17
 18# 删除 Chain
 19# iptables -t mangle -F XRAY
 20# iptables -t mangle -X XRAY
 21
 22
 23# 来自xray的流量直接 RETURN, 防止回环. xray是开启在gid = 23333上
 24# iptables -t mangle -A XRAY -m owner --gid-owner 23333 -j RETURN
 25# 直连 XRAY 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面XRay 配置的 255),此规则目的是解决v2ray占用大量CPU(https://github.com/v2ray/v2ray-core/issues/2621)
 26iptables -t mangle -A XRAY -j RETURN -m mark --mark 0xff
 27
 28# 不需要代理的IP和端口
 29### 访问本机 53 端口走代理, 其它的环回地址不走代理
 30iptables -t mangle -A XRAY -d 192.168.0.0/16 -p UDP -j RETURN
 31iptables -t mangle -A XRAY -d 192.168.0.0/16 -p TCP -j RETURN
 32iptables -t mangle -A XRAY -d 10.0.0.0/8 -j RETURN
 33iptables -t mangle -A XRAY -d 100.64.0.0/10 -j RETURN
 34# iptables -t mangle -A XRAY -d 0.0.0.0/8 -j RETURN
 35iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN
 36iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN
 37iptables -t mangle -A XRAY -d 172.17.0.1/16 -j RETURN
 38iptables -t mangle -A XRAY -d 114.114.115.115/32 -p UDP --dport 53 -j RETURN
 39
 40## 国内IP直连
 41iptables -t mangle -A XRAY -p TCP -s 192.168.88.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 42iptables -t mangle -A XRAY -p TCP -s 192.168.1.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 43iptables -t mangle -A XRAY -p TCP -s 10.8.9.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 44iptables -t mangle -A XRAY -p UDP -s 192.168.88.0/24 -m set --match-set ${IPSET_CN_UDP_IP} dst -j RETURN
 45iptables -t mangle -A XRAY -p UDP -s 192.168.1.0/24 -m set --match-set ${IPSET_CN_UDP_IP} dst -j RETURN
 46
 47## 访问外部不走代理的服务
 48iptables -t mangle -A XRAY -p UDP --dport 1194 -j RETURN
 49iptables -t mangle -A XRAY -p TCP --dport 1194 -j RETURN
 50iptables -t mangle -A XRAY -p UDP --dport 8194 -j RETURN
 51iptables -t mangle -A XRAY -p TCP --dport 8194 -j RETURN
 52iptables -t mangle -A XRAY -p UDP --dport 5500 -j RETURN
 53iptables -t mangle -A XRAY -p TCP --dport 5500 -j RETURN
 54iptables -t mangle -A XRAY -p UDP --dport 5560 -j RETURN
 55iptables -t mangle -A XRAY -p TCP --dport 5560 -j RETURN
 56iptables -t mangle -A XRAY -p UDP --dport 9901 -j RETURN
 57iptables -t mangle -A XRAY -p TCP --dport 9901 -j RETURN
 58# iptables -t mangle -A XRAY -p UDP --dport 8443 -j RETURN
 59# iptables -t mangle -A XRAY -p TCP --dport 8443 -j RETURN
 60
 61
 62## on port 为xray端口
 63iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 10123 --tproxy-mark 1
 64iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 10123 --tproxy-mark 1
 65### 应用规则
 66iptables -t mangle -A PREROUTING -j XRAY
 67# iptables -t mangle -A PREROUTING -j XRAY
 68
 69
 70iptables -t mangle -A XRAY_MASK -m owner --gid-owner 23333 -j RETURN
 71
 72# 如果 ipset ${IPSET_CN_IP} 中有存在, 就直接return, 直连. 提升效率
 73iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.1.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 74iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.88.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 75iptables -t mangle -A XRAY_MASK -p TCP -s 10.8.9.0/24 -m set --match-set ${IPSET_CN_IP} dst -j RETURN
 76iptables -t mangle -A XRAY_MASK -p UDP -s 192.168.88.0/24 -m set --match-set ${IPSET_CN_UDP_IP} dst -j RETURN
 77iptables -t mangle -A XRAY_MASK -p UDP -s 192.168.1.0/24 -m set --match-set ${IPSET_CN_UDP_IP} dst -j RETURN
 78
 79# 不走代理的规则
 80iptables -t mangle -A XRAY_MASK -d 127.0.0.1/32 -j RETURN
 81iptables -t mangle -A XRAY_MASK -d 192.168.0.0/16 -j RETURN
 82iptables -t mangle -A XRAY_MASK -d 10.0.0.0/8 -j RETURN
 83iptables -t mangle -A XRAY_MASK -d 100.64.0.0/10 -j RETURN
 84iptables -t mangle -A XRAY_MASK -d 224.0.0.0/4 -j RETURN
 85iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -j RETURN
 86iptables -t mangle -A XRAY_MASK -d 172.17.0.1/16 -j RETURN
 87iptables -t mangle -A XRAY_MASK -d 114.114.115.115/32 -p UDP --dport 53 -j RETURN
 88
 89## 访问外部不走代理的服务
 90iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.1.6/32 --sport 8194 -j RETURN
 91iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.1.6/32 --dport 1194 -j RETURN
 92iptables -t mangle -A XRAY_MASK -p UDP -s 192.168.1.6/32 --sport 9901 -j RETURN
 93iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.1.6/32 --sport 5500 -j RETURN
 94iptables -t mangle -A XRAY_MASK -p TCP -s 192.168.1.6/32 --sport 5560 -j RETURN
 95iptables -t mangle -A XRAY_MASK -s 192.168.1.6/32 -p TCP --sport 8443 -j RETURN
 96
 97
 98
 99iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1
100iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
101iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK

保存为 xray-firewall.sh, 执行规则 bash xray-firewall.sh

流程上是把所有的流量(转发的,本机的)都按规则转给了 xray, 由 xray 去判断是否需要走代理。如果是国内的流量,这么玩会影响性能。所以 我建立了一个国内IP地址的IPSet,判断一下,如果是 IPSet中存在的 IP 就不再进 xray了。我个人觉得内核空间总归快过 用户空间。

应用规则上分两部分, 一部分是转发的, 所以需要在 PREROUTING 的阶段拦截, 本机的流量在 OUTPUT 链上做拦截。使用 mangle 表是因为 这里需要给包打标记。iptables 的四表五链中常用的 Filter 是过滤用的, nat 是做地址转换用的, mangle是用于修改数据包属性的.

这个时候, 你就可以正常使用 google 搜索了, github 也快多了(当然这个还是取决于你的 outbands 的速度)

还剩下一个域名解析的问题需要解决,国内的域名最好在国内解析, 虽然我有了CN的IPSet但是不是全部,为什么不能用全部CN的IP,后面我会写文档介绍

Xray提供了一个内置的DNS功能, OpenWRT中很多人使用 mosdns,我个人觉得没有必要再开一个服务,而且域名规则还需要和 Xray的保持一致,多出来不少事情。

 1"dns": {
 2    "hosts": {
 3        "dns.google": [
 4            "8.8.8.8",
 5            "8.8.4.4"
 6        ]
 7    },
 8    "servers": [
 9        "8.8.8.8",
10        "8.8.4.4",
11        {
12            "address": "114.114.114.114",
13            "skipFallback": true,
14            "domains": [
15                "geosite:cn"
16            ],
17            "queryStrategy": "UseIPv4"
18        },
19        {
20            "address": "https://1.1.1.1/dns-query",
21            "skipFallback": true,
22            "domains": [
23                "geosite:geolocation-!cn"
24            ],
25            "queryStrategy": "UseIPv4"
26        },
27        {
28            "address": "8.8.8.8",
29            "queryStrategy": "UseIPv4",
30            "skipFallback": false
31        }
32    ],
33    "queryStrategy": "UseIPv4",
34    "disableCache": false,
35    "disableFallback": false,
36    "disableFallbackIfMatch": true,
37    "tag": "inner-dns"
38}

指定 geosite:cn 国内的域名去 114.114.114.114 去解析。 geosite:geolocation-!cn1.1.1.1 解析, 这里的解析策略都是IPv4,IPv6的部分以后写文章慢慢说,比较复杂,因为要解决 DNS 泄漏的问题和Proxy的问题。

再在 routing 配置里拦截一下 DNS的流量

 1"routing": {
 2        "balancers": [
 3            {
 4                "selector": [
 5                    "out-kiwi",
 6                    "out-fox"
 7                ],
 8                "strategy": {
 9                    "type": "roundRobin"
10                },
11                "tag": "lb-round"
12            }
13        ],
14        "rules": [
15            // 拦截 DNS 的流量
16            {
17                "type": "field",
18                "inboundTag": [
19                    "in-tproxy",
20                    "in-shadowsocks",
21                    "in-socks",
22                    "in-http"
23                ],
24                "port": 53,
25                "network": "udp,tcp",
26                "outboundTag": "out-dns"
27            },
28        ]
29}

outbounds 里添加

1{
2    "tag": "out-dns",
3    "protocol": "dns",
4    "streamSettings": {
5        "sockopt": {
6            "mark": 255
7        }
8    }
9}

这样 DNS 的策略解析就解决了

注意: 使用 Xray 的同学, 在 outbounds 的配置里, 第一个节点是兜底的,建议把VPS写在第一个节点。

如此这样, 手搓路由器就基本完成了, 当然你还可以在路由器上添加你想要的功能,路由是一个 Gentoo Linux,安装和维护都比较方便。

Posts in this series