#!/usr/bin/env bash set -Eeuo pipefail CONFIG_FILE="/etc/hysteria/config.yaml" SERVICE_NAME="hysteria-server.service" red() { printf '\033[31m%s\033[0m\n' "$*"; } green() { printf '\033[32m%s\033[0m\n' "$*"; } yellow() { printf '\033[33m%s\033[0m\n' "$*"; } blue() { printf '\033[36m%s\033[0m\n' "$*"; } require_root() { if [[ "${EUID}" -ne 0 ]]; then red "请使用 root 运行此脚本。" exit 1 fi } require_cmd() { command -v "$1" >/dev/null 2>&1 || { red "缺少命令: $1" exit 1 } } prompt_nonempty() { local prompt="$1" local value="" while true; do read -r -p "$prompt" value if [[ -n "${value// }" ]]; then printf '%s' "$value" return 0 fi yellow "输入不能为空,请重新输入。" done } confirm_yes() { local prompt="${1:-确认继续?输入 yes 继续: }" local answer read -r -p "$prompt" answer [[ "$answer" == "yes" ]] } double_confirm() { local title="$1" local detail="$2" echo yellow "========== 二次确认 ==========" yellow "$title" echo "$detail" echo confirm_yes "第一次确认,输入 yes 继续: " || return 1 confirm_yes "第二次确认,输入 yes 最终执行: " || return 1 return 0 } generate_password() { tr -dc 'A-Za-z0-9' 更新 APT 软件库" export DEBIAN_FRONTEND=noninteractive apt update -y blue "==> 安装基础依赖" apt install -y curl sed ufw iptables ip6tables } disable_existing_firewalls() { if ! double_confirm \ "即将停用当前系统防火墙并清空规则" \ $'将尝试执行以下操作:\n- 关闭并重置 UFW\n- 停止并禁用 firewalld\n- 停止并禁用 nftables\n- 清空 nftables ruleset\n- 清空 iptables / ip6tables 规则\n\n该操作可能影响当前网络访问控制策略。'; then red "用户取消:未停用现有防火墙。" exit 1 fi blue "==> 自动检测并关闭当前系统防火墙" if command -v ufw >/dev/null 2>&1; then yellow "检测到 UFW,正在关闭并重置" ufw disable || true yes | ufw reset || true fi if systemctl list-unit-files 2>/dev/null | grep -q '^firewalld\.service'; then yellow "检测到 firewalld,正在停止并禁用" systemctl stop firewalld || true systemctl disable firewalld || true systemctl mask firewalld || true fi if systemctl list-unit-files 2>/dev/null | grep -q '^nftables\.service'; then yellow "检测到 nftables,正在停止并禁用" systemctl stop nftables || true systemctl disable nftables || true fi if command -v nft >/dev/null 2>&1; then yellow "清空 nftables 规则" nft flush ruleset || true fi yellow "清空 iptables / ip6tables 规则" iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT || true ip6tables -I INPUT 1 -p tcp --dport 22 -j ACCEPT || true iptables -F || true iptables -X || true iptables -Z || true iptables -P INPUT ACCEPT || true iptables -P FORWARD ACCEPT || true iptables -P OUTPUT ACCEPT || true ip6tables -F || true ip6tables -X || true ip6tables -Z || true ip6tables -P INPUT ACCEPT || true ip6tables -P FORWARD ACCEPT || true ip6tables -P OUTPUT ACCEPT || true green "现有防火墙已处理完成。" } configure_ufw() { if ! double_confirm \ "即将启用并配置 UFW" \ $'将执行以下规则:\n- 默认拒绝入站\n- 默认允许出站\n- 放行 22/tcp\n- 放行 80/tcp\n- 放行 443/tcp\n- 放行 443/udp\n- 启用 IPv6'; then red "用户取消:未配置 UFW。" exit 1 fi blue "==> 配置 UFW" sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw || true ufw default deny incoming || true ufw default allow outgoing || true ufw allow 22/tcp || true ufw allow 80/tcp || true ufw allow 443/tcp || true ufw allow 443/udp || true yes | ufw enable || true green "UFW 配置完成。" } install_hysteria2() { if ! double_confirm \ "即将安装 Hysteria 2" \ $'将执行:\n- bash <(curl -fsSL https://get.hy2.sh/)\n\n该步骤会从外部下载安装脚本并执行。'; then red "用户取消:未安装 Hysteria 2。" exit 1 fi blue "==> 安装 Hysteria 2" bash <(curl -fsSL https://get.hy2.sh/) green "Hysteria 2 安装完成。" } run_domain_selector() { blue "==> 执行域名筛选脚本" yellow "请根据脚本输出结果,手动输入最终伪装 URL" if ! confirm_yes "确认执行外部域名筛选脚本?输入 yes 继续: "; then red "用户取消:未执行域名筛选脚本。" return 0 fi bash <(curl -sL https://raw.githubusercontent.com/ccxkai233/Domain_Selector/main/domain_check.sh) || true } backup_existing_config() { if [[ -f "${CONFIG_FILE}" ]]; then local backup_file="${CONFIG_FILE}.bak.$(date +%Y%m%d_%H%M%S)" cp -a "${CONFIG_FILE}" "${backup_file}" yellow "检测到已有配置,已备份到: ${backup_file}" fi } write_config() { local domain="$1" local email="$2" local cf_token="$3" local password="$4" local proxy_url="$5" echo blue "==> 即将写入以下配置" cat < "${CONFIG_FILE}" < 启动并设置开机自启" systemctl daemon-reload || true systemctl enable --now "${SERVICE_NAME}" systemctl restart "${SERVICE_NAME}" green "服务已启动。" } show_result() { local domain="$1" local password="$2" local proxy_url="$3" local ip_info="$4" local ipv4="${ip_info%%|*}" local ipv6="${ip_info##*|}" local share_link="hysteria2://${password}@${domain}:443/?sni=${domain}&insecure=0" echo green "================= HY2 节点信息 =================" echo "服务名: ${SERVICE_NAME}" echo "配置文件: ${CONFIG_FILE}" echo "域名: ${domain}" echo "端口: 443" echo "认证方式: password" echo "密码: ${password}" echo "伪装站点: ${proxy_url}" [[ -n "${ipv4}" ]] && echo "服务器 IPv4: ${ipv4}" [[ -n "${ipv6}" ]] && echo "服务器 IPv6: ${ipv6}" echo echo "代理链接:" echo "${share_link}" echo echo "systemd 状态:" systemctl --no-pager --full status "${SERVICE_NAME}" || true echo echo "最近日志:" journalctl --no-pager -n 30 -u "${SERVICE_NAME}" || true echo "================================================" } main() { require_root if ! double_confirm \ "脚本总确认" \ $'本脚本将执行以下操作:\n- apt update -y\n- 安装基础依赖\n- 自动检测并停用当前系统防火墙\n- 重建 UFW 规则\n- 安装 Hysteria 2\n- 写入 /etc/hysteria/config.yaml\n- 启动并启用 hysteria-server.service'; then red "用户取消执行。" exit 1 fi local domain email cf_token password proxy_url ip_info apt_update_and_install_base require_cmd curl require_cmd sed require_cmd systemctl require_cmd iptables require_cmd ip6tables require_cmd ufw domain="$(prompt_nonempty '请输入用于签发证书的域名: ')" email="$(prompt_nonempty '请输入 ACME 邮箱: ')" cf_token="$(prompt_nonempty '请输入 Cloudflare API Token: ')" password="$(generate_password)" disable_existing_firewalls configure_ufw install_hysteria2 run_domain_selector proxy_url="$(prompt_nonempty '请输入最终用于 masquerade 的完整 URL(例如 https://example.com/): ')" write_config "${domain}" "${email}" "${cf_token}" "${password}" "${proxy_url}" start_service ip_info="$(get_server_ip)" show_result "${domain}" "${password}" "${proxy_url}" "${ip_info}" } main "$@"