Logo
热心市民王先生

实施指南

技术研究 人工智能 GitHub

物品 规格要求 数量 备注 ------ ---------- ------ ------ NanoPi R4S 4GB 版本推荐 1 1GB 版本也可用 microSD 卡 32GB+ Class 10 1 用于刷入系统 读卡器 USB 3.0 1 刷机使用 网线 Cat 5e/6 2+ 连接路由器和设备 电源适配器 5V/3A Type-C 1 确保供电...

本章节提供完整的实施步骤,包括固件刷入、系统配置、软件安装以及故障回退配置。

环境准备

1.1 硬件清单

物品规格要求数量备注
NanoPi R4S4GB 版本推荐11GB 版本也可用
microSD 卡32GB+ Class 101用于刷入系统
读卡器USB 3.01刷机使用
网线Cat 5e/62+连接路由器和设备
电源适配器5V/3A Type-C1确保供电充足

1.2 软件准备

需要下载的文件

  1. OpenWrt 固件

  2. 刷机工具

  3. SSH 客户端

    • Windows: PuTTY 或 Windows Terminal
    • macOS/Linux: 自带 Terminal

1.3 刷入固件

步骤 1:下载并解压固件

# Linux/macOS
gunzip openwrt-23.05.3-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-combined.img.gz

# Windows 使用 7-Zip 解压 .gz 文件

步骤 2:刷入 microSD 卡

# Linux/macOS (将 sdX 替换为实际设备名,注意数据会丢失!)
sudo dd if=openwrt.img of=/dev/sdX bs=4M status=progress
sync

# Windows 使用 Rufus:
# 1. 插入 microSD 卡
# 2. 打开 Rufus
# 3. 选择设备和固件 img 文件
# 4. 点击开始

步骤 3:启动 R4S

  1. 插入刷好固件的 microSD 卡
  2. 连接网线到 R4S 的 LAN 口(靠近 HDMI 的网口)
  3. 连接电源,等待启动(约 1-2 分钟)
  4. R4S 默认 IP:192.168.1.1

OpenWrt 安装配置

2.1 初始配置

步骤 1:连接并登录

# SSH 登录(默认无密码)
ssh root@192.168.1.1

# 设置 root 密码
passwd

步骤 2:网络基础配置

将 R4S 配置为旁路由模式:

# 设置 LAN 口静态 IP(旁路由 IP)
uci set network.lan.ipaddr='192.168.1.2'
uci set network.lan.netmask='255.255.255.0'

# 设置网关指向主路由
uci set network.lan.gateway='192.168.1.1'

# 设置 DNS
uci set network.lan.dns='192.168.1.1'

# 提交配置
uci commit network

# 重启网络
/etc/init.d/network restart

注意:配置后 R4S 的 IP 变为 192.168.1.2,需要重新 SSH 连接。

2.2 软件源配置

步骤 1:更新软件源

# 连接互联网(此时 R4S 可通过主路由上网)
ping -c 3 223.5.5.5

# 更新软件列表
opkg update

步骤 2:安装必要工具

# 基础工具
opkg install vim curl wget htop iperf3

# 网络工具
opkg install iptables-mod-tproxy iptables-mod-extra
opkg install ipset dnsmasq-full

# 替换 dnsmasq 为完整版
opkg remove dnsmasq
opkg install dnsmasq-full

2.3 防火墙基础配置

# 允许 LAN 口转发(旁路由模式必需)
uci set firewall.@zone[0].forward='ACCEPT'
uci commit firewall
/etc/init.d/firewall restart

V2Ray 安装与配置

3.1 安装 V2Ray

方式 1:使用官方包(推荐)

# 安装 V2Ray
opkg install v2ray-core

# 或安装 Xray(性能更好)
opkg install xray-core

方式 2:手动安装最新版

# 下载最新版(ARM64)
cd /tmp
wget https://github.com/v2fly/v2ray-core/releases/latest/download/v2ray-linux-arm64-v8a.zip
unzip v2ray-linux-arm64-v8a.zip -d /usr/bin/
chmod +x /usr/bin/v2ray

3.2 V2Ray 配置文件

创建配置文件 /etc/v2ray/config.json

