#!/bin/bash
# 一键系统初始化 + Xray 多 IP Socks5 部署脚本（多网段版本）
# 逻辑：
#   1. 系统 / 内核 / 网卡优化
#   2. 安装 Xray
#   3. 自动识别：同一 /24 段出现 >=3 个 IP 的网段作为 socks5 地址段
#   4. 该 /24 的 1-254 每个 IP 对应一个 socks5 端口
#   5. 随机测一个 socks5，最后重启

#####################################
# 可调参数
#####################################
START_IP=1                 # 尾号起始
END_IP=254                 # 尾号结束
BASE_PORT=51000            # 实际端口 = BASE_PORT + 尾号
S5_USER="vipuser"
S5_PASS="vip@123123"
XRAY_ZIP_URL="https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip"
XRAY_BIN="/usr/local/bin/xray"
XRAY_CONF_DIR="/etc/xray"
XRAY_CONF_FILE="${XRAY_CONF_DIR}/config.json"

#####################################
# 必须 root
#####################################
if [ "$(id -u)" -ne 0 ]; then
    echo "请用 root 运行此脚本"
    exit 1
fi

echo "===== 1. APT 预热 & 基础软件安装 ====="
apt update
apt -y install vim bash-completion wget lrzsz net-tools irqbalance ethtool bc unzip curl

echo "===== 2. 时区 & 时间同步（Asia/Shanghai + chrony） ====="
timedatectl set-timezone Asia/Shanghai
apt install -y chrony
systemctl restart chronyd 2>/dev/null || systemctl restart chrony 2>/dev/null
systemctl enable chronyd 2>/dev/null || systemctl enable chrony 2>/dev/null
chronyc tracking || true
chronyc -a makestep || true

echo "===== 3. 网卡队列 & RPS 调优 ====="
# 获取活动的网络接口（取前两个）
interface1=$(ip a | grep UP | grep -v UNKNOWN | grep -v noqueue | awk '{print $2}' | sed 's/://g' | sed -n '1p')
interface2=$(ip a | grep UP | grep -v UNKNOWN | grep -v noqueue | awk '{print $2}' | sed 's/://g' | sed -n '2p')

if [ -n "$interface1" ]; then
    maxvalue=$(ethtool -g "$interface1" 2>/dev/null | grep RX: | awk '{print $2}' | sed -n '1p')
    if [ -n "$maxvalue" ]; then
        ethtool -G "$interface1" rx "$maxvalue" tx "$maxvalue" 2>/dev/null || true
        [ -n "$interface2" ] && ethtool -G "$interface2" rx "$maxvalue" tx "$maxvalue" 2>/dev/null || true
    fi
fi

# 设置内核参数（部分实时写入）
sysctl -w net.core.rps_sock_flow_entries=65536
sysctl -w net.ipv4.tcp_max_syn_backlog=819200
sysctl -w net.core.netdev_max_backlog=262144

# RPS 相关
N=$(grep -c processor /proc/cpuinfo || echo 1)
[ "$N" -lt 1 ] && N=1
rfc=$(echo 65536/"$N" | bc)
echo "$rfc" | tee /sys/class/net/e*/queues/rx-*/rps_flow_cnt 2>/dev/null || true

if [ "$N" -eq 56 ]; then
    echo "ffffff,ffffffff" | tee /sys/class/net/e*/queues/rx-*/rps_cpus 2>/dev/null || true
    printf "ffffff,ffffffff" | tee /proc/irq/*/smp_affinity 2>/dev/null || true
    echo "0-$((N-1))" | tee /proc/irq/*/smp_affinity_list 2>/dev/null || true
elif [ "$N" -lt 56 ]; then
    mask=$(printf %x $((2**N-1)))
    echo "$mask" | tee /sys/class/net/e*/queues/rx-*/rps_cpus 2>/dev/null || true
    printf %x $((2**N-1)) | tee /proc/irq/*/smp_affinity 2>/dev/null || true
    echo "0-$((N-1))" | tee /proc/irq/*/smp_affinity_list 2>/dev/null || true
fi

echo "===== 4. sysctl / limits / systemd 调优 ====="
cat > /etc/sysctl.conf << 'EOF'
kernel.msgmnb=65536
kernel.msgmax=65536
kernel.shmmax=68719476736
kernel.shmall=4294967296
kernel.printk = 0
vm.swappiness=10

net.core.rps_sock_flow_entries=65536
fs.file-max=1048576
fs.nr_open=1048576
fs.inotify.max_user_instances=131072

# 路由转发
net.ipv4.conf.all.route_localnet=1
net.ipv4.ip_forward=1
net.ipv4.conf.all.forwarding=1
net.ipv4.conf.default.forwarding=1

net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.default.secure_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.default.rp_filter=2
net.ipv4.conf.all.rp_filter=2

