前言:对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做出站代理协议了,你可以修改为vmessshadowsocksvless甚至socks5,因其它类型方案有点多,这里以修改为socks5代理为例,记得本机需要设置相应的上游服务器,方便配置文件的修改。

"outbounds":[
    {
        "tag":"proxy",
        "protocol":"socks",
        "settings":{
            "servers":[
                {
                    "address":"127.0.0.1",
                    "port":1090
                }
            ]
        },
        "streamSettings":{
            "sockopt":{
                "mark":255
            }
        }
    },
    ...
]

提醒:上面添加了本地1090端口的socks5代理,所以你需要使用v2rayclashss或者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.ipv4ipset_rules.ipv4分别作为iptablesipset用于(修改)完整储存和(开机)恢复规则的文件:

  • 创建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一下,测试一下网关规则会不会自动恢复了。

四、结语

本文重要的操作基本都是照搬来的,这里做个记录,方便日后查阅,感谢原文作者写出那么好的教程。如有错误,欢迎留言指正。

参考链接:

标签: none

已有 19 条评论

  1. Robert Robert

    你好,我在加拿大,目前需要搭建一个反向翻墙的透明代理,Trojan/Socks/vmess均可,想让某个设备的全部TCP和UDP流量都发往在国内的VPS,请问如何修改config.json和iptables?我目前在Debian11以及lede-openwrt上的配置都只实现了tcp流量的透明代理。谢谢!

    1. 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

      1. Robert Robert

        但是你的例子里所有国内的域名和IP都是走直连, 只有国外的才走proxy, 而我的要求是所有的TCP/UDP都发给VPS, 肯定还有需要其他更改的地方, 想请教你这点。我的初步想法是干脆不设置routing, 让所有流量默认走outbound里的第一个元素主出站协议。

        我在Trojan-go使用与反馈电报群看到你的名字, 请问我可以通过电报请教你吗?

        1. 嗯,电报里是我,可以交流下

        2. 你这个需求的话,其实不如用ss,就是全部tcp,udp流量都通过代理,太合适不过

          1. Robert Robert

            我完全按照下面的文章在我本地的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"

            }
            root@Debian11:~#
            root@Debian11:~# systemctl restart shadowsocks-libev
            root@Debian11:~#
            root@Debian11:~# systemctl status shadowsocks-libev
            ● shadowsocks-libev.service - Shadowsocks-libev Default Server Service

            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)

            Main PID: 1525 (code=exited, status=255/EXCEPTION)

            CPU: 14ms

            Oct 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:~#

          2. 透明代理本地不是用 ss-server而是ss-redir,还有注意要以root身份启动ss-redir,因为配置文件里有配置udp

          3. https://github.com/shadowsocks/shadowsocks-libev 项目里专门有个配置透明代理的脚本,你可以参考一下,

            https://github.com/shadowsocks/shadowsocks-libev#transparent-proxy-pure-tproxy

  2. Stiwoll Stiwoll

    你好,请教如何将树莓派自己的流量也走代理呢?非常感谢用了你的规则文件后,树莓派作为旁路由(平行局域网)以及树莓派用作AP,自发热点(上行路由)都能顺利使用了。唯独树莓派自己需要定时更新分流文件(geoip.dat、geoside.dat)暂时无法进行。

    1. 你不妨试试在 mangle 表 OUTPUT 链应用这个V2RAY链规则

      iptables -t mangle -I OUTPUT -j V2RAY

      1. Stiwoll Stiwoll

        也就是在 iptables -t mangle -A PREROUTING -j V2RAY 的下方再加一行 iptables -t mangle -I OUTPUT -j V2RAY 对吧?

        1. 对的,你可以试下

          1. Stiwoll Stiwoll

            不行,报错“iptables v1.8.7 (nf_tables): RULE_INSERT failed (Invalid argument): rule in chain OUTPUT”

          2. 你V2RAY链不在了吗?不应该报这个错呀

          3. 你要么参考下这个,可能我说的也不对
            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

          4. Stiwoll Stiwoll

            你好,我结合官方的脚本已经解决了,如下:
            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

          5. 嗯嗯

      2. Stiwoll Stiwoll

        朋友你有推特吗?或者TG。我们加个好友吧,希望能互相交流,共同进步。

        1. 有在用电报, https://t.me/hello_giant

添加新评论