在OpenWrt上安装和配置V2Ray(V2RayA)

168 次浏览

1、安装V2RayA

opkg update
opkg install luci-app-v2raya

或通过Luci安装。

2、配置V2RayA

在Luci中依次点击【Service】-【v2rayA】-【Open Web Interface】进入Web配置界面:
首次进入需在登录界面设置密码。

根据需要配置节点。

相关命令:

# 启动服务
/etc/init.d/v2raya start

# 停止服务
/etc/init.d/v2raya stop

# 重启服务
/etc/init.d/v2raya restart

# 检查运行状态
ps | grep v2raya

# 重置web界面密码
v2raya --reset-password

# 配置文件目录
/etc/v2raya/config.json

3、配置透明代理

使连接到路由器的设备都可通过配置的节点服务器上网,需要配置透明代理。
在Web配置界面,点击【设置】

推荐配置内容如下:
透明代理/系统代理:大陆白名单模式
透明代理/系统代理实现方式:tproxy
规则端口的分流模式:大陆白名单模式
防止DNS污染:仅防止DNS劫持
其他项可保持默认配置。

4、自定义配置文件(如内网穿透)

如需增加自定义配置,直接修改V2RayA的配置文件会被系统自动覆盖。可采用Python脚本进行配置:

安装运行环境:(如有Python环境可跳过)

opkg update
opkg install python3

新建脚本:

nano /etc/v2raya/core-hook.py

内容如下(自定义内网穿透配置):

#!/usr/bin/python
# -*- coding: utf-8 -*-
# 该脚本用于在 V2RayA 启动阶段pre-start自动修改配置文件 config.json
# 向其中添加反向代理 (reverse) 和路由 (routing rules) 配置

import argparse
from os import path
import json

def main():
    # 创建命令行参数解析器
    parser = argparse.ArgumentParser()
    # 添加参数 --v2raya-confdir用于指定 V2RayA 配置文件所在目录
    parser.add_argument('--v2raya-confdir', type=str, required=True)
    # 添加参数 --stage用于标识当前执行阶段 pre-startpost-start 
    parser.add_argument('--stage', type=str, required=True)
    args = parser.parse_args()

    # 仅在 pre-start 阶段执行修改操作其他阶段直接返回
    if args.stage != 'pre-start':
        return

    # 拼接配置文件路径例如:/etc/v2raya/config.json
    conf_path = path.join(args.v2raya_confdir, 'config.json')

    # 打开配置文件并读取内容为 JSON 对象
    with open(conf_path) as f:
        conf = json.loads(f.read())

    # 确保配置中包含 reverse 字段如果没有则创建一个空字典
    if 'reverse' not in conf:
        conf['reverse'] = {}
    # 确保配置中包含 outbounds 字段,,如果没有则创建一个空字典
    if 'outbounds' not in conf:
        conf['outbounds'] = []
    # 确保配置中包含 routing 字段以及 rules 列表
    if 'routing' not in conf:
        conf['routing'] = {'rules': []}

    # 定义要添加的反向代理配置
    reverse_bridges = {
        "bridges": [
            {
                "tag": "bridge-in",       # 反向代理入口标签
                "domain": "reverse.comp"  # 用于匹配的伪域名
            }
        ]
    }
    
    # 定义要添加的出站配置
    outbounds_bridges = {
        "tag": "bridge-out",
        "protocol": "vmess",
        "settings": {
            "vnext": [{
              "address": "输入代理节点地址或域名",
              "port": 443,
              "users":[{ "id": "输入UUID", "alterId": 0, "security": "auto"}]
            }]
        },
        "streamSettings": {
            "network": "ws",
            "security": "tls",
            "tlsSettings": {
                "serverName": "输入代理节点域名",
                "allowInsecure": false
            },
            "wsSettings": {
                "path": "/v2ray"
            }
        }
    }
    
    # 定义路由规则列表
    routing_rules = [
        {
            "type": "field",
            "inboundTag": ["bridge-in"],
            "domain": ["full:reverse.comp"],
            "outboundTag": "bridge-out"
        },
        {
            "type":"field",
            "inboundTag": ["bridge-in"],
            "outboundTag": "direct"
        },
        {
            "type":"field",
            "ip": ["192.168.1.0/24", "192.168.2.0/24", "192.168.31.0/24"],
            "outboundTag": "bridge-out"
        },
        {
            "type": "field",
            "domain": ["geosite:category-ads-all"],
            "outboundTag": "block"
        }
    ]

    # 将反向代理配置写入配置文件中覆盖原有 reverse 配置
    conf['reverse'] = reverse_bridges
    
    #  VMess 出站加入 outbounds 列表的最前面
    conf['outbounds'] = [outbounds_bridges] + conf['outbounds']
    
    # 将新的路由规则插入到现有 routing.rules 列表的最前面
    conf['routing']['rules'] = routing_rules + conf['routing']['rules']
            
    # 将修改后的配置重新写回文件并格式化为 2 空格缩进
    with open(conf_path, 'w') as f:
        f.write(json.dumps(conf, indent=2))

