使用V2Ray做透明代理方案(TPROXY)
前言:对V2Ray
的路由方案比较感兴趣,因为不用自己去更新相关的域名或者IP数据库,且其有blackhole
协议可以屏蔽广告,还能控制bittorrent
协议,让其走直连,难的就是配置文件的书写了。
本文是参考V2Ray白话文-透明代理方案2
,使用Tproxy
同时对tcp和udp
做透明代理,部署硬件以树莓派 Raspbian
为例,这个方案让国内外域名分别用国内外dns服务器解析,另外支持给国外dns服务器解析过程设置代理,很好的避免CDN可能带来的问题。
一、开启转发支持
1.1 开启树莓派转发支持
从pi
切换到root
用户,执行下面命令,否则可能你每条命令前都要加sudo
:
# 切换到root用户
sudo -i
# 给/etc/sysctl.conf文本末尾追加一行,内容是net.ipv4.ip_forward=1
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
#使之生效
sysctl -p
提醒:开启树莓派转发支持以后,就可以把树莓派做为网关使用了,可以访问国内网络(百度,微信),但是此时还不能上外网(访问Google,Youtube),因为还没配置V2Ray
。
1.2 修改树莓派apt源
下面的命令基于目前的最新的Raspbian10(buster)
进行修改,其基于Debian10(buster)
,请使用hostnamectl
命令确认是属于此版本系统后再进行配置:
# 查看系统版本信息
pi@raspberrypi:~ $ hostnamectl
Static hostname: raspberrypi
Icon name: computer
Machine ID: xxxxxxxxx
Boot ID: xxxxxxxxx
Operating System: Raspbian GNU/Linux 10 (buster)
Kernel: Linux 5.4.51-v7+
Architecture: arm
# 编辑 `/etc/apt/sources.list` 文件,删除原文件所有内容,用以下内容取代:
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib rpi
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib rpi
# 编辑 `/etc/apt/sources.list.d/raspi.list` 文件,删除原文件所有内容,用以下内容取代:
deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui
提醒:使用清华源(镜像)以后,可以极大地提升软件安装速度,这个源也是Raspberry pi官方指定的,可以放心使用。地址是:清华大学Raspbian镜像使用帮助。
1.3 设置静态IP地址
对于不同的机器,不同的系统甚至版本,设置静态IP的方案都不尽相同,所以需要自行搜索设置。下面以Raspbian 10
为例,执行下面命令进行修改:
# 重新安装vim
apt update && apt -y purge vim-common && apt -y install vim
# 修改/etc/dhcpcd.conf文件
vim /etc/dhcpcd.conf
//下面是示例,如果你是网线直连,那么接口填eth0,如果是wifi,那么接口填wlan0
interface eth0
static ip_address=192.168.1.2/24
static ip_routers=192.168.1.1
static domain_name_servers=192.168.1.1 223.5.5.5
// 上面是示例,添加到文件内
# 重启,使之生效
reboot
说明:上面配置方式下,你的局域网网段是192.168.1.0/24
,给树莓派固定的IP是192.168.1.2/24
,这个要根据实际情况做出修改,该文件内也有说明。
二、配置V2Ray
2.1 安装V2Ray
因为正常情况下,你的网络访问Github
不会有很好的速度,所以这里建议直接去v2fly/v2ray-core github releases
下载需要的压缩包,树莓派Raspbian 10
目前还是属于32 bit
系统,执行下面的命令进行操作:
# 可以选择win电脑上下载好,然后通过winscp工具传到你的树莓派里面,这里假设传到/home/pi目录下
wget https://github.com/v2fly/v2ray-core/releases/download/v4.31.2/v2ray-linux-arm32-v7a.zip
# 切换目录
mkdir /usr/local/etc/v2ray && cd /usr/local/etc/v2ray
# 将压缩包移动到此
mv /home/pi/v2ray-linux-arm32-v7a.zip .
# 解压
apt -y install unzip && unzip ./v2ray-linux-arm32-v7a.zip
# 删除配置文件和不需要的压缩包
rm config.json v2ray-linux-arm32-v7a.zip
2.2 正确配置配置文件
上面选择删除了自带的配置文件,下面创建新的配置文件:
# 开始编辑
vim config.json
# 下面是示例,修改出站代理以后作为内容添加到配置文件
{
"inbounds":[
{
"tag":"transparent",
"port":12345,
"listen":"0.0.0.0",
"protocol":"dokodemo-door",
"settings":{
"network":"tcp,udp",
"followRedirect":true
},
"sniffing":{
"enabled":true,
"destOverride":[
"http",
"tls"
]
},
"streamSettings":{
"sockopt":{
"tproxy":"tproxy"
}
}
},
{
"port":1080,
"listen":"0.0.0.0",
"protocol":"socks",
"sniffing":{
"enabled":true,
"destOverride":["http","tls"]
},
"settings":{
"auth":"noauth"
}
}
],
"outbounds":[
{
"tag":"proxy",
"protocol":"trojan",
"settings":{
"servers":[
{
"address":"1.2.3.4",
"port":443,
"password":"passwd"
}
]
},
"streamSettings":{
"security":"tls",
"tlsSettings":{
"serverName":"example.com",
"allowInsecure":false,
"alpn":[
"h2",
"http/1.1"
],
"disableSystemRoot":false,
"certificates":[]
},
"sockopt":{
"mark":255
}
}
},
{
"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",
"1.1.1.1",
"114.114.114.114",
{
"address":"223.5.5.5",
"port":53,
"domains":[
"geosite:cn",
"ntp.org"
]
}
]
},
"routing":{
"domainStrategy":"IPOnDemand",
"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",
"domain":[
"geosite:category-ads-all"
],
"outboundTag":"block"
},
{
"type":"field",
"protocol":[
"bittorrent"
],
"outboundTag":"direct"
},
{
"type":"field",
"ip":[
"geoip:private",
"geoip:cn"
],
"outboundTag":"direct"
},
{
"type":"field",
"domain":[
"geosite:cn"
],
"outboundTag":"direct"
}
]
}
}
//添加至文件后,保存并退出
提醒:添加完配置文件以后,可以在当前目录下执行./v2ray -test -config ./config.json
来检查配置文件是否有误,提示OK,才可以进行下面的步骤。另外,上面默认没有开启日志,如果你要设置开启日志记录,请记得修改日志文件的权限,都设为777
,不然v2ray systemd
无法正确启动,因为它是以nobody
身份启动的。
2.3 出站代理设置为socks5代理(可选)
上面默认使用trojan
做出站代理协议了,你可以修改为vmess
,shadowsocks
、vless
甚至socks5
,因其它类型方案有点多,这里以修改为socks5
代理为例,记得本机需要设置相应的上游服务器,方便配置文件的修改。
"outbounds":[
{
"tag":"proxy",
"protocol":"socks",
"settings":{
"servers":[
{
"address":"127.0.0.1",
"port":1090
}
]
},
"streamSettings":{
"sockopt":{
"mark":255
}
}
},
...
]
提醒:上面添加了本地1090端口的socks5
代理,所以你需要使用v2ray
,clash
,ss
或者trojan
等程序在1090
端口监听socks5
类型流量作为此出站代理的上游,后面只需要修改此上游配置文件,不用修改config.json
此配置文件。
2.4 设置v2ray systemd启动
上面的压缩包解压后,会看到有个./systemd/system
目录,没错,这里就是官方预先配置的服务文件,只需要把它拷贝到相应位置即可:
# 拷贝服务文件
cp /usr/local/etc/v2ray/systemd/system/v2ray.service /etc/systemd/system/
# 主配置文件有了,v2ray,v2ctl,geoip.dat,geosite.dat这些文件还没有到位
cp /usr/local/etc/v2ray/v2* /usr/local/etc/v2ray/geo* /usr/local/bin/
# 启动v2ray
systemctl start v2ray
# 查看运行状态
systemctl status v2ray
# 加入开机自启动
systemctl enable v2ray
三、配置规则
3.1 安装ipset
ipset是一个跟iptables搭配使用的工具,但是默认没有安装,执行下面命令安装:
apt -y install ipset
3.2 创建规则文件
本文使用iptables_rules.ipv4
和ipset_rules.ipv4
分别作为iptables
和ipset
用于(修改)完整储存和(开机)恢复规则的文件:
- 创建ipset集合内容
# 创建目录
mkdir /etc/iptables
ipset create local_ip hash:net
ipset add local_ip 0.0.0.0/8
ipset add local_ip 10.0.0.0/8
ipset add local_ip 127.0.0.0/8
ipset add local_ip 169.254.0.0/16
ipset add local_ip 172.16.0.0/12
ipset add local_ip 192.168.0.0/16
ipset add local_ip 224.0.0.0/4
ipset add local_ip 240.0.0.0/4
上面大概意思是创建local_ip
集合,并给该集合添加(局域网IP)作为集合元素。
- 配置iptables规则
# 设置策略路由
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 -p tcp -m set --match-set local_ip dst -j RETURN
iptables -t mangle -A V2RAY -p udp -m set --match-set local_ip dst -m udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
# 添加应用
iptables -t mangle -A PREROUTING -j V2RAY
提醒:执行完上面命令以后,局域网设备就可以通过修改网关来使用代理服务了,你可以设置来检验下。注意v2ray只是劫持了53 udp
端口的数据,并没有自建dns服务器。这里只设置了局域网网关方式,关于代理网关本身,请参考:透明代理(TPROXY)
3.3 iptables和ipset相关命令
每次修改完ipset
集合内容或者iptables
规则后,你都要执行保存
的操作:
# 手动保存
ipset save > /etc/iptables/ipset_rules.ipv4 或者 ipset save -file /etc/iptables/ipset_rules.ipv4
iptables-save > /etc/iptables/iptables_rules.ipv4 或者 iptables-save -f /etc/iptables/iptables_rules.ipv4
# 手动恢复
ipset restore < /etc/iptables/ipset_rules.ipv4 或者 ipset restore -file /etc/iptables/ipset_rules.ipv4
iptables-restore < /etc/iptables/iptables_rules.ipv4 或者 iptables-restore /etc/iptables/iptables_rules.ipv4
3.4 添加开启启动
每次网关重新开机,之前的策略路由配置和iptables等规则都会恢复默认(空)的状态,但又不可能每次都要手动来一遍,所以有了下面的开机自动执行恢复一次的服务:
vim /etc/systemd/system/tproxy.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/ipset restore -file /etc/iptables/ipset_rules.ipv4 ; /sbin/iptables-restore /etc/iptables/iptables_rules.ipv4
[Install]
WantedBy=multi-user.target
//内容示例
# 设置开机自启动
systemctl enable tproxy
现在你可以reboot
一下,测试一下网关规则会不会自动恢复了。
四、结语
本文重要的操作基本都是照搬来的,这里做个记录,方便日后查阅,感谢原文作者写出那么好的教程。如有错误,欢迎留言指正。
你好,我在加拿大,目前需要搭建一个反向翻墙的透明代理,Trojan/Socks/vmess均可,想让某个设备的全部TCP和UDP流量都发往在国内的VPS,请问如何修改config.json和iptables?我目前在Debian11以及lede-openwrt上的配置都只实现了tcp流量的透明代理。谢谢!
config.json的话,只需要修改出站代理为你在用的vmess或者trojan代理了,
只让一个设备走代理的话,那就最后3.2里面应用V2RAY链的时候只指定这台设备的Ip,假设Ip是 192.168.1.2
iptables -t mangle -A PREROUTING -s 192.168.1.12 -j V2RAY
但是你的例子里所有国内的域名和IP都是走直连, 只有国外的才走proxy, 而我的要求是所有的TCP/UDP都发给VPS, 肯定还有需要其他更改的地方, 想请教你这点。我的初步想法是干脆不设置routing, 让所有流量默认走outbound里的第一个元素主出站协议。
我在Trojan-go使用与反馈电报群看到你的名字, 请问我可以通过电报请教你吗?
嗯,电报里是我,可以交流下
你这个需求的话,其实不如用ss,就是全部tcp,udp流量都通过代理,太合适不过
我完全按照下面的文章在我本地的Debian11透明代理机上配置,公网地址敏感,我贴出来的没有用真实公网地址。如此简单的配置启动时总是报错,发现只有将"server":"152.145.104.112"改为本地IP:192.168.1.3或127.0.0.1或0.0.0.0才能正常启动,而"local_address"可以为任意地址。这显然有问题。请教如何排错?谢谢。我将具体的安装配置及报错信息通过电报发给你,如果你愿意,我可以提供远程SSH登录。由于时差关系,我可能无法及时回复,再次感谢
https://www.gwduan.com/wiki/doku.php?id=computer:net:tproxy
root@Debian11:~# cat /etc/shadowsocks-libev/config.json
"server":"152.145.104.112", "server_port":443, "local_address": "192.168.1.3", "local_port":10808, "password":"Mysspasswd", "timeout":86400, "method":"aes-256-gcm", "mode": "tcp_and_udp"{
}
Loaded: loaded (/lib/systemd/system/shadowsocks-libev.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Sun 2022-10-30 12:30:36 EDT; 2s ago Docs: man:shadowsocks-libev(8) Process: 1525 ExecStart=/usr/bin/ss-server -c $CONFFILE $DAEMON_ARGS (code=exited, status=255/EXCEPTION)root@Debian11:~#
root@Debian11:~# systemctl restart shadowsocks-libev
root@Debian11:~#
root@Debian11:~# systemctl status shadowsocks-libev
● shadowsocks-libev.service - Shadowsocks-libev Default Server Service
Main PID: 1525 (code=exited, status=255/EXCEPTION)
CPU: 14msOct 30 12:30:35 Debian11 systemd[1]: Started Shadowsocks-libev Default Server Service.
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 INFO: binding to outbound IPv4 addr: 192.168.1.3
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 INFO: UDP relay enabled
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 INFO: initializing ciphers... aes-256-gcm
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 INFO: tcp server listening at 152.145.104.112:443
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 ERROR: bind: Cannot assign requested address
Oct 30 12:30:36 Debian11 ss-server[1525]: 2022-10-30 12:30:36 ERROR: failed to bind address
Oct 30 12:30:36 Debian11 systemd[1]: shadowsocks-libev.service: Main process exited, code=exited, status=255/EXCEPTION
Oct 30 12:30:36 Debian11 systemd[1]: shadowsocks-libev.service: Failed with result 'exit-code'.
root@Debian11:~#
透明代理本地不是用 ss-server而是ss-redir,还有注意要以root身份启动ss-redir,因为配置文件里有配置udp
https://github.com/shadowsocks/shadowsocks-libev 项目里专门有个配置透明代理的脚本,你可以参考一下,
https://github.com/shadowsocks/shadowsocks-libev#transparent-proxy-pure-tproxy
你好,请教如何将树莓派自己的流量也走代理呢?非常感谢用了你的规则文件后,树莓派作为旁路由(平行局域网)以及树莓派用作AP,自发热点(上行路由)都能顺利使用了。唯独树莓派自己需要定时更新分流文件(geoip.dat、geoside.dat)暂时无法进行。
你不妨试试在 mangle 表 OUTPUT 链应用这个V2RAY链规则
iptables -t mangle -I OUTPUT -j V2RAY
也就是在 iptables -t mangle -A PREROUTING -j V2RAY 的下方再加一行 iptables -t mangle -I OUTPUT -j V2RAY 对吧?
对的,你可以试下
不行,报错“iptables v1.8.7 (nf_tables): RULE_INSERT failed (Invalid argument): rule in chain OUTPUT”
你V2RAY链不在了吗?不应该报这个错呀
你要么参考下这个,可能我说的也不对
https://guide.v2fly.org/app/tproxy.html#%E9%85%8D%E7%BD%AE%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86%E8%A7%84%E5%88%99
你好,我结合官方的脚本已经解决了,如下:
ipset create local_ip hash:net
ipset add local_ip 0.0.0.0/8
ipset add local_ip 10.0.0.0/8
ipset add local_ip 127.0.0.0/8
ipset add local_ip 169.254.0.0/16
ipset add local_ip 172.16.0.0/12
ipset add local_ip 192.168.0.0/16
ipset add local_ip 224.0.0.0/4
ipset add local_ip 240.0.0.0/4
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 -p tcp -m set --match-set local_ip dst -j RETURN
iptables -t mangle -A V2RAY -p udp -m set --match-set local_ip dst -m udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j V2RAY
iptables -t mangle -N V2RAY_MASK
iptables -t mangle -A V2RAY_MASK -p tcp -m set --match-set local_ip dst -j RETURN
iptables -t mangle -A V2RAY_MASK -p udp -m set --match-set local_ip dst -m udp ! --dport 53 -j RETURN
iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff
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
嗯嗯
朋友你有推特吗?或者TG。我们加个好友吧,希望能互相交流,共同进步。
有在用电报, https://t.me/hello_giant