更新 hy2.sh

This commit is contained in:
2026-03-19 15:04:56 +08:00
parent 742a173697
commit 86efd98624

187
hy2.sh
View File

@@ -1,8 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
trap 'echo "[错误] 第 $LINENO 行执行失败:$BASH_COMMAND"' ERR
CONFIG_FILE="/etc/hysteria/config.yaml" CONFIG_FILE="/etc/hysteria/config.yaml"
SERVICE_NAME="hysteria-server.service" SERVICE_NAME="hysteria-server.service"
MASQUERADE_DEFAULT_URL="https://news.ycombinator.com/"
red() { printf '\033[31m%s\033[0m\n' "$*"; } red() { printf '\033[31m%s\033[0m\n' "$*"; }
green() { printf '\033[32m%s\033[0m\n' "$*"; } green() { printf '\033[32m%s\033[0m\n' "$*"; }
@@ -52,15 +54,20 @@ generate_password() {
echo echo
} }
get_server_ip() { generate_sub_prefix() {
local ipv4 ipv6 openssl rand -base64 32 | tr -dc 'a-z0-9' | head -c 8
echo
}
get_public_ips() {
local ipv4="" ipv6=""
ipv4="$(curl -4 -fsSL https://api.ipify.org || true)" ipv4="$(curl -4 -fsSL https://api.ipify.org || true)"
ipv6="$(curl -6 -fsSL https://api64.ipify.org || true)" ipv6="$(curl -6 -fsSL https://api64.ipify.org || true)"
echo "${ipv4}|${ipv6}" printf '%s|%s\n' "$ipv4" "$ipv6"
} }
apt_update_and_install_base() { apt_update_and_install_base() {
if ! confirm_yn "即将执行 apt update 并安装基础依赖 curl sed ufw openssl是否继续"; then if ! confirm_yn "即将执行 apt update 并安装基础依赖 curl sed ufw jq openssl是否继续"; then
red "已取消。" red "已取消。"
exit 1 exit 1
fi fi
@@ -70,7 +77,7 @@ apt_update_and_install_base() {
apt update -y apt update -y
blue "==> 安装基础依赖" blue "==> 安装基础依赖"
apt install -y curl sed ufw openssl apt install -y curl sed ufw jq openssl
} }
disable_existing_firewalls() { disable_existing_firewalls() {
@@ -168,15 +175,118 @@ install_hysteria2() {
green "Hysteria 2 安装完成。" green "Hysteria 2 安装完成。"
} }
run_domain_selector() { cf_api() {
if confirm_yn "是否执行外部域名筛选脚本?"; then local method="$1"
blue "==> 执行域名筛选脚本" local endpoint="$2"
bash <(curl -sL https://raw.githubusercontent.com/ccxkai233/Domain_Selector/main/domain_check.sh) || true local token="$3"
local data="${4:-}"
if [[ -n "$data" ]]; then
curl -fsSL -X "$method" "https://api.cloudflare.com/client/v4${endpoint}" \
-H "Authorization: Bearer ${token}" \
-H "Content-Type: application/json" \
--data "$data"
else else
yellow "已跳过域名筛选脚本。" curl -fsSL -X "$method" "https://api.cloudflare.com/client/v4${endpoint}" \
-H "Authorization: Bearer ${token}" \
-H "Content-Type: application/json"
fi fi
} }
get_cf_zone_id() {
local main_domain="$1"
local token="$2"
local resp zone_id
resp="$(cf_api GET "/zones?name=${main_domain}&status=active" "$token")"
zone_id="$(printf '%s' "$resp" | jq -r '.result[0].id // empty')"
if [[ -z "$zone_id" ]]; then
red "未找到 Cloudflare Zone${main_domain}"
red "请确认主域名已接入 Cloudflare且 API Token 对该 Zone 具有 DNS 编辑权限。"
exit 1
fi
printf '%s\n' "$zone_id"
}
delete_existing_dns_record_if_needed() {
local zone_id="$1"
local full_domain="$2"
local type="$3"
local token="$4"
local resp record_ids rid
resp="$(cf_api GET "/zones/${zone_id}/dns_records?type=${type}&name=${full_domain}" "$token")"
record_ids="$(printf '%s' "$resp" | jq -r '.result[].id // empty')"
if [[ -n "$record_ids" ]]; then
while IFS= read -r rid; do
[[ -z "$rid" ]] && continue
cf_api DELETE "/zones/${zone_id}/dns_records/${rid}" "$token" >/dev/null
done <<< "$record_ids"
fi
}
create_cf_dns_record() {
local zone_id="$1"
local full_domain="$2"
local type="$3"
local content="$4"
local token="$5"
local payload resp success
payload="$(jq -nc \
--arg type "$type" \
--arg name "$full_domain" \
--arg content "$content" \
'{type:$type,name:$name,content:$content,ttl:120,proxied:false}')"
resp="$(cf_api POST "/zones/${zone_id}/dns_records" "$token" "$payload")"
success="$(printf '%s' "$resp" | jq -r '.success')"
if [[ "$success" != "true" ]]; then
red "创建 Cloudflare DNS 记录失败:"
printf '%s\n' "$resp" | jq .
exit 1
fi
}
create_cloudflare_dns_records() {
local main_domain="$1"
local sub_prefix="$2"
local token="$3"
local ip_info="$4"
local ipv4="${ip_info%%|*}"
local ipv6="${ip_info##*|}"
local full_domain="${sub_prefix}.${main_domain}"
local zone_id
zone_id="$(get_cf_zone_id "$main_domain" "$token")"
blue "==> 在 Cloudflare 中创建 DNS 记录"
echo "Zone: ${main_domain}"
echo "完整域名: ${full_domain}"
if [[ -n "$ipv4" ]]; then
delete_existing_dns_record_if_needed "$zone_id" "$full_domain" "A" "$token"
create_cf_dns_record "$zone_id" "$full_domain" "A" "$ipv4" "$token"
green "已创建 A 记录 -> ${ipv4}"
fi
if [[ -n "$ipv6" ]]; then
delete_existing_dns_record_if_needed "$zone_id" "$full_domain" "AAAA" "$token"
create_cf_dns_record "$zone_id" "$full_domain" "AAAA" "$ipv6" "$token"
green "已创建 AAAA 记录 -> ${ipv6}"
fi
if [[ -z "$ipv4" && -z "$ipv6" ]]; then
red "未获取到当前机器公网 IPv4/IPv6无法创建 DNS 记录。"
exit 1
fi
printf '%s\n' "$full_domain"
}
backup_existing_config() { backup_existing_config() {
if [[ -f "${CONFIG_FILE}" ]]; then if [[ -f "${CONFIG_FILE}" ]]; then
local backup_file="${CONFIG_FILE}.bak.$(date +%Y%m%d_%H%M%S)" local backup_file="${CONFIG_FILE}.bak.$(date +%Y%m%d_%H%M%S)"
@@ -186,7 +296,7 @@ backup_existing_config() {
} }
write_config() { write_config() {
local domain="$1" local full_domain="$1"
local email="$2" local email="$2"
local cf_token="$3" local cf_token="$3"
local password="$4" local password="$4"
@@ -199,7 +309,7 @@ listen: :443
acme: acme:
domains: domains:
- ${domain} - ${full_domain}
email: ${email} email: ${email}
type: dns type: dns
dns: dns:
@@ -232,7 +342,7 @@ listen: :443
acme: acme:
domains: domains:
- ${domain} - ${full_domain}
email: ${email} email: ${email}
type: dns type: dns
dns: dns:
@@ -270,42 +380,35 @@ start_service() {
} }
show_result() { show_result() {
local domain="$1" local full_domain="$1"
local password="$2" local password="$2"
local proxy_url="$3" local proxy_url="$3"
local ip_info="$4" local ip_info="$4"
local ipv4="${ip_info%%|*}" local ipv4="${ip_info%%|*}"
local ipv6="${ip_info##*|}" local ipv6="${ip_info##*|}"
local share_link="hysteria2://${password}@${full_domain}:443/?sni=${full_domain}&insecure=0"
local share_link="hysteria2://${password}@${domain}:443/?sni=${domain}&insecure=0"
echo echo
green "================= HY2 节点信息 =================" green "================= HY2 节点信息 ================="
echo "服务名: ${SERVICE_NAME}" echo "名: ${full_domain}"
echo "配置文件: ${CONFIG_FILE}"
echo "域名: ${domain}"
echo "端口: 443" echo "端口: 443"
echo "认证方式: password"
echo "密码: ${password}" echo "密码: ${password}"
echo "伪装站点: ${proxy_url}" echo "伪装站点: ${proxy_url}"
[[ -n "${ipv4}" ]] && echo "服务器 IPv4: ${ipv4}" [[ -n "${ipv4}" ]] && echo "IPv4: ${ipv4}"
[[ -n "${ipv6}" ]] && echo "服务器 IPv6: ${ipv6}" [[ -n "${ipv6}" ]] && echo "IPv6: ${ipv6}"
echo echo
echo "代理链接:" echo "代理链接:"
echo "${share_link}" echo "${share_link}"
echo echo
echo "systemd 状态:" echo "hysteria 状态:"
systemctl --no-pager --full status "${SERVICE_NAME}" || true systemctl status "${SERVICE_NAME}" --no-pager -l | sed -n '1,8p'
echo
echo "最近日志:"
journalctl --no-pager -n 30 -u "${SERVICE_NAME}" || true
echo "================================================" echo "================================================"
} }
main() { main() {
require_root require_root
if ! confirm_yn "本脚本将更新软件源、关闭现有防火墙、配置 UFW、安装并配置 Hysteria 2是否继续"; then if ! confirm_yn "本脚本将更新软件源、关闭现有防火墙、配置 UFW、安装并配置 Hysteria 2、自动创建 Cloudflare DNS,是否继续?"; then
red "用户取消执行。" red "用户取消执行。"
exit 1 exit 1
fi fi
@@ -316,26 +419,34 @@ main() {
require_cmd sed require_cmd sed
require_cmd systemctl require_cmd systemctl
require_cmd ufw require_cmd ufw
require_cmd jq
require_cmd openssl
local domain email cf_token password proxy_url ip_info local main_domain email cf_token password sub_prefix full_domain ip_info proxy_url
domain="$(prompt_nonempty '请输入用于签发证书的域名: ')" main_domain="$(prompt_nonempty '请输入主域名(例如 example.com: ')"
email="$(prompt_nonempty '请输入 ACME 邮箱: ')" email="$(prompt_nonempty '请输入 ACME 邮箱: ')"
cf_token="$(prompt_nonempty '请输入 Cloudflare API Token: ')" cf_token="$(prompt_nonempty '请输入 Cloudflare API Token: ')"
password="$(generate_password)" password="$(generate_password)"
sub_prefix="$(generate_sub_prefix)"
ip_info="$(get_public_ips)"
full_domain="$(create_cloudflare_dns_records "$main_domain" "$sub_prefix" "$cf_token" "$ip_info")"
proxy_url="$MASQUERADE_DEFAULT_URL"
echo
green "自动生成的 Hysteria 域名: ${full_domain}"
echo "默认伪装站点: ${proxy_url}"
echo "随机密码: ${password}"
echo
disable_existing_firewalls disable_existing_firewalls
configure_ufw configure_ufw
install_hysteria2 install_hysteria2
run_domain_selector write_config "${full_domain}" "${email}" "${cf_token}" "${password}" "${proxy_url}"
proxy_url="$(prompt_nonempty '请输入最终用于 masquerade 的完整 URL例如 https://example.com/: ')"
write_config "${domain}" "${email}" "${cf_token}" "${password}" "${proxy_url}"
start_service start_service
show_result "${full_domain}" "${password}" "${proxy_url}" "${ip_info}"
ip_info="$(get_server_ip)"
show_result "${domain}" "${password}" "${proxy_url}" "${ip_info}"
} }
main "$@" main "$@"