前置代理机场节点的路由器及VPS防火墙处理

瓦工BIGGERBOX-20-1024

自动将机场所有落地IP及本地公网IP发送至VPS服务器,获取机场节点延迟,配置VPS防火墙减少GFW及一些有心人士探测,VPS代理服务器更安全。

在当今互联网环境中,安全性和隐私保护成为了我们越来越关注的问题。尤其是我们需要突破网络封锁、使用国际互联网服务时,机场免于搭建、地区多、上手即使用,已经成了大部分有科学需求的用户首选。使用机场也有一些限制,比如机场可能存在审计、记录日志、IP被滥用等行为,易使得我们的隐私泄露。要想完全控制自己上网的流量,需要我们搭建自己的代理服务。

由于墙的强大,自建代理服务器容易受到封锁处理,往往代理运行一番后就被墙发现,从而封锁服务器IP或端口。遇到这种只能更换IP处理,每年也需花费一定的费用。如果使用机场,那么IP被封锁的事情你就无需考虑了,有机场主处理。比如我前期测试了一下Shadowsocks ,几分钟后我的服务器IP便不再能PING通,好在我这是准备做前置代理的,所以被GFW封锁也无所谓,另外GFW可能会主动探测你的这台服务器。VPS服务器暴露在互联网上,这使得它们容易成为网络攻击的目标,如DDoS攻击、暴力破解等。

前置代理机场节点,指的是通过机场的节点连接自有VPS服务器。自有VPS服务器将网络流量从机场节点中转,从而突破国内网络限制,访问国际互联网服务。通过使用这种方式,用户可以访问被屏蔽的外部网站或服务,同时增强自己的匿名性和安全性。由于加密的存在,机场也无法知道你访问了哪些网站服务等。考虑到隐私、安全、服务稳定性,前置代理机场节点成为了一种常见的解决方案。

我们可以通过配置防火墙,有效过滤掉来自不可信IP的访问请求,减少潜在的安全威胁。防火墙能够阻止未经授权的流量进入或离开网络,确保只有符合条件的数据能够通过代理节点,我们可以通过NFTSET解决。现在机场都是中转机场,用户访问的是国内的机场代理服务器,机场国内服务器通过隧道等协议穿墙到国外的落地服务器,有的机场还有IEPL等专线过墙,从而保证了稳定性及低延时。但也给我们前置代理带来了不便。

前置代理机场节点的路由器及VPS防火墙处理

由于一般机场都禁止一号多地登录,也不支持从外国使用机场服务,为了杜绝被机场禁用,这里通过2个脚本路由器和VPS配合,自动获取机场所有节点的落地IP上传到自有的VPS服务器,VPS服务器自动执行脚本完成防火墙设置。路由器是OPENWRT软路由,VPS服务器是bebian12系统。2台设备均安装有sing-box。软路由上使用的是Homeproxy软件管理sing-box,服务器上代理服务是sing-box是官方版本一键安装的,本站均有介绍。

这2个脚本在我的机场及服务器均运行通过。自用机场瓦工GIA服务器 见链接。该机场是中转机场,只有shadowsocks和trojan两种协议,因此脚本里只能处理这2种协议。路由器上安装了Homeproxy代理软件。一般来说大部分机场节点的落地IP是不怎么变动的,脚本每天检测1次机场落地IP情况;碰到重大节日,机场落地IP变化频繁,可修改计划任务增加检测次数。30个节点,检测一次需耗时3min左右。

软路由获取机场落地IP脚本

自动通过sing-box来获取中转机场落地IP。通过socks5也不影响路由器HOMEPROXY的代理服务。脚本主要做了这几个任务:

#!/bin/sh

# 订阅地址,改为自己的
SUBSCRIPTION_URL="https://..."

# 远程主机,改为自己的vps服务器及ssh端口号
REMOTEHOST="1.2.3.4"
REMOTEPORT="22"

# 公共 IP 服务,自己到ipinfo.io申请
IPINFOTOKEN="12345678"                      # IP 服务的 API Token
IP_SERVICE="https://ipinfo.io/ip?token=$IPINFOTOKEN"  # 获取 IP 的服务 URL