net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_retries1=3
net.ipv4.tcp_retries2=3
net.ipv4.tcp_orphan_retries=1
net.ipv4.tcp_max_orphans = 32768
net.ipv4.tcp_syn_retries=1
net.ipv4.tcp_synack_retries=3
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_max_tw_buckets = 32768

net.core.netdev_budget=65536
net.core.netdev_budget_usecs=4096
net.ipv4.tcp_max_syn_backlog = 819200
net.core.netdev_max_backlog=262144
net.core.somaxconn=100000
net.ipv4.tcp_notsent_lowat=16384
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_keepalive_intvl=20
net.ipv4.route.gc_timeout=100
net.ipv4.neigh.default.gc_thresh1=2048
net.ipv4.neigh.default.gc_thresh2=4096 
net.ipv4.neigh.default.gc_thresh3=8192

net.ipv4.tcp_fastopen=3
net.ipv4.tcp_autocorking=0
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_no_metrics_save=1
net.ipv4.tcp_ecn=0
net.ipv4.tcp_frto=0
net.ipv4.tcp_mtu_probing=0
net.ipv4.tcp_sack=1
net.ipv4.tcp_fack=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_adv_win_scale=1
net.ipv4.tcp_moderate_rcvbuf=1

net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.ipv4.tcp_rmem = 8192 87380 67108864
net.ipv4.tcp_wmem = 8192 65536 67108864
net.ipv4.udp_rmem_min=8192
net.ipv4.udp_wmem_min=8192
net.ipv4.tcp_mem=262144 1048576 4194304
net.ipv4.udp_mem=262144 1048576 4194304
net.ipv4.tcp_congestion_control=bbr
net.core.default_qdisc=fq
net.ipv4.ip_local_port_range=1025 65535
net.ipv4.ping_group_range=0 2147483647
EOF

[ -f /sys/kernel/mm/transparent_hugepage/enabled ] && echo madvise > /sys/kernel/mm/transparent_hugepage/enabled 2>/dev/null || true

sed -i '/DefaultTimeoutStartSec/d' /etc/systemd/system.conf 2>/dev/null || true
sed -i '/DefaultTimeoutStopSec/d' /etc/systemd/system.conf 2>/dev/null || true
sed -i '/DefaultRestartSec/d' /etc/systemd/system.conf 2>/dev/null || true
sed -i '/DefaultLimitCORE/d' /etc/systemd/system.conf 2>/dev/null || true
sed -i '/DefaultLimitNOFILE/d' /etc/systemd/system.conf 2>/dev/null || true
sed -i '/DefaultLimitNPROC/d' /etc/systemd/system.conf 2>/dev/null || true

cat > /etc/systemd/system.conf << 'EOF'
[Manager]
DefaultTimeoutStopSec=30s
DefaultLimitCORE=infinity
DefaultLimitNOFILE=65535
DefaultLimitNPROC=65535
EOF

cat > /etc/security/limits.conf << 'EOF'
root     soft   nofile    1048576
root     hard   nofile    1048576
root     soft   nproc     1048576
root     hard   nproc     1048576
root     soft   core      unlimited
root     hard   core      unlimited
root     hard   memlock   unlimited
root     soft   memlock   unlimited

*     soft   nofile    1048576
*     hard   nofile    1048576
*     soft   nproc     1048576
*     hard   nproc     1048576
*     soft   core      unlimited
*     hard   core      unlimited
*     hard   memlock   unlimited
*     soft   memlock   unlimited
EOF

sysctl -p

echo "===== 5. 启用 IRQBalance & 网卡 GRO/TSO 等优化 ====="
systemctl enable irqbalance
systemctl start irqbalance

for iface in $(ls /sys/class/net | grep -v lo); do
    ethtool -K "$iface" gro on lro on tso on gso on 2>/dev/null || true
    ethtool -G "$iface" rx 4096 tx 4096 2>/dev/null || true
done

for dev in $(ls /sys/block/ | grep 'sd'); do
    echo "deadline" > /sys/block/"$dev"/queue/scheduler 2>/dev/null || true
done

echo "===== 6. 配置 DNS（/etc/resolv.conf -> 8.8.8.8） ====="
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
EOF

echo "===== 7. 安装 Xray ====="
mkdir -p /var/log/xray
cd /tmp || exit 1
rm -f Xray-linux-64.zip
wget -O Xray-linux-64.zip "$XRAY_ZIP_URL"
unzip -o Xray-linux-64.zip -d /usr/local/bin/
chmod +x "$XRAY_BIN"

#####################################
# 8. 自动识别 socks5 使用的 /24 段（出现 >=3 个 IP 的网段）
#####################################
echo "===== 8. 自动识别 socks5 IP 段（出现 >=3 个 IP 的 /24） ====="

# 获取全部全局 IPv4
mapfile -t ALL_IPS < <(ip -4 addr show scope global | awk '/inet /{print $2}' | cut -d/ -f1)