{
  "log": {
    "loglevel": "warning",
    "access": "/var/log/v2ray-access.log",
    "error": "/var/log/v2ray-error.log"
  },
  "inbounds": [
    {
      "tag": "transparent",
      "port": 12345,
      "protocol": "dokodemo-door",
      "settings": {
        "network": "tcp,udp",
        "followRedirect": true
      },
      "streamSettings": {
        "sockopt": {
          "tproxy": "tproxy"
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "your.server.address",
            "port": 443,
            "users": [
              {
                "id": "your-uuid-here",
                "security": "auto",
                "alterId": 0
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls"
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "block",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private", "geoip:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "udp",
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:geolocation-!cn"],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "ip": ["geoip:!cn"],
        "outboundTag": "proxy"
      }
    ]
  }
}

重要:将 your.server.addressyour-uuid-here 替换为你的实际服务器配置。

3.3 启动 V2Ray

# 创建启动脚本 /etc/init.d/v2ray

cat > /etc/init.d/v2ray << 'EOF'
#!/bin/sh /etc/rc.common

START=99
STOP=10

USE_PROCD=1

start_service() {
    procd_open_instance
    procd_set_param command /usr/bin/v2ray -config /etc/v2ray/config.json
    procd_set_param respawn
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}
EOF

chmod +x /etc/init.d/v2ray

# 启动并设置开机自启
/etc/init.d/v2ray enable
/etc/init.d/v2ray start

# 检查状态
/etc/init.d/v2ray status

DHCP 服务器设置

4.1 配置 DHCP

# 启用 DHCP 服务器
uci set dhcp.lan.ignore='0'

# 设置 DHCP 范围
uci set dhcp.lan.start='100'
uci set dhcp.lan.limit='150'
uci set dhcp.lan.leasetime='12h'

# 关键:设置 DHCP Option 3,告知客户端使用 R4S 作为网关
uci add_list dhcp.lan.dhcp_option='3,192.168.1.2'

# 可选:设置 DNS 为 R4S
uci add_list dhcp.lan.dhcp_option='6,192.168.1.2'

uci commit dhcp
/etc/init.d/dnsmasq restart

4.2 关闭主路由 DHCP(重要)

为避免 DHCP 冲突,需要关闭主路由的 DHCP 服务:

  1. 登录主路由管理界面(通常是 192.168.1.1
  2. 找到 DHCP 服务器设置
  3. 关闭 DHCP 服务器
  4. 保存并重启主路由

注意:如果无法关闭主路由 DHCP,可以将 R4S DHCP 租期设短(如 2 分钟),作为辅助 DHCP。

透明代理配置

5.1 创建 iptables 规则脚本

创建 /etc/init.d/v2ray-setup-iptables

cat > /etc/init.d/v2ray-setup-iptables << 'EOF'
#!/bin/sh /etc/rc.common

START=95
STOP=5

start() {
    # 创建新链
    iptables -t mangle -N V2RAY 2>/dev/null
    iptables -t mangle -F V2RAY 2>/dev/null
    
    # 绕过本地地址和私有网络
    iptables -t mangle -A V2RAY -d 0.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY -d 10.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY -d 127.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY -d 169.254.0.0/16 -j RETURN
    iptables -t mangle -A V2RAY -d 172.16.0.0/12 -j RETURN
    iptables -t mangle -A V2RAY -d 192.168.0.0/16 -j RETURN
    iptables -t mangle -A V2RAY -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A V2RAY -d 240.0.0.0/4 -j RETURN
    
    # 绕过已建立的连接
    iptables -t mangle -A V2RAY -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
    
    # 绕过 V2Ray 自身流量(避免环路)
    iptables -t mangle -A V2RAY -m mark --mark 0xff -j RETURN
    
    # 劫持 TCP 流量到 TPROXY
    iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 0x1/0x1
    
    # 劫持 UDP 流量到 TPROXY(可选)
    # iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x1/0x1
    
    # 应用规则到 PREROUTING
    iptables -t mangle -A PREROUTING -j V2RAY
    
    # 为本地流量添加标记(OUTPUT 链)
    iptables -t mangle -N V2RAY_MASK 2>/dev/null
    iptables -t mangle -F V2RAY_MASK 2>/dev/null
    
    iptables -t mangle -A V2RAY_MASK -d 0.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 10.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 127.0.0.0/8 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 169.254.0.0/16 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 172.16.0.0/12 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 240.0.0.0/4 -j RETURN
    iptables -t mangle -A V2RAY_MASK -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
    iptables -t mangle -A V2RAY_MASK -m mark --mark 0xff -j RETURN
    iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 0x1
    # iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 0x1
    
    iptables -t mangle -A OUTPUT -j V2RAY_MASK
    
    # 配置路由表
    ip rule add fwmark 0x1 table 100 2>/dev/null
    ip route add local 0.0.0.0/0 dev lo table 100 2>/dev/null
    
    echo "V2Ray iptables rules applied"
}

stop() {
    iptables -t mangle -D PREROUTING -j V2RAY 2>/dev/null
    iptables -t mangle -D OUTPUT -j V2RAY_MASK 2>/dev/null
    iptables -t mangle -F V2RAY 2>/dev/null
    iptables -t mangle -F V2RAY_MASK 2>/dev/null
    iptables -t mangle -X V2RAY 2>/dev/null
    iptables -t mangle -X V2RAY_MASK 2>/dev/null
    
    ip rule del fwmark 0x1 table 100 2>/dev/null
    
    echo "V2Ray iptables rules cleared"
}

restart() {
    stop
    start
}
EOF

chmod +x /etc/init.d/v2ray-setup-iptables

5.2 启动透明代理

# 启动 iptables 规则
/etc/init.d/v2ray-setup-iptables start

# 设置开机自启
/etc/init.d/v2ray-setup-iptables enable

5.3 下载 GeoIP/GeoSite 数据库

# 创建数据目录
mkdir -p /usr/share/v2ray

# 下载 GeoIP 数据库
curl -L -o /usr/share/v2ray/geoip.dat \
  "https://github.com/v2fly/geoip/releases/latest/download/geoip.dat"

# 下载 GeoSite 数据库
curl -L -o /usr/share/v2ray/geosite.dat \
  "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat"

# 重启 V2Ray 加载数据库
/etc/init.d/v2ray restart

故障回退配置

6.1 健康检查脚本

创建 /usr/bin/v2ray-health-check.sh

cat > /usr/bin/v2ray-health-check.sh << 'EOF'
#!/bin/sh

# 配置
CHECK_INTERVAL=30
FAIL_THRESHOLD=3
LOG_FILE="/var/log/v2ray-health.log"
STATE_FILE="/var/run/v2ray-health.state"

# 获取当前失败计数
FAIL_COUNT=$(cat "$STATE_FILE" 2>/dev/null || echo 0)

# 检查 1:V2Ray 进程是否存在
V2RAY_PID=$(pgrep -f "v2ray.*config")
if [ -z "$V2RAY_PID" ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') ERROR: V2Ray process not found" >> "$LOG_FILE"
    FAIL_COUNT=$((FAIL_COUNT + 1))
else
    # 进程存在,检查是否响应
    if ! kill -0 "$V2RAY_PID" 2>/dev/null; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') ERROR: V2Ray process not responding" >> "$LOG_FILE"
        FAIL_COUNT=$((FAIL_COUNT + 1))
    else
        # 进程正常,重置失败计数
        FAIL_COUNT=0
    fi
fi

# 检查失败次数是否超过阈值
if [ "$FAIL_COUNT" -ge "$FAIL_THRESHOLD" ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') WARN: Fail threshold reached, enabling fallback" >> "$LOG_FILE"
    /usr/bin/v2ray-fallback.sh enable
    echo 0 > "$STATE_FILE"
else
    # 确保代理模式启用
    /usr/bin/v2ray-fallback.sh disable
    echo "$FAIL_COUNT" > "$STATE_FILE"
fi
EOF

chmod +x /usr/bin/v2ray-health-check.sh

6.2 回退控制脚本

创建 /usr/bin/v2ray-fallback.sh

cat > /usr/bin/v2ray-fallback.sh << 'EOF'
#!/bin/sh

ACTION=$1
LOCK_FILE="/var/run/v2ray-fallback.lock"
STATE_FILE="/var/run/v2ray-fallback.state"
LOG_FILE="/var/log/v2ray-health.log"

# 防止并发执行
exec 200>"$LOCK_FILE"
flock -n 200 || exit 0

current_state=$(cat "$STATE_FILE" 2>/dev/null || echo "disabled")

enable_fallback() {
    if [ "$current_state" != "enabled" ]; then
        # 清除代理规则
        /etc/init.d/v2ray-setup-iptables stop 2>/dev/null
        echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: Fallback mode enabled" >> "$LOG_FILE"
        echo "enabled" > "$STATE_FILE"
    fi
}

disable_fallback() {
    if [ "$current_state" != "disabled" ]; then
        # 恢复代理规则
        /etc/init.d/v2ray-setup-iptables start 2>/dev/null
        echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: Proxy mode restored" >> "$LOG_FILE"
        echo "disabled" > "$STATE_FILE"
    fi
}

case $ACTION in
    enable)
        enable_fallback
        ;;
    disable)
        disable_fallback
        ;;
    status)
        echo "Current state: $current_state"
        ;;
    *)
        echo "Usage: $0 {enable|disable|status}"
        exit 1
        ;;
esac
EOF

chmod +x /usr/bin/v2ray-fallback.sh

6.3 配置定时任务

# 编辑 crontab
cat >> /etc/crontabs/root << 'EOF'

# V2Ray 健康检查(每 30 秒)
*/1 * * * * /usr/bin/v2ray-health-check.sh
*/1 * * * * sleep 30 && /usr/bin/v2ray-health-check.sh
EOF

# 启动 cron
/etc/init.d/cron enable
/etc/init.d/cron start

测试验证步骤

7.1 基础功能测试

测试 1:网络连通性

# 在客户端执行
ping 192.168.1.1    # 主路由
ping 192.168.1.2    # R4S
ping 223.5.5.5      # 公共 DNS
ping baidu.com      # 国内网站

测试 2:DHCP 分配

# 查看客户端获取的 IP 和网关
ipconfig  # Windows
ip addr   # Linux

# 确认网关是 192.168.1.2

测试 3:透明代理生效

# 访问国外网站检查 IP
curl -s ipinfo.io

# 应显示代理服务器所在国家的 IP

7.2 故障回退测试

测试 1:V2Ray 进程停止

# 在 R4S 上执行
/etc/init.d/v2ray stop

# 在客户端测试
ping baidu.com        # 应该正常
ping google.com       # 可能超时(正常)
curl -s ipinfo.io     # 应显示真实 IP

测试 2:恢复 V2Ray

# 在 R4S 上执行
/etc/init.d/v2ray start

# 等待 30 秒后测试
curl -s ipinfo.io     # 应显示代理 IP

测试 3:查看日志

# 在 R4S 上查看回退日志
tail -f /var/log/v2ray-health.log

# 查看 iptables 规则状态
iptables -t mangle -L -n -v

7.3 性能测试

# 内网带宽测试(R4S 到客户端)
iperf3 -s  # 在 R4S 运行
iperf3 -c 192.168.1.2  # 在客户端运行

# 外网速度测试
speedtest-cli

7.4 验证清单

  • R4S 正常启动,可 SSH 登录
  • 客户端通过 DHCP 获取 IP 和网关
  • 网关指向 192.168.1.2
  • 国内网站访问正常
  • 国外网站通过代理访问
  • V2Ray 停止后,国内网站仍可访问
  • V2Ray 恢复后,代理自动生效
  • 带宽达到预期(500Mbps+)

故障排查

常见问题

问题 1:客户端无法获取 IP

# 检查 DHCP 服务
/etc/init.d/dnsmasq status
logread | grep dnsmasq

# 检查防火墙
iptables -L -n | grep 67

问题 2:透明代理不生效

# 检查 V2Ray 运行状态
/etc/init.d/v2ray status
logread | grep v2ray

# 检查 iptables 规则
iptables -t mangle -L V2RAY -n -v

# 检查路由表
ip rule show
ip route show table 100

问题 3:国内网站走代理

# 检查 GeoIP 数据库是否存在
ls -la /usr/share/v2ray/geoip.dat

# 检查 V2Ray 配置中的路由规则
cat /etc/v2ray/config.json | grep -A5 geoip

日志查看

# 系统日志
logread -f

# V2Ray 日志
tail -f /var/log/v2ray-error.log
tail -f /var/log/v2ray-access.log

# 回退日志
tail -f /var/log/v2ray-health.log

参考资料