# 程序入口
if __name__ == '__main__':
    main()

给脚本添加执行权限:

chmod +x /etc/v2raya/core-hook.py

在V2rayA启动时运行脚本:
修改启动配置文件:

nano /etc/init.d/v2raya

在procd_set_param command “$PROG” 后面添加:–core-hook /etc/v2raya/core-hook.py

procd_set_param command "$PROG" --core-hook /etc/v2raya/core-hook.py

检查脚本执行情况:

# 停止v2raya
/etc/init.d/v2raya stop

# 测试脚本
/usr/bin/v2raya --core-hook /etc/v2raya/core-hook.py

# 检查配置文件是否更新
nano /etc/v2raya/config.json

# 开启v2raya
/etc/init.d/v2raya start

# 检查v2raya运行状态
ps | grep v2raya

参考官方文档:

https://v2raya.org/docs/advanced-application/custom-extra-config/

5、自定义配置文件(多个配置文件修改)

同时修改路由规则/etc/v2raya/v2raya.ntf,让对特定IP的访问走代理:(实际测试修改v2raya.ntf后路由规则并未同步修改,可参考“添加自定义分流规则”相关内容)

#!/usr/bin/python

import argparse
from os import path
import json
import re


def modify_config_json(v2raya_confdir):
    conf_path = path.join(v2raya_confdir, 'config.json')
    with open(conf_path) as f:
        conf = json.load(f)

    if 'reverse' not in conf:
        conf['reverse'] = {}
    if 'outbounds' not in conf:
        conf['outbounds'] = []
    if 'routing' not in conf:
        conf['routing'] = {'rules': []}

    reverse_bridges = {
        "bridges": [
            {"tag": "bridge-in", "domain": "reverse.comp"}
        ]
    }

    outbounds_bridges = {
        "tag": "bridge-out",
        "protocol": "vmess",
        "settings": {
            "vnext": [{
                "address": "输入代理节点地址或域名",
                "port": 443,
                "users": [{"id": "输入UUID", "alterId": 0, "security": "auto"}]
            }]
        },
        "streamSettings": {
            "network": "ws",
            "security": "tls",
            "tlsSettings": {"serverName": "输入代理节点域名", "allowInsecure": False},
            "wsSettings": {"path": "/v2ray"}
        }
    }

    routing_rules = [
        {"type": "field", "inboundTag": ["bridge-in"], "domain": ["full:reverse.comp"], "outboundTag": "bridge-out"},
        {"type": "field", "inboundTag": ["bridge-in"], "outboundTag": "direct"},
        {"type":"field", "ip": ["192.168.1.0/24", "192.168.2.0/24", "192.168.31.0/24"], "outboundTag": "bridge-out"},
        {"type": "field", "domain": ["geosite:category-ads-all"], "outboundTag": "block"}
    ]

    conf['reverse'] = reverse_bridges
    conf['outbounds'] = [outbounds_bridges] + conf['outbounds']
    conf['routing']['rules'] = routing_rules + conf['routing']['rules']

    with open(conf_path, 'w') as f:
        f.write(json.dumps(conf, indent=2))

    print(f"Modified {conf_path} successfully.")