declare -A COUNT
declare -A LIST

for ip in "${ALL_IPS[@]}"; do
    pfx=$(echo "$ip" | awk -F. '{print $1"."$2"."$3}')
    COUNT["$pfx"]=$((COUNT["$pfx"] + 1))
    LIST["$pfx"]+="$ip "
done

SOCKS_PREFIX=""
MAXCNT=0
for pfx in "${!COUNT[@]}"; do
    if [ "${COUNT[$pfx]}" -ge 3 ] && [ "${COUNT[$pfx]}" -gt "$MAXCNT" ]; then
        SOCKS_PREFIX="$pfx"
        MAXCNT=${COUNT[$pfx]}
    fi
done

if [ -z "$SOCKS_PREFIX" ]; then
    echo "未找到出现 >=3 个 IP 的网段，无法判断 socks5 网段，退出。"
    echo "全部全局 IP："
    printf '  %s\n' "${ALL_IPS[@]}"
    exit 1
fi

echo "检测到 socks5 地址段：${SOCKS_PREFIX}.x"
echo "该网段绑定的 IP 有：${LIST[$SOCKS_PREFIX]}"

PREFIX_IP="$SOCKS_PREFIX"

#####################################
# 9. 生成 Xray 配置（整段 /24 1-254）
#####################################
echo "===== 9. 生成 Xray 配置（${PREFIX_IP}.1-${PREFIX_IP}.254） ====="
mkdir -p "$XRAY_CONF_DIR"

{
cat <<EOF
{
    "log": {
        "access": "/var/log/xray/access.log",
        "error": "/var/log/xray/error.log",
        "loglevel": "info"
    },
    "inbounds": [
EOF

for i in $(seq "$START_IP" "$END_IP"); do
    ip="${PREFIX_IP}.${i}"
    port=$((BASE_PORT + i))

    if [ "$i" -lt "$END_IP" ]; then
        comma=","
    else
        comma=""
    fi

    cat <<EOF
        {
            "tag": "socks-1-$i",
            "protocol": "socks",
            "listen": "$ip",
            "port": $port,
            "settings": {
                "auth": "password",
                "accounts": [
                    {
                        "user": "$S5_USER",
                        "pass": "$S5_PASS"
                    }
                ],
                "udp": true,
                "ip": "$ip"
            }
        }$comma
EOF
done

cat <<EOF
    ],
    "routing": {
        "rules": [
EOF

for i in $(seq "$START_IP" "$END_IP"); do
    if [ "$i" -lt "$END_IP" ]; then
        comma=","
    else
        comma=""
    fi

    cat <<EOF
            {
                "inboundTag": ["socks-1-$i"],
                "outboundTag": "direct-1-$i"
            }$comma
EOF
done

cat <<EOF
        ]
    },
    "outbounds": [
EOF

for i in $(seq "$START_IP" "$END_IP"); do
    ip="${PREFIX_IP}.${i}"
    if [ "$i" -lt "$END_IP" ]; then
        comma=","
    else
        comma=""
    fi

    cat <<EOF
        {
            "protocol": "freedom",
            "tag": "direct-1-$i",
            "settings": {},
            "sendThrough": "$ip"
        }$comma
EOF
done

cat <<EOF
    ]
}
EOF

} > "$XRAY_CONF_FILE"

echo "Xray 配置生成完成：$XRAY_CONF_FILE"

echo "===== 10. 测试 Xray 配置语法 ====="
"$XRAY_BIN" -config "$XRAY_CONF_FILE" -test
if [ $? -ne 0 ]; then
    echo "Xray 配置测试失败，脚本退出，不重启。"
    exit 1
fi

echo "===== 11. 创建 Xray systemd 服务并启动 ====="
cat > /etc/systemd/system/xray.service << EOF
[Unit]
Description=Xray Service
After=network.target

[Service]
User=root
LimitNOFILE=1048576
ExecStart=${XRAY_BIN} -config ${XRAY_CONF_FILE}
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable xray
systemctl restart xray

echo "===== 12. 随机检查一个 SOCKS5 是否可用 ====="
sleep 5

rand=$((RANDOM % (END_IP - START_IP + 1) + START_IP))
test_ip="${PREFIX_IP}.${rand}"
test_port=$((BASE_PORT + rand))

echo "随机抽测：${test_ip}:${test_port}"

HTTP_CODE=$(curl -x "socks5h://${S5_USER}:${S5_PASS}@${test_ip}:${test_port}" -m 8 -s -o /dev/null -w "%{http_code}" https://api.ipify.org || echo "000")

if [ "$HTTP_CODE" = "200" ]; then
    echo "socks5 ok (${test_ip}:${test_port})"
else
    echo "socks5 fail (${test_ip}:${test_port}) http_code=${HTTP_CODE}"
fi

echo "===== 13. 所有配置执行完毕，5 秒后重启 ====="
sleep 5
reboot

