透明代理(TPROXY)
原来出过一篇透明代理的教程,但过了许久,V2Ray 也已经迭代了好多个版本。原来的教程依旧可以正常使用,但随着 V2Ray 的更新,V2Ray 推出了新的透明代理方式—— TPROXY,原来的叫 REDIRECT。最近测试了一下 TPROXY ,效果还不错,主观感觉比 REDIRECT 好。并且在本文的透明代理中,DNS 服务将由 V2Ray 提供。不过这种方式需要 iptables 的 TPROXY 模块支持,有一些阉割版的系统会精简掉 TPROXY 模块,这种系统是不适用于本文的。
普通家庭大多数是光纤入户接光猫调制解调,一个路由器的 WAN 口接网线,要上网的设备(如 PC 、电视盒子、手机)接路由器的 LAN 口。本文的透明代理需要一台 Linux 主机接路由器 LAN 口,作为局域网中的网关,为其他接入局域网中的设备提供翻墙功能。这样的方式与我原来的透明代理教程是一样的,都是搭建在一个 Linux 主机上。这样可以透明代理的设备,有的人叫“透明网关”,也有的叫“旁路由”。我觉得这种不是很严肃的场合,叫什么都行,只要不妨碍理解。
很多设备都可以做透明网关,路由器、开发板、个人电脑、虚拟机和 Android 设备等。路由器可能比较特殊点,因为它本身就可以充当网关。上面可能说得太抽象,我就举些实际的,比如说树莓派、香橙派、用 PC 装的 Linux 虚拟机、淘宝的工控机(如 j1900)、NAS、电视盒子(如翻车迅)、你刚配的牙膏厂或农厂的电脑,这些都没问题。至于到底用什么?这得看需求,我觉得网络 200M 以下搞个高性能的类树莓派的 SBC 就够了,200M 以上就得考虑 X86 主机了(如今甚火的软路由)。当然,到底怎么选择还是得看自己。
本文假设你已经有一个设备(就以树莓派举例),将用来作网关(或说旁路由),并且已经安装好 Linux。关于系统,我更推荐 Debian 或 Debian 衍生版。为方面起见,本文均以 root 权限账户执行命令。并且有一台 PC 以便于操作。
设置网关
- 用网线将树莓派接入路由器 的LAN 口,假设分给树莓派的 IP 是 192.168.1.22。
- 树莓派开启 IP 转发(需要开启 IP 转发才能作为网关)。命令为
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf && sysctl -p。执行后将出现 net.ipv4.ip_forward=1 的提示。 - 手动配置 PC 的网络,将默认网关指向树莓派的地址即
192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。
树莓派安装配置 V2Ray
- 安装 V2Ray。可以使用 V2Ray 提供的 go.sh 脚本安装,由于 GFW 会恶化对 GitHub 的访问,直接运行脚本几乎无法安装,建议先下载 V2Ray 的压缩包,然后用安装脚本通过 --local 参数进行安装。
- 配置 V2Ray。按照前文教程将 V2Ray 配置成客户端形式。然后执行
curl -so /dev/null -w "%{http_code}" google.com -x socks5://127.0.0.1:1080确认 V2Ray 已经可以翻墙(命令中 socks5 指 inbound 协议为 socks,1080 指该 inbound 端口是 1080)。如果执行这个命令出现了 301 或 200 这类数字的话代表可以翻墙,如果长时间没反应或者是 000 的话说明不可以翻墙。
配置透明代理
为 V2Ray 配置透明代理的入站和 DNS 分流
以下是 V2Ray 透明代理的配置示例,配置文件之后有说明。
{
"inbounds": [
{
"tag":"transparent",
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"streamSettings": {
"sockopt": {
"tproxy": "tproxy" // 透明代理使用 TPROXY 方式
}
}
},
{
"port": 1080,
"protocol": "socks", // 入口协议为 SOCKS 5
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth"
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess", // 代理服务器
"settings": {
"vnext": [
...
]
},
"streamSettings": {
"sockopt": {
"mark": 255
}
},
"mux": {
"enabled": true
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
},
{
"tag": "dns-out",
"protocol": "dns",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],
"dns": {
"servers": [
"8.8.8.8", // 非中中国大陆域名使用 Google 的 DNS
"1.1.1.1", // 非中中国大陆域名使用 Cloudflare 的 DNS(备用)
"114.114.114.114", // 114 的 DNS (备用)
{
"address": "223.5.5.5", //中国大陆域名使用阿里的 DNS
"port": 53,
"domains": [
"geosite:cn",
"ntp.org", // NTP 服务器
"$myserver.address" // 此处改为你 VPS 的域名
]
}
]
},
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{ // 劫持 53 端口 UDP 流量,使用 V2Ray 的 DNS
"type": "field",
"inboundTag": [
"transparent"
],
"port": 53,
"network": "udp",
"outboundTag": "dns-out"
},
{ // 直连 123 端口 UDP 流量(NTP 协议)
"type": "field",
"inboundTag": [
"transparent"
],
"port": 123,
"network": "udp",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址直连,以达到 DNS 分流目的
"223.5.5.5",
"114.114.114.114"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
// 设置 DNS 配置中的国内 DNS 服务器地址走代理,以达到 DNS 分流目的
"8.8.8.8",
"1.1.1.1"
],
"outboundTag": "proxy" // 改为你自己代理的出站 tag
},
{ // 广告拦截
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
},
{ // BT 流量直连
"type": "field",
"protocol":["bittorrent"],
"outboundTag": "direct"
},
{ // 直连中国大陆主流网站 ip 和 保留 ip
"type": "field",
"ip": [
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
},
{ // 直连中国大陆主流网站域名
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
}
]
}
}
以上是 V2Ray 透明代理的参考配置,关于配置有一些注意点及说明:
- dokodemo-door 是用来接收透明代理的入站协议,followRedirect 项须为 true 以及 sockopt.tproxy 项须为 tproxy,建议开启 snifing,否则路由无法匹配域名;
- 本节添加了 DNS 配置,用来对国内外域名进行 DNS 分流,需要
DNS 配置、DNS 入站、DNS 出站和路由四者配合,在本例中 DNS 入站直接使用透明代理入站,可参考DNS 及其应用; - 在 DNS 配置中,依次配置了 Google、Cloudflare、114 和阿里的 DNS,由于在阿里的 DNS 中指定了 domain,所以匹配的域名会用阿里的 DNS 查询,其他的先查询 Google 的 DNS,如果查不到的话再依次查 Cloudflare 及 114 的。所以达到了国内外域名 DNS 分流,以及 DNS 备用。要注意把 NTP 服务器和你自己 VPS 域名也加入到直连的 DNS ,否则会导致 V2Ray 无法与 VPS 正常连接;
- DNS 配置只是说明哪些域名查哪个 DNS,至于哪个 DNS 走代理哪个 DNS 直连要在 routing 里设置规则;
- routing 也要设置 123 端口的 UDP 流量直连,不然的话要是时间误差超出允许范围(90s),要使用 NTP 校准时间就要先连上代理,但是连代理又要确保时间准确,结果就是既连不上代理,也无法自动校准时间;
- freedom 的出站设置 domainStrategy 为 UseIP,以避免直连时因为使用本机的 DNS 出现一些奇怪问题;
- 注意要在所有的 outbound 加一个 255 的 mark,这个 mark 与下文 iptables 命令中
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff配合,以直连 V2Ray 发出的流量(blackhole 可以不配置 mark)。
配置透明代理规则
执行下面的命令开启透明代理。由于使用了 TPROXY 方式的透明代理,所以 TCP 流量也是使用 mangle 表。以下命令中,以 # 开头的为注释。
# 设置策略路由
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
# 代理局域网设备
iptables -t mangle -N V2RAY
iptables -t mangle -A V2RAY -d 127.0.0.1/32 -j RETURN
iptables -t mangle -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网,避免 V2Ray 无法启动时无法连网关的 SSH,如果你配置的是其他网段(如 10.x.x.x 等),则修改成自己的
iptables -t mangle -A V2RAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的
iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 # 给 UDP 打标记 1,转发至 12345 端口
iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 # 给 TCP 打标记 1,转发至 12345 端口
iptables -t mangle -A PREROUTING -j V2RAY # 应用规则
# 代理网关本机
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN # 直连局域网
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN # 直连局域网,53 端口除外(因为要使用 V2Ray 的 DNS)
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面V2Ray 配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1 # 给 UDP 打标记,重路由
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1 # 给 TCP 打标记,重路由
iptables -t mangle -A OUTPUT -j V2RAY_MASK # 应用规则
执行了以上 ip 和 iptables 命令后,局域网同网段的设备以及网关本身就可以直接翻墙了。
关于 iptables 规则,比较容易理解,如果不太理解的话也可以 Google 搜索其他相关文章资料对比学习。在类 ss-redir 透明代理中,有两个观点非常深入人心:
1. UDP 只能 TPROXY
2. TPROXY 不能用于 OUTPUT 链
然后我们从这两个观点很容易得出一个推论:无法在提供透明代理的本机(即本例中的网关)上对 UDP 透明代理。 这个结论好像并没有什么问题,对吧?但实际上,在本例的配置中无论是 TCP 还是 UDP,都可以实现在本机上的透明代理,而且都是用 TPROXY。那好像又跟前面的结论矛盾了?其实关键在于这三句命令:
iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1
iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j V2RAY_MASK
这几句是说给 OUTPUT 链的 TCP 和 UDP 打个标记 1(OUTPUT 应用 V2RAY_MASK 链)。由于 Netfilter 的特性,在 OUTPUT 链打标记会使相应的包重路由到 PREROUTING 链上,在已经配置好了 PREROUTING 相关的透明代理的情况下,OUTPUT 链也可以透明代理了,也就是网关对自身的 UDP 流量透明代理自身(当然 TCP 也不在话下)。因为这是 netfilter 本身的特性,Shadowsocks 应该也可以用同样的方法对本机的 UDP 透明代理,但我没有实际测试过效果。
开机自动运行透明代理规则
由于策略路由以及 iptables 有重启会失效的特性,所以当测试配置没有问题之后,需要再弄个服务在开机时自动配置策略路由和 iptables,否则每次开机的时候就要手动来一遍了。
- 由于 iptables 命令有点多,所以先将 iptables 规则保存到 /etc/iptables/rules.v4 中。
mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4
- 在 /etc/systemd/system/ 目录下创建一个名为 tproxyrule.service 的文件,然后添加以下内容并保存。
[Unit]
Description=Tproxy rule
After=network.target
Wants=network.target
[Service]
Type=oneshot
#注意分号前后要有空格
ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /sbin/iptables-restore /etc/iptables/rules.v4
[Install]
WantedBy=multi-user.target
- 执行下面的命令使 tproxyrule.service 可以开机自动运行。
systemctl enable tproxyrule
其他
解决 too many open files 问题
对 UDP 透明代理比较容易出现”卡住“的情况,这个时候细心的朋友可能会发现日志中出现了非常多 "too many open files" 的语句,这主要是受到最大文件描述符数值的限制,把这个数值往大调就好了。设置步骤如下。
- 修改 /etc/systemd/system/v2ray.service 文件,在
[Service]下加入LimitNPROC=500和LimitNOFILE=1000000,修改后的内容如下。
[Unit]
Description=V2Ray Service
After=network.target
Wants=network.target
[Service]
# This service runs as root. You may consider to run it as another user for security concerns.
# By uncommenting the following two lines, this service will run as user v2ray/v2ray.
# More discussion at https://github.com/v2ray/v2ray-core/issues/1011
# User=v2ray
# Group=v2ray
Type=simple
PIDFile=/run/v2ray.pid
ExecStart=/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json
Restart=on-failure
# Don't restart in the case of configuration error
RestartPreventExitStatus=23
LimitNPROC=500
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
- 执行
systemctl daemon-reload && systemctl restart v2ray生效。
设定网关为静态 IP
最好给网关设成静态 IP,以免需要重启的时 IP 发生变化。如何设置请自行探究。 提示一下,如果你用 nmcli 命令设置静态 IP,最好先另外添加一个 connection 进行配置,配置好之后在切换到新添加的这个 connection 来。因为如果在原有的 connection 上直接修改成静态 IP 可能会导致无法透明代理。
设定 DHCP
在路由器上设定 DHCP,将网关地址指向网关设备,在本文的举例中即为树莓派的 IP 192.168.1.22; DNS 随意,因为已经配置了劫持 53 端口的 UDP,当然填常规的 DNS 也更是没有问题的。
备注
- TPROXY 与 REDIRECT 是针对 TCP 而言的两种透明代理模式,两者的差异主要在于 TPROXY 可以透明代理 IPV6,而 REDIRECT 不行,本文主要是将透明代理模式改为 TPROXY 并且使用了 V2Ray 的 DNS。但我没有 IPV6 环境,无法进行测试,所以本文只适用于 IPV4。
- 据我了解,到目前(2019.10)为止,在我所知的具备透明代理功能的翻墙工具中,TCP 透明代理方式可以使用的 TPROXY 的只有 V2Ray。所以你要找其他资料参考的话,要注意透明代理方式,因为基本上都是 REDIRECT 模式的(包括 V2Ray 官网给的示例)。
- 在透明代理中,不要用 V2Ray 开放 53 端口做 DNS 服务器。如果这么做了,DNS 会出问题,这应该是个 BUG。(详情见此 Issue)
我用 NatTypeTester 测试过 NAT 类型,结果是 FullCone,但也看到有反馈说玩游戏依然是 PortRestrictedCone。我也不清楚是怎么回事,这点需要玩游戏的朋友来确认了。不过目前测试发现代理 QUIC 的效果还不不错的。V2Ray 仍然不支持 FullCone,详情见此 Issue。
参考资料
https://github.com/v2fly/v2ray-step-by-step
-------------------------------------------------------
Transparent proxy on OpenWrt based router.
OTransproxy
Typical usage
Install
- Download the OTransproxy and configurations:
mkdir -p /opt/OTransproxy && \
cd /opt/OTransproxy && \
wget https://raw.githubusercontent.com/pwrliang/OTransproxy/master/otransproxy.sh && \
wget https://raw.githubusercontent.com/pwrliang/OTransproxy/master/config.json && \
wget https://raw.githubusercontent.com/pwrliang/OTransproxy/master/bypass.list && \
wget https://raw.githubusercontent.com/pwrliang/OTransproxy/master/proxy.list && \
chmod +x otransproxy.sh
- Custom you own config.json of V2Ray. Fill your IPs/domains of V2Ray servers into
bypass.list, otherwise it causes INFINITELY proxy. ./otransproxy.sh --installThis step will download V2Ray binaries and rules../otransproxy.sh --startThis step will start V2Ray and configure iptables and dnsmasq../otransproxy.sh --enableThis step will startup OTransproxy service when system up.
curl https://google.com to test the network connectivity.Uninstall
/opt/OTransproxy/otransproxy.sh --stop/opt/OTransproxy/otransproxy.sh --disablerm -rf /opt/OTransproxy
Update rules automatically
crontab -e- append
0 5 * * * /opt/OTransproxy/otransproxy.sh --update-rules
Sample output
BusyBox v1.28.3 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 18.06.1, r7258-5eb055306f
-----------------------------------------------------
root@GL-AR750:/opt# mkdir -p /opt/OTransproxy && \
> cd /opt/OTransproxy && \
> wget -q https://raw.githubusercontent.com/pwrliang/OTransproxy/master/otransproxy.sh && \
> wget -q https://raw.githubusercontent.com/pwrliang/OTransproxy/master/config.json && \
> wget -q https://raw.githubusercontent.com/pwrliang/OTransproxy/master/bypass.list && \
> wget -q https://raw.githubusercontent.com/pwrliang/OTransproxy/master/proxy.list && \
> chmod +x otransproxy.sh
root@GL-AR750:/opt/OTransproxy# vi bypass.list
root@GL-AR750:/opt/OTransproxy# vi config.json
root@GL-AR750:/opt/OTransproxy# ./otransproxy.sh --install
Tue Oct 8 15:01:07 UTC 2019 - Checking V2Ray version
Tue Oct 8 15:01:17 UTC 2019 - Downloading V2Ray v4.20.0
Downloaded
Unziping...
V2Ray installed
Tue Oct 8 15:11:21 UTC 2019 - Detected rules changed, downloading...
Tue Oct 8 15:11:40 UTC 2019 - Generating /opt/OTransproxy/tmp/transproxy_accelerated_domains.conf
Tue Oct 8 15:12:00 UTC 2019 - China route list downloaded
root@GL-AR750:/opt/OTransproxy# ./otransproxy.sh --start
Tue Oct 8 15:13:00 UTC 2019 - V2Ray has been started
Tue Oct 8 15:13:00 UTC 2019 - Copy dnsmasq configurations
Tue Oct 8 15:13:00 UTC 2019 - Restart dnsmasq
Tue Oct 8 15:13:02 UTC 2019 - Creating ipset
Tue Oct 8 15:13:04 UTC 2019 - Applying iptables
Tue Oct 8 15:13:04 UTC 2019 - Optimize network
root@GL-AR750:/opt/OTransproxy# ./otransproxy.sh --enable
root@GL-AR750:/opt/OTransproxy# curl google.com
<HTML>"content-type"
Note
- Only tested and works on following platforms: Koolshare x86_64, OpenWrt mips
- The config.json, bypass.list and proxy.list must be putted with otransproxy.sh under the same location.
- Requirements: dnsmasq, iptables, ipset.
- You must add your IPs/domains of V2Ray servers into bypass.list to avoid infinitely proxy.
- The script will try to parse the configuration of dnsmasq under the
/tmp/resolv.conf.autoto get the upstream DNS server. If the file does not exist, 192.168.1.1 will be used as upstream DNS server. - You must append the following JSON for each outbound. This prevents iptables forward the network traffic infinitely.
"streamSettings": {
"sockopt": {
"mark": 255
}
}
- Currently, OTransproxy only supports forwarding TCP traffic.
V2RAY做透明代理
目标
- 配置 v2ray 使其接受透明代理的流量
- 配置 iptables 将所有 tcp 和 udp 53 的流量转发给 v2ray
- OpenWrt 配置 v2ray 服务
V2ray 配置
v2ray 的配置如下:
{
"log": {
"access": "",
"error": "",
"loglevel": "warning"
},
"policy": {
"levels": {
"0": {
"uplinkOnly": 0,
"downlinkOnly": 0,
"connIdle": 150,
"handshake": 4
}
}
},
"inbounds": [
{
"port": 1088,
"listen": "0.0.0.0",
"protocol": "http",
"settings": {
"userLevel": 0,
"auth": "noauth",
"udp": true,
"ip": "127.0.0.1"
},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
},
{
"port": "1099",
"listen": "0.0.0.0",
"protocol": "dokodemo-door",
"settings": {
"userLevel": 0,
"network": "tcp,udp",
"timeout": 30,
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"mux": {
"enabled": false,
"concurrency": 8
},
"protocol": "vmess",
"tag": "default",
"settings": {
"vnext": [
{
"address": "127.0.0.1",
"users": [
{
"id": "a994b3c1-c7cc-4868-8072-c93e491bba0b",
"alterId": 64,
"level": 0,
"security": "aes-128-gcm"
}
],
"port": 10086
}
]
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],
"dns": {
"servers": ["8.8.8.8", "8.8.4.4", "localhost"]
},
"routing": {
"strategy": "rules",
"domainStrategy": "IPIfNonMatch",
"settings": {
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
}
]
}
}
}(我按照上面的配置文件,想搭配mac系统的pf做全局代理,没成功)
配置里有几个重点要说下,第一个是 dokudemo-door 的配置:
{
"port": "1099",
"listen": "0.0.0.0",
"protocol": "dokodemo-door",
"settings": {
"userLevel": 0,
"network": "tcp,udp",
"timeout": 30,
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}不要忘了添加sniffing的配置,这个配置是为了从流量中提取 ip 和 domain 信息,这样针对 ip 和 domain 的路由规则才能生效。
第二个是要给所有的outbound都打上 mark 的配置:
"streamSettings": {
"sockopt": {
"mark": 255
}
}这样 iptables 才能区分 v2ray 流量和非 v2ray 流量,非 v2ray 流量会被转发给 v2ray,v2ray 流量就直接从路由器发出去了。这样就避免了死循环,后面 iptables 规则的时候还会提到。
接下来就可以启动 v2ray 测试了
./v2ray -config client_proxy.json通过 http 的inbound来测试下隧道
curl -Is -x 127.0.0.1:1088 https://www.google.com没问题就可以配置 iptables 了。
Iptables 配置
先说明一点,Linux 内核的包处理框架是 Netfilter,而 iptables 只是 userspace 的工具而已,但是多年来大家叫 iptables 其实多数都是指的 Netfilter,只是习惯了。
Iptables 这块的挑战比较大,我一路试错过来,总结来说有以下几点:
- 要理解 iptables 的各个表中的链的先后顺序
- 要捕捉其他设备过来的 tcp 流量
- 要捕捉本机发起的 tcp 流量
- 要捕捉其他设备过来的 udp 53 流量,也就是 DNS 流量
- 要捕捉本机发起的 DNS 流量
Netfilter 数据包流程图:
https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg
从这张图中我们可以看出对于其他设备过来的流量都应该在PREROUTING这个链来做,而对于本机发出的流量应该在OUTPUT这个链来做。但由于重定向 tcp 和 udp 流量在实现上有区别,分别用到了 iptables 里的REDIRECT和TPROXY两种技术。参考这篇博客所说,是因为 ss-redir 应用没有实现 UDP REDIRECT 相关的代码,当然我也把 UDP 全都通过REDIRECT转发给了 v2ray 结果也不行,所以 UDP 转发的部分还是通过TPROXY来实现的。
REDIRECT vs TPROXY
REDIRECT其实是 DNAT 的一种特殊形式,特殊在其把数据包的目标 IP 改成了 127.0.0.1,端口改成了--to-ports 参数指定的本地端口,这样本机的透明代理程序就能处理这个包,应用能通过内核的状态信息拿到被改写之前的目标 IP 和端口号,具体参考这里
TPROXY比REDIRECT新的特性,它能做到不修改数据包,应用只需一点改动就能实现REDIRECT所有的功能,内核文档里有如下说明:
Transparent proxying often involves "intercepting" traffic on a router. This is usually done with the iptables REDIRECT target; however, there are serious limitations of that method. One of the major issues is that it actually modifies the packets to change the destination address -- which might not be acceptable in certain situations. (Think of proxying UDP for example: you won't be able to find out the original destination address. Even in case of TCP getting the original destination address is racy.)
从这段说明里似乎 UDP 并没有内核状态来记录更改前的 IP 地址,这与这篇博客所说所说的有些矛盾,我目前的理解还是 UDP 在内核没有状态记录。TPROXY得以实现归结为三个要点:
- 将流量重定向到本地路由
- 路由规则定义去向
- 代理程序监听,通过特殊的参数可以响应非本机的 IP(因为包的目的地址没改嘛)
重定向 TCP 流量
新建一个 nat 链,排除私网地址流量
iptables -t nat -N V2RAY
# Ignore your V2Ray outbound traffic
# It's very IMPORTANT, just be careful.
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff
# Ignore LANs and any other addresses you'd like to bypass the proxy
# See Wikipedia and RFC5735 for full list of reserved networks.
iptables -t nat -A V2RAY -d 0.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 127.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 169.254.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 172.16.0.0/12 -j RETURN
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t nat -A V2RAY -d 240.0.0.0/4 -j RETURN
# Anything else should be redirected to Dokodemo-door's local port
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 1099注意这里有一个关键规则iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff,这个规则就是为了排除 v2ray 要发出去的流量,没有这个规则的话就成死循环了,v2ray 要发出去的流量又被重定向给了 v2ray。
然后分别在PREROUTING和OUTPUT连个链里应用我们新建的V2RAY链,前者是为了重定向其他设备过来的 TCP 流量,后者是重定向本机发出的 TCP 流量。
# apply redirect for traffic forworded by this proxy
iptables -t nat -A PREROUTING -p tcp -j V2RAY
# apply redirect for proxy itself
iptables -t nat -A OUTPUT -p tcp -j V2RAY重定向 UDP 流量
这块要复杂一些,先新建一个 mangle 链,匹配 UDP 流量,然后应用TPROXYtarget,同时打上特定的 mark
# UDP Redirect
iptables -t mangle -N V2RAY
iptables -t mangle -A V2RAY -p udp -j RETURN -m mark --mark 0xff
iptables -t mangle -A V2RAY -p udp --dport 53 -j TPROXY --on-port 1099 --tproxy-mark 0x01/0x01注意这里也有一个关键规则iptables -t mangle -A V2RAY -p udp -j RETURN -m mark --mark 0xff目的和 TCP REDIRECT 里的一样,避免死循环。
然后配置策略路由,按 mark 匹配流量,将流量路由到本机回环接口。
# add route for udp traffic
ip route add local default dev lo table 100
ip rule add fwmark 1 lookup 100注意,这条路由规则的类型是local,我的理解内核把TPEOXY和路由关联起来了
最后就是,把这条链应用到PREROUTING链里,这样就能重定向其他设备过来的 UDP 流量了。
iptables -t mangle -A PREROUTING -j V2RAY好像还没有完,我们还没有重定向本机发出的 UDP 流量,这也是我目前的一个困惑点。先说我的做法吧,我再 mangle 表的OUTPUT链里添加了如下两条规则:
iptables -t mangle -N V2RAY_MARK
iptables -t mangle -A V2RAY_MARK -p udp -j RETURN -m mark --mark 0xff
iptables -t mangle -A V2RAY_MARK -p udp --dport 53 -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j V2RAY_MARK第一条规则仍然是排除 v2ray 自己的流量,第二条是给 UDP 数据包打上了 mark,而只是打上 mark 怎么就出发上面的重定向规则嘞?目前我的比较粗浅的理解就是上面数据包流程图里 mangle 的OUTPUT链会触发 reroute check,也就让数据包重新从PREROUTING链走了一遍。
OpenWrt 集成
将 v2ray 作为 OpenWrt 跑到时候需要安装一些依赖包
opkg update
opkg install bash kmod-ipt-tproxy iptables-mod-tproxy bind-dig编写 iptables 操作脚本
#!/bin/bash
# -*- coding: utf-8 -*-
start() {
# TCP Redirect
# Create new chain
iptables -t nat -N V2RAY
# Ignore your V2Ray outbound traffic
# It's very IMPORTANT, just be careful.
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff
# Ignore LANs and any other addresses you'd like to bypass the proxy
# See Wikipedia and RFC5735 for full list of reserved networks.
iptables -t nat -A V2RAY -d 0.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 127.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 169.254.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 172.16.0.0/12 -j RETURN
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t nat -A V2RAY -d 240.0.0.0/4 -j RETURN
# Anything else should be redirected to Dokodemo-door's local port
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 1099
# apply redirect for traffic forworded by this proxy
iptables -t nat -A PREROUTING -p tcp -j V2RAY
# apply redirect for proxy itself
iptables -t nat -A OUTPUT -p tcp -j V2RAY
# UDP Redirect
iptables -t mangle -N V2RAY
iptables -t mangle -A V2RAY -p udp -j RETURN -m mark --mark 0xff
iptables -t mangle -A V2RAY -p udp --dport 53 -j TPROXY --on-port 1099 --tproxy-mark 0x01/0x01
iptables -t mangle -N V2RAY_MARK
iptables -t mangle -A V2RAY_MARK -p udp -j RETURN -m mark --mark 0xff
iptables -t mangle -A V2RAY_MARK -p udp --dport 53 -j MARK --set-mark 1
# add route for udp traffic
ip route add local default dev lo table 100
ip rule add fwmark 1 lookup 100
# Apply the rules
# apply udp tproxy for traffic forworded by this proxy
iptables -t mangle -A PREROUTING -j V2RAY
# apply udp tproxy for proxy itself
iptables -t mangle -A OUTPUT -j V2RAY_MARK
}
stop() {
iptables -t nat -D PREROUTING -p tcp -j V2RAY
iptables -t nat -D OUTPUT -p tcp -j V2RAY
iptables -t nat -F V2RAY
iptables -t nat -X V2RAY
iptables -t mangle -D PREROUTING -j V2RAY
iptables -t mangle -F V2RAY
iptables -t mangle -X V2RAY
iptables -t mangle -D OUTPUT -j V2RAY_MARK
iptables -t mangle -F V2RAY_MARK
iptables -t mangle -X V2RAY_MARK
ip rule del fwmark 1 lookup 100
ip route del local default dev lo table 100
}
case $1 in
start)
start
;;
stop)
stop
;;
*)
echo "$0 start|stop"
;;
esac然后是服务管理脚本
#!/bin/sh /etc/rc.common
# "new" style init script
# Look at /lib/functions/service.sh on a running system for explanations of what other SERVICE_
# options you can use, and when you might want them.
START=80
STOP=20
APP=v2ray
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1
PREFIX=/usr/local/v2ray
start() {
service_start $PREFIX/v2ray -config $PREFIX/client_proxy.json
$PREFIX/client_proxy.sh start
}
stop() {
$PREFIX/client_proxy.sh stop
service_stop $PREFIX/v2ray
}最后启用脚本,开机启动
/etc/init.d/v2ray start
/etc/init.d/v2ray enable参考文档
- Iptables 指南
- v2ray 官方文档
- Linux 使用 TPROXY 进行 UDP 的透明代理
- v2ray 白话文教程
- PowerDNS 关于 TPROXY 的解释
- TPROXY 官方文档
- Netfilter 维基百科
- OpenWrt 服务脚本
- -------------------
家庭网接入V2RAY透明代理
- 兼容各种设备,比如 IPTV,NAS
- 接入设备无感知,无需做任何配置
- 设备间互访不受影响
下图为应用透明代理前我的家庭网拓扑:
由于联通路由光猫如果改成光猫的话 IPTV 就不好使了,所以这个猫比如像其名字一样作为家庭网关了。
方案 1 嵌套路由器模式
这种方案的网络拓扑图如下:
直接把极路由刷上 OpenWrt 改成路由模式,然后上透明代理就可以了。这种方案优点就是配置成本很小,缺点是电视,IPTV 和 NAS 和手机电脑等设备被分割到了两个局域网内,这就造成了:
- 只能单向发起通信,比如电脑可以访问 NAS,而 NAS 就不能直接访问电脑了
- AirPlay 之类的就不好使了,手机没法投屏到电视了:
方案 2 两个网关模式
这种方案拓扑图如下:
极路由还是工作在 AP 模式,当然也可以把透明代理做在上面。由于我的极路由已经跑了老毛子系统,而且从 NAS 上虚拟出来的 OpenWrt 性能应该比极路由更好一些,所以我就跑了一个 OpenWrt 以单臂路由方式当做透明代理。首先,这个拓扑上所有的设备都跑在一个局域网内,包括极路由,NAS 以及 NAS 上的虚拟机,而且这个局域网里有两个网关路由光猫和 OpenWrt;然后,我要关闭路由光猫的 DHCP 功能,因为这个 DHCP 不满足条件,不能将非本机的的 IP 配置成 DHCP 网关;最后,我需要在 OpenWrt 上做如下的配置:
- 默认的 DHCP 配置让所有的设备的网关指向了 OpenWrt
- OpenWrt 要配置一个静态地址,而且默认路由要指向路由光猫
- 我们可以配置 DHCP 来根据 mac 地址来让部分设备的网关直接指向路由光猫,这样对于不需要翻墙的电视和 IPTV 就绕过了 OpenWrt 直接出去了。
现在我们来配置下 OpenWrt:
# 在lan接口上开启DHCP
uci set dhcp.lan.ignore='0'
uci set dhcp.lan.start='100'
uci set dhcp.lan.limit='99'
# 配置静态IP并且默认路由指向联通路由光猫
uci set network.lan.proto='static'
uci set network.lan.ipaddr='192.168.1.200'
uci set network.lan.netmask='255.255.255.0'
uci set network.lan.gateway='192.168.1.1'
uci set network.lan.dns='192.168.1.1'
# 匹配特定mac地址,对它们分配特殊的网关地址
uci set dhcp.iptv=host
uci set dhcp.iptv.name='iptv'
uci set dhcp.iptv.tag='free'
uci set dhcp.iptv.mac='2c:55:d3:ab:86:64' 'c8:0e:77:75:ea:b3'
uci set dhcp.free=tag
uci set dhcp.free.dhcp_option='3,192.168.1.1'
uci commit
service dnsmasq restart方案 3 单路由器模式
这种方案拓扑图如下:
首先,修改联通路由光猫改成桥接模式让其只作为猫使用,具体可以参考这个帖子,具体方法如下:
- 进 http://192.168.1.1/hidden_version_switch.gch ,选 default version,密码 CUAdmin
- 机器自动重启之后就可以进 http://192.168.1.1/cu.html 了, 选管理员账户,密码 CUAdmin
- 进去之后删掉之前的 internet 配置,然后新建 internet bridge,vlan 选项记得选改 tag,然后在 vlanid 里填 3961(这里是北京联通的 vlanid,我测试是可以的)
- iptv 那块选 dhcp,vlan_i 填 3964 即可(这步我做了但是 iptv 并不能工作,IPTV 能正常工作的朋友请分享下你的配置吧)
然后极路由作为网关和透明代理,所有的设备都以极路由为网关,而且 DHCP 这块不需要啥特殊配置了。但是路由光猫改成桥接模式后 IPTV 就不好使了,所以这种场景不适合我,如果你不需要 IPTV,那么这种模式最为理想,当然得有个比较牛逼的路由器哇。
参考文档
- --------------------------------
V2Ray透明代理/透明网关/路由器翻墙
- 这篇文章主要记录V2Ray当作透明代理时客户端的配置。
首先我在PVE里面开了一台虚拟机,安装了Debian9,使用ROOT权限登录进去开启IPv4转发:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p
安装系统的时候使用了DHCP,这里因为要当成网关(旁路由)使用,所以编辑网卡配置文件,改为静态IP:
nano /etc/network/interfaces
我的具体配置:
allow-hotplug ens18 iface ens18 inet static address 192.168.0.11 # 这台虚拟机的IP gateway 192.168.0.1 # 上级路由的IP netmask 255.255.255.0
重启网络服务,因为是在PVE内的虚拟机,可能重启网络服务会失败,那么直接重启虚拟机:
systemctl restart networking.service reboot
重启登录上来之后,开始安装V2Ray,因为是国内的网络环境,官方的install.direct一键安装脚本无法正常使用,所以这里改为手动安装,首先下载最新版本的V2Ray/解压:
mkdir -p /opt/v2ray && cd /opt/v2ray wget https://github.com/v2ray/v2ray-core/releases/download/v4.20.0/v2ray-linux-64.zip unzip v2ray-linux-64.zip
创建需要的目录:
mkdir -p /usr/bin/v2ray /etc/v2ray
移动文件到对应的目录:
cp v2ctl /usr/bin/v2ray cp v2ray /usr/bin/v2ray cp geoip.dat /usr/bin/v2ray cp geosite.dat /usr/bin/v2ray cp vpoint_vmess_freedom.json /etc/v2ray/config.json cp systemd/v2ray.service /etc/systemd/system/v2ray.service
编辑systemd服务文件:
nano /etc/systemd/system/v2ray.service
在[Service]下面加一行,解决too many open files的问题:
LimitNOFILE=1048576
启动V2Ray服务:
systemctl daemon-reload systemctl start v2ray.service systemctl enable v2ray.service
现在编辑V2Ray的配置文件,清空里面的所有配置:
nano /etc/v2ray/config.json
这里给出我目前正在用的两份配置文件,第一种就相当于是全局代理,所有流量都走代理:
{ "inbounds": [ { "port": 1080, "protocol": "socks", "settings": { "auth": "noauth", "udp": true } }, { "port": 12315, // 透明代理开放的端口号 "protocol": "dokodemo-door", "settings": { "network": "tcp,udp", "followRedirect": true // 这里要为true才能接受来自iptables的流量 }, "sniffing": { "enabled": true, "destOverride": ["http", "tls"] } } ], "outbounds": [ { "protocol": "vmess", "settings": { "vnext": [ { "address": "lala.im", // 服务器地址,请修改为你自己的服务器IP或域名。 "port": 50000, // 服务器端口,与服务器上的配置文件要相同 "users": [ { "id": "你的UUID", // 用户的UUID必须与服务器端配置相同 "alterId": 64 // 此处的值也应当与服务器相同 } ] } ] } } ] }
第二种对流量进行智能路由,需要的域名走代理,国内的域名/IP则直连,因为这套配置还使用了外部GEO文件,所以要想正常使用,还需要先下载外部GEO文件到V2Ray的运行目录:
wget https://github.com/ToutyRater/V2Ray-SiteDAT/raw/master/geofiles/h2y.dat -O /usr/bin/v2ray/h2y.dat
配置如下:
{ "inbounds": [ { "port": 1080, "protocol": "socks", "settings": { "auth": "noauth", "udp": true } }, { "port": 12315, // 透明代理开放的端口号 "protocol": "dokodemo-door", "settings": { "network": "tcp,udp", "followRedirect": true // 这里要为true才能接受来自iptables的流量 }, "sniffing": { "enabled": true, "destOverride": ["http", "tls"] } } ], "outbounds": [ { "tag": "proxy", // 打一个TAG,让外部GeoFile使用此TAG处理被GFW屏蔽的域名 "protocol": "vmess", "settings": { "vnext": [ { "address": "lala.im", // 服务器地址,请修改为你自己的服务器IP或域名。 "port": 50000, // 服务器端口,与服务器上的配置文件要相同 "users": [ { "id": "你的UUID", // 用户的UUID必须与服务器端配置相同 "alterId": 64 // 此处的值也应当与服务器相同 } ] } ] } }, { "tag": "block", // 黑洞TAG,让外部GeoFile使用此TAG屏蔽广告域名 "protocol": "blackhole", "settings": {} }, { "tag": "direct", // 直连TAG,处理国内域名和IP使其直连 "protocol": "freedom", "settings": {} } ], "routing": { "domainStrategy": "IPOnDemand", "rules": [ { "type": "field", "outboundTag": "proxy", "domain": ["ext:h2y.dat:gfw"] // GFWList }, { "type": "field", "outboundTag": "block", "domain": ["ext:h2y.dat:ad"] // 广告域名屏蔽 }, { "type": "field", "outboundTag": "direct", "domain": ["geosite:cn"] // 中国大陆主流网站的域名 }, { "type": "field", "outboundTag": "direct", "ip": [ "geoip:cn", // 中国大陆的IP "geoip:private" // 私有地址IP,如路由器等 ] } ] } }
配置完成之后测试:
/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json -test
有错排错没问题的话重启V2Ray:
systemctl restart v2ray.service
最后创建iptables规则,对流量进行处理:
iptables -t nat -N V2RAY iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12315 iptables -t nat -A PREROUTING -p tcp -j V2RAY
局域网内的其他机器,修改网关IP为这台虚拟机的IP即可:
现在只要接入你这个网络的设备,无论是电脑还是手机等,都可以实现自动翻墙/广告屏蔽等功能。
一点补充:
如果你使用第一套配置(全局代理)其实也可以实现对流量进行路由,并且据说这种路由方法比V2Ray自带的原生GeoIP方法效率更高,更适合跑在CPU性能不咋地的路由器上。
先重启机器清空所有iptables规则:
reboot安装ipset:
apt -y install ipset
下载中国IP地址列表:
wget https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt
创建一个ipset链:
ipset -N cn hash:net
将中国的IP都加入到ipset链:
for i in $(cat china_ip_list.txt); do ipset -A cn $i; done
执行下面的命令处理流量:
iptables -t nat -N V2RAY iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN iptables -t nat -A V2RAY -p tcp -m set --match-set cn dst -j RETURN iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12315 iptables -t nat -A PREROUTING -p tcp -j V2RAY
差不多用了5年的ss透明代理,最近换成了v2ray。ss透明代理的好处是配置方便、生态成熟、对硬件要求不高。
只要不是太老的路由器,可刷OpenWRT,就基本可以用ss透明代理,就连很多年前的TP link 703N也有不少玩家魔改内存上OpenWRT。
因为一段时间前,ss官方推荐换v2ray混淆插件而不是simple obfs了,后来我试了一次,在路由器上运行非常缓慢,而且我的路由器还不错,Linksys 1900ac v2,就放弃了。最近又想折腾一下,于是用电脑上的v2ray试了下,飞一般的速度,同时用ss并不会达到这样的速度,于是开始着手准备v2ray透明代理搭建。
V2Ray透明代理
如果v2ray没法用透明代理我可能也还会将就ss。因为目前的路由器没法直接运行v2ray,空间和性能都跟不上了,考虑软路由,我的youtube首页总有几个视频是软路由选购、测评。最终没有买,用NAS开了台虚拟机安装v2ray,作为旁路由接入。其实用软路由多半也是用旁路由的模式。另外还考虑了买下一代Linksys产品,再刷openWRT安装v2ray,本着艰苦创业的精神,放弃了。
旁路由也类似一台设备接入到主路由中,只不过有一部分特别的职责,它可以处理其他设备发来的请求,处理完后还会发回对应设备,作用与主路由的部分功能类似。
一般家庭网络中只有一个网关,作用是连接内部与外部网络,网络内部设备需要访问互联网时,例如要访问百度,则需要通过网关与外界沟通,在百度看来,一直与网关沟通,而不知道网络中的那一台设备在和自己通信,百度也并不关心。
所以最简单的配置就是把旁路由配置成网关,这样网络内其他设备需要访问外网时就会与这台旁路由联系,而旁路由本身并不能直接访问外网,它需要继续与上级设备沟通,而上级设备就是主路由了。
因为还在实验,不想让所有设备都走旁路由,而且需要出国的设备也不多,没必要都接入到旁路由。于是采用了更复杂的路由配置——源地址路由。
source route
在主路由上添加了一个路由表,修改/etc/iproute2/rb_tables
10 v2ray
添加默认网关
ip route add default via 192.168.1.32 table 10
给路由表10添加默认网关,没有其他规则,这样进入该路由表的流量就都转入到了192.168.1.32了,这是旁路由的IP
再添加一条规则
ip rule add from 192.168.1.240/32 table 10
意思是来自192.168.1.240的流量走路由表10,而进入了路由表10就会继续进入到旁路由
不过这样添加很麻烦,每次需要让某个设备出国的话需要在主路由上添加ip rule,后面针对这个做了优化。
透明代理配置
v2ray配置主要包含inbound, outbound, dns, routing
inbound
{
"tag": "transparent",
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"streamSettings": {
"sockopt": {
"tproxy": "tproxy"
}
}
}
协议dokodemo-door,监听12345端口,使用tproxy方式完成透明代理。
本想省略followRedirect,文档描述这个参数设置成true才可以处理iptables的redirect,但我用的是tproxy,理论讲可以省略,然而省略了就不行。
network配置tcp,udp表示接受这两种协议的流量。
tproxy可用tproxy或者redirect,两种透明代理的方法,推荐tproxy,可以代理IPv4/6流量、UDP流量;redirect只能IPv4和UDP。代理UDP流量的目的是让DNS解析也能走代理,因为某些网站的DNS解析也会被恶意篡改,即便你的代理再好再快,如果不能得到正确IP地址的话,一样无法正常访问网站。
sniffing配置,可以从流量中解析出域名和协议,尝试解析,并不是所有流量都能得到域名和协议。猜测:如果解析出来了,并且与配置的destOverride匹配的话,那么就会修改这些流量的outbound target,因为在没有解析的时候只能得到IP,用来匹配outbound,但如果有了域名、协议,就可以做更精确的路由,比如解析出了bt协议,可以选择禁止bt还是其他怎样。
outbound
没啥特别,第一个是proxy的配置
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "your proxy address",
"port": your proxy port,
"users": [
{
"id": "your id",
"alterId": your alert id
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"sockopt": {
"mark": 255
}
},
"mux": {
"enabled": false
}
}
streamSettings根据需要填写networking和security,但需要注意sockopt设置mark是透明代理需要。
mux配置默认关闭就好,文档没看清楚,以为开着看视频啥的更好,结果并不是,是更差。开着的话看youtube视频能到10W,关闭后能到20W。。。同一时间同一个server。
另外几个outbound
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
},
{
"tag": "dns-out",
"protocol": "dns",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
direct和dns-out没啥特别,要mark。
DNS
v2ray内建的dns配置
{
"servers": [
"8.8.8.8",
"1.1.1.1",
{
"address": "114.114.114.114",
"port": 53,
"domains": [
"geosite:cn",
"domain:ntp.org",
"domain:zoom.us",
"domain:slack.com",
"domain:slack-core.com"
]
},
"223.5.5.5"
]
}
国内域名、ntp、其他需要用国内DNS解析的可以继续添加。其他域名就从8.8.8.8开始解析了。
routing
这是最复杂的一部分,几乎能和上面各个部分联系起来。
{
"domainStrategy": "IPIfNonMatch",
"rules": [
{ "type": "field", "inboundTag": [ "transparent" ], "port": 53, "network": "udp", "outboundTag": "dns-out" },
{ "type": "field", "inboundTag": [ "transparent" ], "port": 123, "network": "udp", "outboundTag": "direct" },
{ "type": "field", "ip": [ "223.5.5.5", "114.114.114.114" ], "outboundTag": "direct" },
{ "type": "field", "ip": [ "8.8.8.8", "1.1.1.1" ], "outboundTag": "proxy" },
{ "type": "field", "ip": [ "geoip:private", "geoip:cn" ], "outboundTag": "direct" },
{ "type": "field", "domain": [ "vali.cp31.ott.cibntv.net" ], "outboundTag": "direct" },
{ "type": "field", "domain": [ "geosite:category-ads-all" ], "outboundTag": "block" },
{ "type": "field", "domain": [ "geosite:cn" ], "outboundTag": "direct" }
]
}
Routing控制流入v2ray的流量该如何流出,主要目的就是让该走代理的流量走代理,不该走的不走。
目前的规则:
- 进入的udp流量,端口是53的,走
dns-out,dns-out就是mark一下 - 进入的udp流量,端口是123的,走
direct,直连 - 114DNS和aliDNS走
direct - GoogleDNS和CloudflareDNS走
proxy - 内网地址IP、国内IP走
direct vali.cp31.ott.cibntv.net这个域名是youku播放视频前需要访问的,默认被放在了广告域名中,会被下一条规则block,但在使用投影仪投屏时,如果访问不到这个域名,视频播放就有问题,于是放行了geosite:category-ads-all表示所有的广告域名,会被block- 最后,国内网站域名,直连
- 匹配不到的,走
outbound第一个,即proxy
domainStrategy可选值:"AsIs" | "IPIfNonMatch" | "IPOnDemand”。
这三个可选值,不管选哪一个,要求都是能解析出域名,解析不出的话,我猜测还是用IP匹配。
默认AsIs,只用域名选择路由。猜测意思是能解析出域名的,会用域名在rules中匹配规则;没有域名的,用IP匹配。
进一步,IPIfNonMatch,如果有一个域名匹配不了,那么会解析域名,解析出来的IPs,会再次匹配。
最后,IPOnDemand,如果rules中有IP相关的规则,就会把域名解析成IP再匹配规则。
让udp流量不要进入v2ray:
sudo iptables -t mangle -A V2RAY -p udp -m multiport --dport 3478,3479,8801:8810 -j RETURN
------------------------------------
v2ray 结合 iptables 做透明代理
有些软件或者游戏没法设置代理,又需要走 v2ray 的时候,用 dokodemo-door 这个 protocol 配合 iptables 可以实现局域网其他机器无感知透明代理。
很简单,先修改 config.json,多加一个 dokodemo-door 协议的 inboundDetour,然后给代理的 outbound 加个 tag 比如 proxy
"inboundDetour": [
{
"protocol": "dokodemo-door",
"port": 8081,
"domainOverride": ["tls","http"],
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"tag":"forwardingport"
}
]
在 routing.settings.rules 里多加一个策略
"routing": {
{
"type": "field",
"inboundTag": ["forwardingport"],
"outboundTag": "proxy"
}
}
重启 v2ray,在命令行下 root 身份执行
iptables -t nat -N V2RAY
iptables -t nat -A V2RAY -d 192.168.2.0/16 -j RETURN # 局域网网段
iptables -t nat -A PREROUTING -p tcp -j V2RAY # tcp 全部走 V2RAY 这个链
iptables -t nat -A PREROUTING -p udp -j V2RAY # udp 全部走这个链
这样准备工作就做好了,这只是流量都走到 V2RAY 这个 nat chain,现在这个 chain 还没有任何规则,跟没加是一样的。
然后把需要代理的流量转发到本地 dokodemo-door 端口,比如目标全部 tcp 21 端口的流量
iptables -t nat -A V2RAY -p tcp --dport 21 -j REDIRECT --to-ports 8081
比如全部来自 192.168.2.100 的流量
iptables -t nat -A V2RAY -p tcp -s 192.168.2.100 -j REDIRECT --to-ports 8081
全部流量都透明代理
iptables -t nat -A V2RAY -j REDIRECT --to-ports 8081
删除某条规则的话直接把 -A 换成 -D,或者 iptables -t nat -F V2RAY 全清空。
------------------------------
一文玩转openwrt路由器上的V2ray透明代理
本文主要是自己配置过程的流水帐,也算作是一个备份,防止以后再弄的时候忘了流程。本文使用openwrt-v2ray和luci-app-v2ray作为配置工具,前者为V2ray的Openwrt的二进制文件,后者为可视化的配置工具。经过一段时间的摸索,发现该配置工具比原版V2ray+手动配置透明代理要简单的多,希望能够帮助到正在研究V2ray+透明代理的玩家。
更换源
1.安装支持https的工具
如果你想快速安装软件,那么必须换成国内的openwrt的源,但是目前国内好用的源都是https的。
opkg update
opkg install ca-certificates luci-ssl-openssl
2.替换系统源(推荐)
编辑源文件/etc/opkg/customfeeds.conf,我是软路由,所以是x86_64,请根据自己实际情况替换这部分。最后的kmod那条可加可不加,这个自己随意。编辑好自定义源文件后,还要把同目录下系统自带的源文件distfeeds.conf里的内容全部注释掉或删除。自定义源文件内容如下:
src/gz openwrt_core https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/targets/x86/64/packages
src/gz openwrt_base https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/packages/x86_64/base
src/gz openwrt_luci https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/packages/x86_64/luci
src/gz openwrt_packages https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/packages/x86_64/packages
src/gz openwrt_routing https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/packages/x86_64/routing
src/gz openwrt_telephony https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/packages/x86_64/telephony
src/gz openwrt_kmods https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/19.07.1/targets/x86/64/kmods/4.14.167-1-e1dd7676581672f6f0bdb1363506dee1
如果不知道自己的架构,可以使用下面的命令查询
opkg print-architecture | awk '{print $2}'
3.安装openwrt-v2ray
openwrt-v2ray作者非常良心,提供了多种架构的编译文件,以及可以在线更新的源,方便日后更新使用,但我们要先把第三方源的key导入才能正常使用。
wget -O kuoruan-public.key http://openwrt.kuoruan.net/packages/public.key
opkg-key add kuoruan-public.key
然后在上面提到的自定义源里增加下面的内容,注意替换架构目录。
src/gz kuoruan_packages https://openwrt.kuoruan.net/packages/releases/x86_64/
src/gz kuoruan_universal https://openwrt.kuoruan.net/packages/releases/all
4.添加Shadowsocks源(可跳过)
方法同上,这里就不赘述了。需要说明的是,这个源是安装ss和dns-forward这类工具的源,有需要可以添加,没需要就跳过吧,我下面的教程没有用到这里的相关程序。
wget http://openwrt-dist.sourceforge.net/openwrt-dist.pub
opkg-key add openwrt-dist.pub
注意替换为自己的架构
src/gz openwrt_dist http://openwrt-dist.sourceforge.net/packages/base/x86_64/
src/gz openwrt_dist_luci http://openwrt-dist.sourceforge.net/packages/luci
安装软件
5.替换dnsmasq
系统自带的dnsmasq功能不全,需要替换掉,而dnsmasq又是系统重要的组成部分(负责分配ip的dhcp和dns解析那部分工作),所以一旦删除,可能会短暂的无法联网,需要先下载到本地再安装,下面的方法和顺序都是用血泪探索出来的。
注意,我下面的代码没有写错,第一条是下载ipk文件到本地,第二条dnsmasq-full安装一定会失败,但目的是让系统自动安装所需要的依赖。
opkg download dnsmasq-full
opkg install dnsmasq-full
opkg remove dnsmasq
opkg install dnsmasq-full_2.80-15_x86_64.ipk
rm dnsmasq-full_2.80-15_x86_64.ipk
6.全面更新(可以跳过)
我是更新强迫党,要尽量保持软件最新。
opkg update
opkg list-upgradable | cut -f 1 -d ' ' | xargs opkg upgrade
7.安装全部插件
下面包含了必要软件、系统工具和部分中文翻译补丁,建议全部安装,如果路由器空间实在不够,可以看看我写的Extroot教程。
opkg update
opkg install luci-i18n-base-zh-cn uhttpd libuhttpd-openssl luci-app-uhttpd luci-i18n-uhttpd-zh-cn ip-full ipset iptables-mod-tproxy iptables-mod-nat-extra libpthread coreutils-base64 ca-bundle curl vim-full vim-runtime v2ray-core luci-app-v2ray luci-i18n-v2ray-zh-cn
安装好openwrt-v2ray后需要为geo文件增加执行权限,不然启动可能报错, 即使你用不到这两个文件。
chmod a+x /usr/bin/geoip.dat
chmod a+x /usr/bin/geosite.dat
可视化配置V2ray
配置v2ray其实是一个很痛苦的过程,一旦按照官方弄好就懒得再去折腾。我开始使用luci-app-v2ray的时候就觉得摸不着头脑,只想直接加载配置好的json文件,但是这样弄真是问题多多,需要手动下载更新中国CIDR文件和GFWlist文件,还需要配置dnsmasq和ipset,然后再配合iptables等等,一旦重装,这些东西想想就头疼。后来经过几次尝试,发现luci-app-v2ray其实非常的好用,上面说的问题只要配置好,都是一键启动,这里把我的配置步骤一步步贴出来,供还没有找到门路的各位参考,而且luci-app-v2ray的官方文档也做的不好,这里就当为他们做个推广教程。
入站连接
按照上面安装好所有软件后,我们要从服务—V2Ray进入主界面,先不看全局设置,来看看入站连接,如图
出站连接
然后来看看出站连接,下图是整体配置,绿色框内是我把默认配置删除后留下的两个,完全没有修改。黄色框内是我新增的三台服务器,因为之后我要用到负载均衡,当然你就一台也没关系,不使用负载均衡就可以了。
随便看一个服务器的配置里,按照你自己服务器的连接方式配置好,相信搞过官方json配置文件的都能看明白这些配置的含义,我这里是用的WS+TLS,所以必须要用443端口。黄色框内是标识名,用于负载均衡,用不到的话可以不写。
路由
路由部分稍微复杂一点,同样,绿色框内是默认配置就带的,我没有修改。下方黄色框内是我自己添加的一个配置,用于真实的代理,这个之后再看,上方黄色框内打勾的是最后启动的配置,所以我只是启用了个别的路由配置。蓝色框内是负载均衡的配置,最下方的标识匹配要和你出站连接里的标识一致。
下面这个图就是我新增的真实代理路由规则,配置非常简单,含义就是所有TCP和UDP连接都走负载均衡器,当然如果你没有设置负载均衡,那么就要设置好出站连接标识。
上面我的代理配置为什么这么简单,还要把我的代理架构简单说一下。所有路由条件其实都在路由器的iptables/ipset层面完成了,能够被输送到v2ray的连接一定是被屏蔽了的,所以可以理解为只要进入v2ray路由系统的一定要走代理,我这里是在v2ray的路由系统中新增了BT下载和去广告的过滤,把这两个规则去掉其实就更好理解了。
透明代理
搞懂了路由路线,再来看看最重要的透明代理设置,就是由于luci-app-v2ray有这部分的配置,省下玩家去搞iptables、ipset和dnsmasq这部分的工作。整体也是非常的简单,但是需要注意的是红框内的部分,我没有开启任何UDP相关的转发,因为一旦开启转发DNS,再配合我上面的路由,那么所有的DNS都要走国外,这让访问国内的网站非常的慢;如果开启UDP转发,那么所有网络都访问不通,这个原因我还没有弄清,不知道是bug还是我没有完全搞明白透明代理。蓝色框内就是帮你完成iptables、ipset和dnsmasq要完成的所有工作,弥补了上面有几率被DNS污染的缺点,也算是在简单和完美之间找到了一个平衡。
全局设置
最后全部设置完成再回过头来看看全局设置,黄色框内勾选好你要启用的各组件的配置,然后勾上已启用,最后保存并应用,不出意外,你的透明代理就搭建好了。
结语
V2ray的玩法很多,配套工具也很丰富,这里只是抛砖引玉,希望大家布不局限于此。我这套东西前前后后折腾了几个月才弄明白,现在已经在家里三个路由器上实验成功,最短也只需要1小时左右就能完全搞定,现在路由器重装起来也不发愁了。另外这套配置不能够代理Telegram手机客户端,添加IP也不行,不知道是不是与UDP有关系,我在入站、出站和路由上搞过MTproxy协议,但是一旦使用,v2ray程序就会崩溃,所以就没再尝试了。最后还有一个小技巧,luci-app-v2ray的配置文件在/etc/config/v2ray,每次只要保存了这个文件,在新的路由器上覆盖配置就能快速配置好哦。
from https://www.solarck.com/openwrt-v2ray.html
-----
http://gsoc-blog.ecklm.com/iptables-redirect-vs.-dnat-vs.-tproxy/













No comments:
Post a Comment