def modify_v2raya_nft(v2raya_confdir):
    conf_path = path.join(v2raya_confdir, 'v2raya.nft')
    with open(conf_path) as f:
        conf = f.read()

    conf = re.sub(r"\s*192\.168\.0\.0/16,?", "", conf)

    if "192.168.80.0/16" not in conf:
        conf = re.sub(r"(\s*198\.51\.100\.0/24\s*)", "\n            192.168.80.0/16,\\1", conf)
    if "192.168.100.0/16" not in conf:
        conf = re.sub(r"(\s*198\.51\.100\.0/24\s*)", "\n            192.168.100.0/16,\\1", conf)
    if "192.168.101.0/16" not in conf:
        conf = re.sub(r"(\s*198\.51\.100\.0/24\s*)", "\n            192.168.101.0/16,\\1", conf)

    with open(conf_path, "w") as f:
        f.write(conf)

    print(f"Modified {conf_path} successfully.")
    

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--v2raya-confdir', type=str, required=True)
    parser.add_argument('--stage', type=str, required=True)
    args = parser.parse_args()

    if args.stage != 'pre-start':
        return
        
    modify_config_json(args.v2raya_confdir)
    modify_v2raya_nft(args.v2raya_confdir)


if __name__ == '__main__':
    main()

6、添加自定义分流规则

新建脚本:

nano /etc/v2raya/tproxy-hook.sh

内容如下:

#!/bin/sh


for i in "$@"; do
  case $i in
    --transparent-type=*)
      TYPE="${i#*=}"
      shift
      ;;
    --stage=*)
      STAGE="${i#*=}"
      shift
      ;;
    -*|--*)
      shift
      ;;
    *)
      ;;
  esac
done

echo "$(date) stage=$STAGE type=$TYPE"

case "$STAGE" in
post-start)
  set -ex
  
  for i in $(seq 1 5); do
    nft list set inet v2raya whitelist >/dev/null 2>&1 && break
    sleep 1
  done

  nft delete element inet v2raya whitelist { 192.168.0.0/16 } 2>/dev/null || true
  nft add element inet v2raya whitelist { 192.168.101.0/24 } 2>/dev/null || true
  
  echo "$(date) updated whitelist"
  
  ;;
esac

exit 0

上述脚本将whitelist中的192.168.0.0/16删除,改为192.168.101.0/24,可实现如在公司内网对家庭内网的访问。

为脚本添加执行权限:

chmod +x /etc/v2raya/tproxy-hook.sh

在V2rayA启动时运行脚本:
修改启动配置文件:

nano /etc/init.d/v2raya

在procd_set_param command “$PROG” 后面添加:–transparent-hook /etc/v2raya/tproxy-hook.sh

procd_set_param command "$PROG" --core-hook /etc/v2raya/core-hook.py --transparent-hook /etc/v2raya/tproxy-hook.sh

检查脚本执行情况:

# 停止v2raya
/etc/init.d/v2raya stop

# 测试脚本
/usr/bin/v2raya --transparent-hook /etc/v2raya/tproxy-hook.sh

# 检查nftables是否更新
nft list ruleset

# 开启v2raya
/etc/init.d/v2raya start

# 检查v2raya运行状态
ps | grep v2raya
# 保存现有规则到临时文件
nft list ruleset > /tmp/v2raya.rules

# 编辑或查看规则文件
nano /tmp/v2raya.rules

# 重新加载
nft -f /tmp/v2raya.rules

# 重启 V2RayA
/etc/init.d/v2raya restart

参考官方文档:

https://v2raya.org/docs/advanced-application/intranet-direct/

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部