# 临时文件和日志设置,一下无需修改
SCRIPT_PATH=$(readlink -f "$0")
BASE_DIR="/usr/share/airport"
LOG_FILE="/var/log/singbox_blockcn.log"
CONFIG_DIR=/tmp/singbox # 用于存储临时配置文件的目录
TEMP_FILE=$(mktemp)       # 临时文件路径
DECODED_FILE=$(mktemp)    # 用于存储解码后的内容的临时文件
LANDING_FILE="$BASE_DIR/landing_ip.txt"  # 存储代理落地 IP 的文件

# 创建日志和数据目录
mkdir -p "$BASE_DIR"
mkdir -p "$CONFIG_DIR"
mkdir -p "$(dirname "$LOG_FILE")"

# 清理临时文件和进程
trap "rm -f $TEMP_FILE $DECODED_FILE; rm -rf $CONFIG_DIR" EXIT
rm -rf $LANDING_FILE

# 检查依赖项
for cmd in curl base64 sing-box; do
  if ! command -v $cmd >/dev/null 2>&1; then
    echo "需要安装 $cmd" | tee -a "$LOG_FILE" >&2
    exit 1
  fi
done

# 检查订阅地址
if [[ -z $SUBSCRIPTION_URL ]]; then
  echo "订阅地址为空!请检查配置。" | tee -a "$LOG_FILE" >&2
  exit 1
fi

# 下载订阅信息
if ! curl -s "$SUBSCRIPTION_URL" -o "$TEMP_FILE"; then
  echo "订阅地址下载失败!" | tee -a "$LOG_FILE" >&2
  exit 1
fi

# 检查文件是否为空
if [[ ! -s $TEMP_FILE ]]; then
  echo "订阅文件内容为空!" | tee -a "$LOG_FILE" >&2
  exit 1
fi

# Base64 解码
if ! base64 -d "$TEMP_FILE" > "$DECODED_FILE" 2>> "$LOG_FILE"; then
  echo "Base64 解码失败!" | tee -a "$LOG_FILE" >&2
  exit 1
fi

