Fix: [document/level-2] tropxy

https://github.com/XTLS/XTLS.github.io/pull/74
Co-Authored-By: kirin10000 <57820613+kirin10000@users.noreply.github.com>
This commit is contained in:
JimhHan 2021-03-26 11:23:56 +08:00
parent aaa7fe05a9
commit f6b196b3e7
No known key found for this signature in database
GPG Key ID: 48D5D7CF95157AC5
3 changed files with 170 additions and 115 deletions

View File

@ -2,22 +2,18 @@
**这个章节包含进阶级的 Xray 使用心得分享, 如果您已经熟悉 Xray, 那么这里的经验可以让您更加发挥 Xray 的威力**
[透明代理入门](./transparent_proxy/transparent_proxy.md) by <img src="https://avatars2.githubusercontent.com/u/57820613?s=32" width="32px" height="32px" alt="a"/> [@kirin](https://github.com/kirin10000)</font>
透明代理TProxy的入门篇章。
透明代理的入门篇章。
[透明代理TProxy配置教程 ](./tproxy.md) by <img src="https://avatars2.githubusercontent.com/u/41363844?s=32" width="32px" height="32px" alt="a"/> [@BioniCosmos](https://github.com/BioniCosmos)</font>
基于 Xray 的透明代理TProxy配置完整教程。
[[透明代理]通过 gid 规避 Xray 流量](./iptables_gid.md) by <img src="https://avatars2.githubusercontent.com/u/57820613?s=32" width="32px" height="32px" alt="a"/> [@kirin](https://github.com/kirin10000)</font>
在 iptables/nftables 实现的透明代理中,一种新的规避 Xray 流量的方式。
[通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”](./redirect.md) by <img src="https://avatars.githubusercontent.com/u/28607089?s=460" width="32px" height="32px" alt="a"/> [@Zzz3m](https://github.com/Zzz3m)</font>
将 Xray 玩出花:基于 fwmark 或 sendThrough 方式实现“分流”。

View File

@ -9,7 +9,9 @@
2. 安卓系统有自己的 mark 机制,该方案在安卓上不可用
本教程的方案不需要设置 mark理论性能更高同时也不存在上述问题。
## 思路
tproxy 流量只能被 root 权限用户(uid==0)或其他有 CAP_NET_ADMIN 权限的用户接收。
iptables 规则可以通过 uid(用户 id)和 gid(用户组 id)分流。
@ -17,7 +19,9 @@ iptables规则可以通过uid(用户id)和gid(用户组id)分流。
让 Xray 运行在一个 uid==0 但 gid!=0 的用户上,设置 iptables 规则不代理该 gid 的流量来规避 Xray 流量。
## 配置过程
### 1. 前期准备
**安卓系统**
1. 系统已 root
@ -31,25 +35,36 @@ iptables规则可以通过uid(用户id)和gid(用户组id)分流。
需要依赖 sudoiptables 的 tproxy 模块和 extra 模块。
一般系统都有自带openwrt 运行:
```bash
opkg install sudo iptables-mod-tproxy iptables-mod-extra
```
另附上一些 openwrt 常用的依赖,缺少可能导致 Xray 无法运行
```bash
opkg install libopenssl ca-certificates
```
### 2. 添加用户(安卓用户请忽略)
安卓系统不支持/etc/passwd 文件来管理用户,请忽略,直接下一步。
```bash
grep -qw xray_tproxy /etc/passwd || echo "xray_tproxy:x:0:23333:::" >> /etc/passwd
```
其中 xray_tproxy 是用户名0 是 uid23333 是 gid用户名和 gid 可以自己定uid 必须为 0。
检查用户是否添加成功,运行
```bash
sudo -u xray_tproxy id
```
显示的结果应该是 uid 为 0gid 为 23333
### 3. 配置运行 Xray配置 iptables 规则
在现有的 iptables 透明代理白话文(**[新 V2Ray 白话文指南-透明代理](https://guide.v2fly.org/app/transparent_proxy.html)** 、 **[新 V2Ray 白话文指南-透明代理(TPROXY)](https://guide.v2fly.org/app/tproxy.html)** 、 **[透明代理TProxy配置教程](./tproxy)**)教程的基础上修改:
1. 修改 json 配置文件,删除 mark 相关内容
@ -57,18 +72,27 @@ sudo -u xray_tproxy id
2. 修改 iptables 规则,删除 mark 相关内容,并在 OUTPUT 链应用规则处添加选项"-m owner ! --gid-owner 23333"。
如:
```bash
iptables -t mangle -A OUTPUT -j XRAY_SELF
```
改为
```bash
iptables -t mangle -A OUTPUT -m owner ! --gid-owner 23333 -j XRAY_SELF
```
3. 修改运行 Xray 的方式,使其运行在 uid 为 0gid 为 23333 的用户上,参考[这里](#3-配置最大文件大开数运行xray客户端)。
## 下面提供一个实现 tproxy 全局代理的完整配置过程
### 1. 完成 **[前期准备](#1-前期准备)** 和 **[添加用户](#2-添加用户安卓用户请忽略)**
### 2. 准备 Xray 配置文件
配置 Xray 任意门监听 12345开启 followRedirect 和 tproxy不需要设置 sniffing
```json
{
"inbounds": [
@ -93,39 +117,49 @@ iptables -t mangle -A OUTPUT -m owner ! --gid-owner 23333 -j XRAY_SELF
]
}
```
### 3. 配置最大文件大开数&运行 Xray 客户端
关于最大文件大开数问题见: **[too many open files 问题](https://guide.v2fly.org/app/tproxy.html#解决-too-many-open-files-问题)**
目前 Xray 服务端使用官方脚本安装的已经自动配置了最大文件大开数,无需再修改。
**安卓系统**
```bash
ulimit -SHn 1000000
setuidgid 0:23333 "运行Xray的命令"&
```
**其它 Linux 系统**
```bash
ulimit -SHn 1000000
sudo -u xray_tproxy "运行Xray的命令"&
```
*第一条命令:*
_第一条命令_
改变最大打开文件数,只对当前终端有效,每次启动 Xray 前都要运行,该命令是设置客户端的最大文件大开数
*第二条命令:*
_第二条命令_
以 uid 为 0gid 不为 0 的用户来运行 Xray 客户端,后面加&代表放在后台运行
**检查最大文件大开数是否设置成功**
```bash
cat /proc/Xray的pid/limits
```
找到 max open files 一项应该是你设置的数值。pid 的获取方法为运行`ps``ps -aux``ps -a`
服务端和客户端都要检查
### 4. 设置 iptables 规则
**代理 ipv4**
```bash
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
@ -137,9 +171,9 @@ iptables -t mangle -A XRAY -d 网关所在ipv4网段1 -j RETURN
iptables -t mangle -A XRAY -d 网关所在ipv4网段2 -j RETURN
...
# 组播地址直连
iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN
# 组播地址/E类地址/广播地址直连
iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN
#如果网关作为主路由则加上这一句https://xtls.github.io/documents/level-2/transparent_proxy/transparent_proxy.md#iptables透明代理的其它注意事项
#网关LAN_IPv4地址段,运行命令"ip address | grep -w "inet" | awk '{print $2}'"获得,是其中的一个
@ -158,14 +192,14 @@ iptables -t mangle -A XRAY_MASK -m owner --gid-owner 23333 -j RETURN
iptables -t mangle -A XRAY_MASK -d 网关所在ipv4网段1 -j RETURN
iptables -t mangle -A XRAY_MASK -d 网关所在ipv4网段2 -j RETURN
...
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/3 -j RETURN
iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
```
**代理 ipv6(可选)**
```bash
ip -6 rule add fwmark 1 table 106
ip -6 route add local ::/0 dev lo table 106

View File

@ -1,10 +1,13 @@
# 透明代理入门
## 什么是透明代理
透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。
这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。
## 透明代理的实现
透明代理的实现目前主要有两种方式:
### tun2socks
@ -38,6 +41,7 @@ iptables与nftables实现透明代理的原理相同下文统一使用iptable
现存的三篇白话文透明代理教程其实讲的都是基于这种方案的透明代理实现,它们是: **[新 V2Ray 白话文指南-透明代理](https://guide.v2fly.org/app/transparent_proxy.html)** 、 **[新 V2Ray 白话文指南-透明代理(TPROXY)](https://guide.v2fly.org/app/tproxy.html)** 、 **[透明代理TProxy配置教程](../tproxy.md)** 。其中第一篇是基于 iptables-redirect 模式,已经过时了,不建议使用,仅供参考。第二篇和第三篇讲的都是基于 iptables-tproxy 模式的透明代理实现。
## iptables 实现透明代理原理
Linux 使用`Netfilter`来管理网络,`Netfilter`模型如下:
![Netfilter](./netfilter.png)
@ -57,6 +61,7 @@ Linux使用`Netfilter`来管理网络,`Netfilter`模型如下:
`网关本机->OUTPUT链->POSTINGROUTING链`
**通过使用 iptables 操控`PREROUTING链``OUTPUT链`的流量走向,转发到 Xray就可以代理局域网设备和网关本机。**
## 透明代理难在哪里
透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做**分流**更加合适。
@ -74,7 +79,9 @@ Linux使用`Netfilter`来管理网络,`Netfilter`模型如下:
上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。
## 从零开始一步步实现基于 iptables-tproxy 的透明代理
### 在开始之前,你需要有一定的基础知识:
1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器
2. 知道什么是 WAN 口LAN 口LAN_IPWAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口
@ -82,7 +89,9 @@ Linux使用`Netfilter`来管理网络,`Netfilter`模型如下:
3. 对 Linux 系统有最基础的了解(知道怎么运行命令)
4. 能够手写客户端 json 文件配置,至少要能看懂
### 前期准备工作
**1. 准备一个运行 Linux 系统的网关**
比如,刷了 OpenWRT 的路由器
@ -90,6 +99,7 @@ Linux使用`Netfilter`来管理网络,`Netfilter`模型如下:
**2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件**
配置文件监听 12345 端口,开启 tproxy
```json
{
"log": {
@ -117,11 +127,15 @@ Linux使用`Netfilter`来管理网络,`Netfilter`模型如下:
]
}
```
我们由易到难,不写 routing只写一个 inbound 一个 outbound。
### 首先,我们先试试做到第一阶段
将所有`PREROUTING链`的流量,都转发到 Xray 中。
运行 Xray执行以下指令
```bash
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
@ -130,11 +144,13 @@ iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j XRAY
```
当你输入完之后,如果你是使用 ssh 连接到网关上的,你会发现 ssh 的连接断开了(不用紧张,断电重启即可恢复),并且透明代理无法上网;如果你是的网关是虚拟机,你会发现网关本身也无法上网,并且 Xray 日志 access_log 中出现许多源地址为目标地址,目标地址为 WAN_IP 的请求。
理论上网关本机访问公网只会经过`OUTPUT链``POSTROUTING链`,为什么操控`PREROUTING链`会导致网关无法上网呢?这是因为网络通讯往往是双向的,虽然网关访问公网 IP 不需要经过`PREROUTING链`,但被访问的服务器向网关返回信息时要经过`PREROUTING链`,且这部分被转发到 Xray 了,因此出现了日志中的反向请求。
我们修改一下规则,源 IP 不是来自局域网的则返回。重启网关,运行 Xray执行以下指令
```bash
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
@ -145,11 +161,15 @@ iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j XRAY
```
然后你会发现,虽然 ssh 连接断开了,但是透明代理已经可用了。只要我们修改系统 dns 为公共 dns就能正常上网了(因为现在网关访问不了,所以 dns 设置为网关是不行的)。
至此,第一阶段就完成了。之所以无法访问网关,是因为代理规则代理了全部流量,包括访问网关的流量。试想在 VPS 上访问你本地的网关,肯定是访问不了的,所以我们要对这部分流量直连,请看第二阶段:
### 第二阶段
重启网关,运行 Xray执行以下指令
```bash
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
@ -161,14 +181,14 @@ iptables -t mangle -A XRAY -d 网关所在网段1 -j RETURN
iptables -t mangle -A XRAY -d 网关所在网段2 -j RETURN
...
# 目标地址为组播IP的请求直连
iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN
# 目标地址为组播IP/E类地址/广播IP的请求直连
iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN
iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j XRAY
```
使用这条规则后,上一条规则`iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN`便成为了多余规则,可以删去。
至此第二阶段完成。网关已经可以访问ssh 不会断开。
@ -188,6 +208,7 @@ iptables-tproxy不支持对`OUTPUT链`操作,但是`Netfilter`有个特性,
1. 直连目标地址为 VPS 的流量
重启网关,运行 Xray执行以下指令
```bash
#代理局域网设备
#继承上一个阶段的成果
@ -197,8 +218,7 @@ iptables -t mangle -N XRAY
iptables -t mangle -A XRAY -d 网关所在网段1 -j RETURN
iptables -t mangle -A XRAY -d 网关所在网段2 -j RETURN
...
iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN
iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j XRAY
@ -208,13 +228,13 @@ iptables -t mangle -N XRAY_MASK
iptables -t mangle -A XRAY_MASK -d 网关所在网段1 -j RETURN
iptables -t mangle -A XRAY_MASK -d 网关所在网段2 -j RETURN
...
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/3 -j RETURN
iptables -t mangle -A XRAY_MASK -d VPS公网ip/32 -j RETURN
iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
```
但是这么配置有个缺点,如果使用 CDN 或者 VPS 很多的话,就不好写规则了。
2. 通过 mark 规避
@ -228,14 +248,19 @@ iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
这样就完成了第三阶段的代理,也就是平时说的全局代理。但是记得把网关的 DNS 服务器设置为国外的 DNS 服务器,否则可能依然返回被污染的结果。
### 第四阶段
其实,并不是所有人都需要实现第四阶段。全局代理对于大部分情况已经适用。
特别是对于旁路由而言。需要代理时,将网关调成旁路由的 IP不需要代理时将网关换回主路由 IP。
至于第四阶段的具体实现,那三篇白话文教程讲的都是。在理解了上面的内容后,再去看那三篇白话文教程,就比较容易理解了。
### 代理 ipv6
上面的规则只对 ipv4 生效,如果还想要代理 ipv6 请求,则使用 ip6tables 命令,用法与 iptables 基本相同。参考 **[[透明代理]通过 gid 规避 Xray 流量#4-设置 iptables 规则](../iptables_gid#4-设置iptables规则.md)**
# iptables 透明代理的其它注意事项
1. 如果作为代理的网关作为主路由,要在`PREROUTING链`规则中加一条`iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN`即在第一阶段使用、第二阶段被删除的指令。如果不写WAN 口中同网段的其它人可以将网关填写成你的 WAN_IP从而蹭你的透明代理用还可能带来一定的危险性。
2. **[新 V2Ray 白话文指南-透明代理(TPROXY)#设置网关](https://guide.v2fly.org/app/tproxy.html#设置网关)** 中的第三条说:`手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)`。实际上Ubuntu、CentOS、debian 等系统就算开启了 IP 转发PC 也不能正常上网,这是正常的。事实上只有 OpenWRT 能做到文中所描述的那样,据 **[@BioniCosmos](https://github.com/BioniCosmos)** 点拨,这是由于一般的 Linux 系统没有 Masquery 规则。