MENU

【歪门邪道】2022年使用openSUSE搭建V2RAY透明代理

April 1, 2022 • 瞎折腾

之前写过一篇搭建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_tproxynft_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 处获得。

Last Modified: April 15, 2022
Archives QR Code
QR Code for this page
Tipping QR Code
Leave a Comment

2 Comments
  1. 只会用,看不懂啊

  2. tey tey

    需要一些操作来将其持久化