之前写过一篇搭建 V2RAY 透明代理的文章,那时候搭建在树莓派上,这个树莓派至今还在使用,并且至今这个透明代理还可以使用,但是树莓派有个问题就是作为单臂路由时单程最大只能跑到 2MB/s(树莓派 2B+,这是唯一一个可以通过 USB 口带动的设备)。今天决定使用虚拟机重新搭建一个透明代理,给本机的其他虚拟机使用,这样其他虚拟机在操作 docker、k8s 的时候就不必担心网络不通畅的问题了。
服务端展开目录
关于 V2Ray 的使用方式比较多样,这里我选择比较推荐的 VLESS-TCP-TLS-WS,这种配置不需要额外的 Nginx 等软件,并且在 TCP 模式认证失败时会自动回落到 WS 模式。关于服务端的配置可以参考这个模板。服务端可选开启 BBR 阻塞控制。
客户端展开目录
客户端配置比较复杂,这里分部分说明。
V2Ray 客户端配置展开目录
服务端跑起来之后就可以考虑客户端了,这里客户端是重头戏,因为它要负责作为其他使用仅主机网络的虚拟机的网关,提供上网与代理服务。这里我是用 TPROXY 的方式进行透明代理。客户端配置如下:
- {
- "log": {
- "loglevel": "warning"
- },
- "inbounds":[
- {
- "tag":"transparent",
- "port":12345,
- "protocol":"dokodemo-door",
- "settings":{
- "network":"tcp,udp",
- "followRedirect":true
- },
- "sniffing":{
- "enabled":true,
- "destOverride":[
- "http",
- "tls"
- ]
- },
- "streamSettings":{
- "sockopt":{
- "tproxy":"tproxy",
- "mark":255
- }
- }
- },
- {
- "port":1080,
- "protocol":"socks",
- "sniffing":{
- "enabled":true,
- "destOverride":[
- "http",
- "tls"
- ]
- },
- "settings":{
- "udp":true
- }
- },
- {
- "port":1081,
- "protocol":"http",
- "sniffing":{
- "enabled":true,
- "destOverride":[
- "http",
- "tls"
- ]
- }
- }
- ],
- "outbounds":[
- { // 出口代理,对应服务器的配置
- "tag":"proxy",
- "protocol":"vless",
- "settings":{
- "vnext":[
- {
- "address":"example.com",
- "port":443,
- "users":[
- {
- "id":"",
- "encryption":"none",
- "level":0
- }
- ]
- }
- ]
- },
- "streamSettings":{
- "network":"tcp",
- "security":"tls",
- "tlsSettings":{
- "serverName":"example.com"
- },
- "sockopt":{
- "mark":255
- }
- }
- },
- {
- "tag":"direct",
- "protocol":"freedom",
- "settings":{
- "domainStrategy":"UseIP"
- },
- "streamSettings":{
- "sockopt":{
- "mark":255
- }
- }
- }
- ],
- "routing":{
- "domainStrategy":"IPOnDemand",
- "rules":[
- { // udp53的DNS查询直连
- "type":"field",
- "inboundTag":[
- "transparent"
- ],
- "port":53,
- "network":"udp",
- "outboundTag":"direct"
- },
- { // udp123的NTP校时直连
- "type":"field",
- "inboundTag":[
- "transparent"
- ],
- "port":123,
- "network":"udp",
- "outboundTag":"direct"
- },
- { // bt流量直连
- "type":"field",
- "protocol":[
- "bittorrent"
- ],
- "outboundTag":"direct"
- },
- { // 中国及局域网ip直连
- "type":"field",
- "ip":[
- "geoip:private",
- "geoip:cn"
- ],
- "outboundTag":"direct"
- },
- { // 中国网站直连
- "type":"field",
- "domain":[
- "geosite:cn"
- ],
- "outboundTag":"direct"
- }
- ]
- }
- }
配置文件可以先留存备用,下面来说负责透明代理的虚拟机。
虚拟机配置展开目录
由于透明代理的虚拟机并不负责其他负载,因此只分配给他 1C1G,分配 20GB 硬盘,有两块网卡,一个是 NAT 模式,用于连接互联网,另一个是 VMnet2,配置为仅主机模式,用于向其他虚拟机提供服务。系统选择了 openSUSE Leap 15.3,使用 XFS 作为文件系统,2GB 的交换空间,安装时不额外创建用户,关闭防火墙,配置 VMnet2 的静态 IP 为 10.172.1.1/16,启用 v4 和 v6 转发。
安装完成后进行一个系统更新,如果源特别慢的话可以考虑使用清华源。这里选用 Leap 的原因是它比较稳定,不需要风滚草那样有事儿没事儿滚一滚。更新完成之后安装 V2Ray,将上面的配置文件应用过去,这时候可以通过 10.172.1.1:1080
这个端口来检查我们的代理配置是否正确。我这边测试使用该端口进行大约 5MB/s 的传输时,V2Ray 占用 CPU 大约 10%,网卡软中断占用 1%。
接下来即可配置网络过滤规则了。
Netfilter 配置(nftables)展开目录
与较为熟悉的 iptables 不同,nftables 是更为新颖的一款代替品。但是使用 nftables 要求内核中具备 nft_tproxy
和 nft_socket
,如果 lsmod | grep nft
命令中不包含这两个模块,那么需要创建对应的配置文件以开机启动。配置文件 /etc/modules-load.d/tproxy.conf
:
- nft_tproxy
- nft_socket
该配置文件将会在开机时无条件加载这两个模块。
使用以下命令配置 nftables:
- # 设置策略路由
- ip rule add fwmark 1 table 100
- ip route add local 0.0.0.0/0 dev lo table 100
-
- #代理局域网设备
- nft add table v2ray
- nft add chain v2ray prerouting { type filter hook prerouting priority 0 \; }
- nft add rule v2ray prerouting ip daddr {127.0.0.1/32, 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4, 255.255.255.255/32} return # 前往这些地址的包不需要被代理,其中包括私有IP和TailScale
- nft add rule v2ray prerouting ip saddr {100.64.0.0/10, 172.16.0.0/12} return # 来自Docker和TailScale的流量不被代理
- nft add rule v2ray prerouting mark 0xff return # 直连 0xff 流量
- nft add rule v2ray prerouting meta l4proto {tcp, udp} mark set 1 tproxy to 127.0.0.1:12345 accept # 转发至 V2Ray 12345 端口
-
- # DIVERT 规则,避免已有连接的包二次通过 TPROXY,理论上有一定的性能提升
- nft add table filter
- nft add chain filter divert { type filter hook prerouting priority -150 \; }
- nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept
完成后可以开启一台虚拟机测试一下,只保留一张仅主机网卡,然后设置网关为 10.172.1.1
。测试通过之后先别着急走,由于这些配置在重启后会丢失,因此还需要一些操作来将其持久化:
- mkdir -p /etc/nftables && nft list ruleset > /etc/nftables/rules.v4
-
- cat > /etc/systemd/system/tproxyrule.service <<EOF
- [Unit]
- Description=Tproxy rule
- After=network.target
- Wants=network.target
-
- [Service]
- Type=oneshot
- RemainAfterExit=yes
- ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /usr/sbin/nft -f /etc/nftables/rules.v4
- ExecStop=/sbin/ip rule del fwmark 1 table 100 ; /sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; /usr/sbin/nft flush ruleset
-
- [Install]
- WantedBy=multi-user.target
- EOF
-
- systemctl enable tproxyrule
另外由于 TProxy 支持 UDP 代理,而 UDP 经常会出现数量比较多的情况,这时候可以考虑允许 V2Ray 打开更多文件,以避免出现 too many open files
的错误。修改 /etc/systemd/system/v2ray.service
文件,在 [Service]
下加入如下两行:
- LimitNPROC=500
- LimitNOFILE=1000000
随后刷新并重启 V2Ray:
- systemctl daemon-reload && systemctl restart v2ray
至此,其余的虚拟机都可以使用仅主机模式,通过将网关设置为 10.172.1.1
来上网了,同时安装 Docker 和 k8s 等软件还不需要额外设置镜像仓库,方便又好用,岂不美哉?
- 全文完 -

【歪门邪道】2022 年使用 openSUSE 搭建 V2RAY 透明代理 由 天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。
只会用,看不懂啊
需要一些操作来将其持久化