# 解析解码后的内容并生成配置
cat "$DECODED_FILE" | while read -r LINE; do
  if [[ $LINE == ss://* || $LINE == trojan://* ]]; then
    # 获取类型
    TYPE=$(echo $LINE | cut -d':' -f1)

    # 提取 Base64 部分
    BASE64_PART=$(echo $LINE | sed 's/^ss:\/\///' | sed 's/^trojan:\/\///' | cut -d'#' -f1)

    # Base64 解码
    DECODED=$(echo $BASE64_PART | base64 -d 2>/dev/null)
    if [[ -z $DECODED ]]; then
      echo "Base64 解码失败: $LINE" | tee -a $LOG_FILE >&2
      continue
    fi

    # 提取加密协议、密码
    PROTOCOL=$(echo $DECODED | cut -d':' -f1)
    
    # 提取加密密码
    if [[ $TYPE == "ss" ]]; then
      PASSWORD=$(echo $DECODED | cut -d':' -f2 | cut -d'@' -f1)
    elif [[ $TYPE == "trojan" ]]; then
      PASSWORD=$(echo "$LINE" | sed -n 's/^trojan:\/\/\([^@]*\)@.*/\1/p')
    fi

    # 提取服务器和端口
    SERVER=$(echo $LINE | sed 's/^ss:\/\/.*@//g' | sed 's/^trojan:\/\/.*@//g' | cut -d':' -f1)
    PORT=$(echo "$LINE" | sed -E 's/.*@[^:]+:([0-9]+).*/\1/')

    # 提取备注并解码为中文
    REMARK=$(echo "$LINE" | awk -F'#' '{print $2}' | sed 's/+/ /g; s/%/\\x/g' | xargs -0 printf "%b" | tr -d '\r')

    # 设置机场节点配置文件	
    CONFIG_FILE_NAME="$CONFIG_DIR/$(echo -n "$REMARK" | sha256sum | cut -c 1-8).json"

    # 根据节点类型生成配置文件
    if [[ $TYPE == "ss" ]]; then
      cat <<-EOF > "$CONFIG_FILE_NAME"
{
  "log": {
    "level": "error"
  },
  "outbounds": [
    {
      "type": "shadowsocks",
      "tag": "ss-out",
      "server": "$SERVER",
      "server_port": $PORT,
      "password": "$PASSWORD",
      "method": "$PROTOCOL"
    }
  ],
  "inbounds": [
    {
      "type": "socks",
      "tag": "socks-in",
      "listen": "::",
      "listen_port": 2025
    }
  ]
}
EOF
    elif [[ $TYPE == "trojan" ]]; then
      cat <<-EOF > "$CONFIG_FILE_NAME"
{
  "log": {
    "level": "error"
  },
  "outbounds": [
    {
      "type": "trojan",
      "tag": "trojan-out",
      "server": "$SERVER",
      "server_port": $PORT,
      "password": "$PASSWORD",
      "tls": {
        "enabled": true,
        "server_name": "$(echo "$LINE" | sed -n 's/^.*sni=\([^&#]\+\).*/\1/p')",
        "insecure": $(echo $LINE | grep -o 'allowInsecure=\([0-9]\+\)' | cut -d'(' -f2 | awk '{print ($1 == 1) ? "true" : "false"}' || echo "false")
      }
    }
  ],
  "inbounds": [
    {
      "type": "socks",
      "tag": "socks-in",
      "listen": "::",
      "listen_port": 2025
    }
  ]
}
EOF
    fi
    
    # 启动 sing-box 并测试代理
    sing-box run -c "$CONFIG_FILE_NAME" &
    SING_BOX_PID=$!

    # 等待代理启动
    sleep 5
    
    # 分开检测
    # LANDING_IP=$(curl -s --socks5 127.0.0.1:2025 $IP_SERVICE)
    # LATENCY=$(curl -s -o /dev/null -w "%{time_total}\n" --socks5 127.0.0.1:2025 https://wwww.google.com)

    # 获取落地 IP及延时
    result=$(curl -s --socks5 127.0.0.1:2025 -w " TIME: %{time_total}" $IP_SERVICE)
    
    # 提取访问者 IP 和延时
    LANDING_IP=$(echo "$result" | awk '{print $1}') # 提取第一部分(IP)
    LATENCY=$(echo "$result" | awk -F'TIME: ' '{print $2}') # 提取 "TIME:" 后的延时值
    
    if echo "$LANDING_IP" | grep -Eq '^([0-9]{1,3}\.){3}[0-9]{1,3}$|^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'; then
      echo "# ${REMARK},HTTPS真延时为${LATENCY}s" >> "$LANDING_FILE"
      echo "$LANDING_IP" >> "$LANDING_FILE"
      echo "${REMARK}的落地IP是${LANDING_IP},HTTPS真延时为${LATENCY}s"
    else
      echo "无法通过代理获取落地 IP: $SERVER" | tee -a $LOG_FILE >&2
    fi

    # 停止 sing-box
    kill $SING_BOX_PID
    wait $SING_BOX_PID 2>/dev/null
  fi

done

# 获取本机IP,注意ipip.net不能被代理,可直接在浏览器里打开查看
LOCALIP=$(curl -s http://myip.ipip.net/ | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
echo "# 国内本地公网IPv4,无需获取延时" >> "$LANDING_FILE"
echo "$LOCALIP" >> "$LANDING_FILE"

# 设置定时任务
CRON_JOB="48 7 * * * /bin/sh $SCRIPT_PATH"
if ! crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH"; then
  (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
fi

# openwrt的密钥和openssh的不兼容,需要在服务器上安装apt install dropbear ,
# 然后dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key /etc/dropbear_rsa_host_key转换,
# 转换后文件放入openwrt中,密钥需要设为600权限

if ! grep -q "$REMOTEHOST" "/root/.ssh/known_hosts"; then
    # 如果没有找到该主机的指纹,输出提示信息
    echo "第一次运行需要手工确认信任主机"
fi

scp -q -p -i /etc/ssl/private/vps_dropbear_private_key -P $REMOTEPORT $LANDING_FILE root@$REMOTEHOST:/usr/local && echo "文件已上传" || echo "文件上传失败"

echo "脚本执行成功" | tee -a $LOG_FILE >&2

注意点:一些说明在脚本中已经说明,请仔细查看。上传至服务器使用的是scp协议,ssh登录是使用的证书登录,本脚本也是通过证书登录的方法上传至服务器。服务器证书是openssh生成的,OPENWRT的scp命令只认可dropbear生成的公钥,所以需要转换服务器证书为dropbear格式的。需要在服务器上安装dropbear后转换openssh的证书。需要密码登录自行查找相关命令。

# 在vps服务器上执行
apt install dropbear

dropbearconvert openssh dropbear /path/to/ssh_host_rsa_key /path/to/dropbear_rsa_host_key

转换路径需自己确定好。

前置代理机场节点的路由器及VPS防火墙处理

Homeproxy日志显示

VPS服务器设置防火墙脚本

该脚本主要处理了:

#!/bin/bash

# 设置 PATH 环境变量
export PATH=$PATH:/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin

# 变量定义
SCRIPT_PATH=$(realpath "$0")
URLCN="https://fastly.jsdelivr.net/gh/gaoyifan/china-operator-ip@ip-lists/china.txt"
URLCN6="https://raw.githubusercontent.com/1715173329/IPCIDR-CHINA/refs/heads/master/ipv6.txt"

# 自定义singbox服务端端口,根据自己的修改
SS_PORT=1234                 #自定义ss端口
SOCKS_PORT=4321             #自定义socks端口
REALITY_PORT=443             #自定义reality端口

# 以下无需修改
ALLOWED_IPS="allowed_ips"
BLOCKCN_IPS="blockcn_ips"
BLOCKCN6_IPS="blockcn6_ips"
NFTTABLES_NAME="proxy"
BASE_DIR="/usr/share/singbox"
AIRPORTLANDING_IPS="/usr/local/landing_ip.txt"

# 检查是否安装了相关软件
for cmd in nft curl base64 sing-box; do
  if ! command -v $cmd >/dev/null 2>&1; then
    echo "需要安装 $cmd"
    exit 1
  fi
done

# 检查是否存在相关文件
function existfile {
  if [ ! -f $1 ]; then
    echo "$1 文件不存在,请检查!"
    exit 1
  fi
}

existfile "/etc/nftables.conf"
existfile "$AIRPORTLANDING_IPS"

# 创建nft规则保存文件夹
mkdir -p "$BASE_DIR" 

function echolog() {
  local d="$(date "+%Y-%m-%d %H:%M:%S")"
  echo -e "$d $*" >> ${BASE_DIR}/frontpoxy_airport.log
}

function downloadfile {
  echo "正在下载中国IP $1"
  if ! curl -s "$1" -o $2; then
    echo "下载中国IP地址列表失败,继续使用现有的IP地址列表..."
    # 如果没有旧文件,退出
    if [ ! -f $2 ]; then
      echo "未找到中国现有的IP地址列表,无法继续。"
      echolog "IP下载失败"
      exit 1
    fi
  else
    echo "中国IP地址列表已成功下载并保存至$2。"
  fi
}

downloadfile "$URLCN" "/tmp/cn_ips.txt"
downloadfile "$URLCN6" "/tmp/cn6_ips.txt"

# 设置 IP 集合
function setipset {
  IPSET_NAME=$1    
  IPSET_TXTDIR=$2   
  
  # 判断 $IPSET_NAME 是否包含字符 "6"
  if echo "$IPSET_NAME" | grep -q "6"; then
    ADDRESS_TYPE="ipv6_addr"
  else
    ADDRESS_TYPE="ipv4_addr"
  fi

  # 检查集合是否存在
  if nft list set inet $NFTTABLES_NAME "$IPSET_NAME" >/dev/null 2>&1; then
    nft flush set inet $NFTTABLES_NAME "$IPSET_NAME"
  else
    nft add set inet $NFTTABLES_NAME "$IPSET_NAME" { type $ADDRESS_TYPE\; flags interval\; auto-merge\; }
  fi

  # 删除注释含、空行、制表符、最后的空格
  clean_output=$(sed 's/#.*$//; /^$/d; s/[ \t]*$//' "$IPSET_TXTDIR")
  # 处理后的结果
  elements=$(echo "$clean_output" | tr '\n' ',' | sed 's/,$//')
  # 添加元素到集合,换行符变为逗号,且删除最后的逗号
  if [[ -z $elements ]]; then
    echo "IP 地址列表为空,无法添加到集合中。" | tee -a "$LOG_FILE" >&2
    exit 1
  fi

  nft add element inet $NFTTABLES_NAME "$IPSET_NAME" { $elements }
  
}

# 加入自定义nftables表
if ! nft list tables | grep -q "^table .* $NFTTABLES_NAME$"; then
  echo "建立新NFT防火墙 ${NFTTABLES_NAME}表"

  nft flush table inet $NFTTABLES_NAME 2>/dev/null 
  nft add table inet $NFTTABLES_NAME

  nft add chain inet $NFTTABLES_NAME singboxinput { type filter hook input priority -199 \; policy accept \; }
  nft add chain inet $NFTTABLES_NAME singboxforward { type filter hook forward priority -199 \; policy accept \; } 
  nft add chain inet $NFTTABLES_NAME singboxoutput { type filter hook output priority -199 \; policy accept \; }
  
  setipset "$ALLOWED_IPS" "$AIRPORTLANDING_IPS"
  setipset "$BLOCKCN_IPS" "/tmp/cn_ips.txt"
  setipset "$BLOCKCN6_IPS" "/tmp/cn6_ips.txt"
   
  nft add chain inet $NFTTABLES_NAME singbox_proxy_allowed
  nft add rule inet $NFTTABLES_NAME singbox_proxy_allowed ip saddr @$ALLOWED_IPS meta l4proto tcp counter accept
  nft add rule inet $NFTTABLES_NAME singbox_proxy_allowed ip saddr @$ALLOWED_IPS meta l4proto udp counter accept
  nft add rule inet $NFTTABLES_NAME singbox_proxy_allowed meta l4proto tcp counter ct state new drop
  nft add rule inet $NFTTABLES_NAME singbox_proxy_allowed meta l4proto udp counter ct state new drop
  
  nft add rule inet $NFTTABLES_NAME singboxinput meta l4proto { tcp, udp } th dport $SS_PORT goto singbox_proxy_allowed
  nft add rule inet $NFTTABLES_NAME singboxinput meta l4proto { tcp, udp } th dport $SOCKS_PORT goto singbox_proxy_allowed
  nft add rule inet $NFTTABLES_NAME singboxinput meta l4proto { tcp, udp } th dport $REALITY_PORT goto singbox_proxy_allowed
  
  nft add rule inet $NFTTABLES_NAME singboxoutput ip daddr @$BLOCKCN_IPS meta mark 100 counter drop comment \"singbox中标记100目标中国拒绝\"
  nft add rule inet $NFTTABLES_NAME singboxoutput ip6 daddr @$BLOCKCN6_IPS meta mark 100 counter drop comment \"singbox中标记100目标中国拒绝\"  

  echo "include \"${BASE_DIR}/singbox.nft\"" >> "/etc/nftables.conf"
  
else
  echo "NFTABLES ${NFTTABLES_NAME}表已存在" 
fi

# 刷新集合
setipset "$ALLOWED_IPS" "$AIRPORTLANDING_IPS"
setipset "$BLOCKCN_IPS" "/tmp/cn_ips.txt"
setipset "$BLOCKCN6_IPS" "/tmp/cn6_ips.txt"
echo "NFT集合机场IP、中国IP刷新成功"

#检查是否存在nftables配置文件,防止其他操作被删除
if ! grep -q "singbox.nft" "/etc/nftables.conf"; then
  echo "include \"${BASE_DIR}/singbox.nft\"" >> "/etc/nftables.conf"
fi

# 保存 nftables 规则
nft list table inet $NFTTABLES_NAME > "${BASE_DIR}/singbox.nft"

# 检测IP变化
BACKUP_FILE="${BASE_DIR}/airport_ips.txt"

# 创建备份
if [ ! -f "$BACKUP_FILE" ]; then
    cp "$AIRPORTLANDING_IPS" "$BACKUP_FILE"
    echo "首次运行,已创建备份文件:$BACKUP_FILE"
fi

# 对比当前文件和备份文件
while IFS= read -r current_line; do
    if echo "$current_line" | grep -qE '^# '; then
        # 如果是标注行,提取名称部分(假设名称部分在 `# ` 后以 `,` 结束)
        label=$(echo "$current_line" | awk -F',' '{print $1}' | sed 's/^# //')
    elif [ -n "$label" ]; then
        # 如果是 IP 行,检查是否发生变化
        old_ip=$(grep -F "$label" "$BACKUP_FILE" -A 1 | tail -n 1)
        if [ "$current_line" != "$old_ip" ]; then
            echolog "$label 的IP发生了变化,原IP为 $old_ip,现在为 $current_line"
        fi
    fi
done < $AIRPORTLANDING_IPS

# 更新备份文件
cp $AIRPORTLANDING_IPS "$BACKUP_FILE"

# 配置定时任务,确保日8:00下载并更新 IP 地址列表
CRON_SCHEDULE="0 8 * * *"
CRON_JOB="$CRON_SCHEDULE $SCRIPT_PATH"

# 检查是否已存在相同的 cron 任务
if crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH"; then
  echo "定时任务已存在,跳过设置。"
else
  (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
  echo "已成功设置每天定时任务,自动更新 IP 地址列表并更新规则。"
fi

echolog "SING-BOX防火墙设置完成"
echo "SING-BOX防火墙设置完成"

本自定义防火墙优先级别较高,防火墙规则可以根据自己的实际情况修改。

前置代理机场节点的路由器及VPS防火墙处理

机场IP发生变动

前置代理机场节点的路由器及VPS防火墙处理

防火墙概况

我们还可以做端口重定向处理。比如VPS的reality服务运行在4433端口,可以通过防火墙,将允许的机场ip集合的443端口流量重定向至4433端口,从而让443端口保持https服务,这样你客户端虽然还是通过443端口代理,但服务器实际服务的是4433端口,其他IP访问443端口就是返回网站服务内容,从而迷惑GFW。由于我这里主要是通过机场过墙,没有做这样的处理。

首先开启端口转发

nano /etc/sysctl.conf

最下方加入

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

保存后,执行命令让其生效

sysctl -p

刚才VPS脚本里删除原有关于reality的规则,然后加入如下内容:

nft add chain inet $NFTTABLES_NAME singboxprerouting { type nat hook prerouting priority -199 \; policy accept \; }

nft add rule inet "$NFTTABLES_NAME" singboxprerouting ip saddr @"$ALLOWED_IPS" tcp dport 443 counter
nft add rule inet "$NFTTABLES_NAME" singboxprerouting ip saddr @"$ALLOWED_IPS" udp dport 443 counter
nft add rule inet "$NFTTABLES_NAME" singboxprerouting ip saddr @"$ALLOWED_IPS" tcp dport 443 redirect to :$REALITY_PORT 
nft add rule inet "$NFTTABLES_NAME" singboxprerouting ip saddr @"$ALLOWED_IPS" udp dport 443 redirect to :$REALITY_PORT

这样,端口转发就处理好了。

最后:提供2个sh脚本的下载,可以根据自己的实际情况来修改使用。点我下载

技术不断升级,请注意文章时效性。
本站文章,欢迎转发。转载请注明出处:https://www.bandwh.com/net/2219.html

(0)

BandWh.com 折腾之路●一起折腾

上一篇 2024年12月23日 10:31
下一篇 2025年1月8日 13:54
瓦工BIGGERBOX-20-1024

相关推荐

发表回复

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

请文明评论!