#!/bin/bash export LANG=ru_RU.UTF-8 RED="\033[31m" GREEN="\033[32m" YELLOW="\033[33m" PLAIN="\033[0m" red(){ echo -e "\033[31m\033[01m$1\033[0m" } green(){ echo -e "\033[32m\033[01m$1\033[0m" } yellow(){ echo -e "\033[33m\033[01m$1\033[0m" } if [[ $EUID -ne 0 ]]; then red "Внимание: Запустите скрипт от имени root пользователя" exit 1 fi CUSTOM_SNI="" for arg in "$@"; do case $arg in --custom-sni=*) CUSTOM_SNI="${arg#*=}" shift ;; --help) echo "Использование: $0 [--custom-sni=example.com]" echo "" echo "Опции:" echo " --custom-sni=HOSTNAME Указать свой SNI хост (по умолчанию: web.max.ru)" echo " --help Показать эту справку" exit 0 ;; esac done REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora" "alpine") RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora" "Alpine") PACKAGE_UPDATE=("apt-get update" "apt-get update" "yum -y update" "yum -y update" "yum -y update" "apk update -f") PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "yum -y install" "apk add -f") CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')") for i in "${CMD[@]}"; do SYS="$i" && [[ -n $SYS ]] && break done for ((int = 0; int < ${#REGEX[@]}; int++)); do [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break done [[ -z $SYSTEM ]] && red "Текущая система VPS не поддерживается, используйте основную операционную систему" && exit 1 if [[ -z $(type -P curl) ]]; then if [[ ! $SYSTEM == "CentOS" ]]; then ${PACKAGE_UPDATE[int]} fi ${PACKAGE_INSTALL[int]} curl fi get_ip() { local ip=$(curl -s4m8 ip.sb -k) || ip=$(curl -s6m8 ip.sb -k) echo "$ip" } install_server_core() { yellow "Установка Hysteria2..." set -e SCRIPT_ARGS=("$@") EXECUTABLE_INSTALL_PATH="/usr/local/bin/hysteria" SYSTEMD_SERVICES_DIR="/etc/systemd/system" CONFIG_DIR="/etc/hysteria" REPO_URL="https://github.com/apernet/hysteria" HY2_API_BASE_URL="https://api.hy2.io/v1" CURL_FLAGS=(-L -f -q --retry 5 --retry-delay 10 --retry-max-time 60) PACKAGE_MANAGEMENT_INSTALL="${PACKAGE_MANAGEMENT_INSTALL:-}" OPERATING_SYSTEM="${OPERATING_SYSTEM:-}" ARCHITECTURE="${ARCHITECTURE:-}" HYSTERIA_USER="${HYSTERIA_USER:-}" HYSTERIA_HOME_DIR="${HYSTERIA_HOME_DIR:-}" OPERATION= VERSION= FORCE= LOCAL_FILE= has_command() { local _command=$1 type -P "$_command" > /dev/null 2>&1 } curl() { command curl "${CURL_FLAGS[@]}" "$@" } mktemp() { command mktemp "$@" "/tmp/hyservinst.XXXXXXXXXX" } note() { local _msg="$1" echo -e "$SCRIPT_NAME: $(tput bold)note: $_msg$(tput sgr0)" } warning() { local _msg="$1" echo -e "$SCRIPT_NAME: $(tput setaf 3)warning: $_msg$(tput sgr0)" } error() { local _msg="$1" echo -e "$SCRIPT_NAME: $(tput setaf 1)error: $_msg$(tput sgr0)" } check_environment_operating_system() { if [[ -n "$OPERATING_SYSTEM" ]]; then warning "OPERATING_SYSTEM=$OPERATING_SYSTEM обнаружено, определение ОС выполняться не будет." return fi if [[ "x$(uname)" == "xLinux" ]]; then OPERATING_SYSTEM=linux return fi error "Этот скрипт поддерживает только Linux." exit 95 } check_environment_architecture() { if [[ -n "$ARCHITECTURE" ]]; then warning "ARCHITECTURE=$ARCHITECTURE обнаружено, определение архитектуры выполняться не будет." return fi case "$(uname -m)" in 'i386' | 'i686') ARCHITECTURE='386' ;; 'amd64' | 'x86_64') ARCHITECTURE='amd64' ;; 'armv5tel' | 'armv6l' | 'armv7' | 'armv7l') ARCHITECTURE='arm' ;; 'armv8' | 'aarch64') ARCHITECTURE='arm64' ;; 'mips' | 'mipsle' | 'mips64' | 'mips64le') ARCHITECTURE='mipsle' ;; 's390x') ARCHITECTURE='s390x' ;; *) error "Архитектура '$(uname -a)' не поддерживается." exit 8 ;; esac } check_environment_systemd() { if [[ -d "/run/systemd/system" ]] || grep -q systemd <(ls -l /sbin/init); then return fi case "$FORCE_NO_SYSTEMD" in '1') warning "FORCE_NO_SYSTEMD=1, продолжим даже если systemd не обнаружен." ;; '2') warning "FORCE_NO_SYSTEMD=2, продолжим но пропустим все команды связанные с systemd." ;; *) error "Этот скрипт поддерживает только дистрибутивы Linux с systemd." exit 1 ;; esac } update_packages() { ${PACKAGE_UPDATE[int]} } check_environment_curl() { if has_command curl; then return fi ${PACKAGE_INSTALL[int]} curl } check_environment_grep() { if has_command grep; then return fi ${PACKAGE_INSTALL[int]} grep } check_environment_qrencode() { if has_command qrencode; then return fi ${PACKAGE_INSTALL[int]} qrencode } check_environment() { update_packages check_environment_operating_system check_environment_architecture check_environment_systemd check_environment_curl check_environment_grep check_environment_qrencode } install_content() { local _install_flags="$1" local _content="$2" local _destination="$3" local _overwrite="$4" local _tmpfile="$(mktemp)" echo -ne "Установка $_destination ... " echo "$_content" > "$_tmpfile" if [[ -z "$_overwrite" && -e "$_destination" ]]; then echo -e "существует" elif install "$_install_flags" "$_tmpfile" "$_destination"; then echo -e "ок" fi rm -f "$_tmpfile" } get_latest_version() { if [[ -n "$VERSION" ]]; then echo "$VERSION" return fi local _tmpfile=$(mktemp) if ! curl -sS "$HY2_API_BASE_URL/update?cver=installscript&plat=${OPERATING_SYSTEM}&arch=${ARCHITECTURE}&chan=release&side=server" -o "$_tmpfile"; then error "Ошибка получения последней версии от Hysteria 2 API" exit 11 fi local _latest_version=$(grep -oP '"lver":\s*\K"v.*?"' "$_tmpfile" | head -1) _latest_version=${_latest_version#'"'} _latest_version=${_latest_version%'"'} if [[ -n "$_latest_version" ]]; then echo "$_latest_version" fi rm -f "$_tmpfile" } download_hysteria() { local _version="$1" local _destination="$2" local _download_url="$REPO_URL/releases/download/app/$_version/hysteria-$OPERATING_SYSTEM-$ARCHITECTURE" echo "Загрузка бинарного файла hysteria: $_download_url ..." if ! curl -R -H 'Cache-Control: no-cache' "$_download_url" -o "$_destination"; then error "Ошибка загрузки, проверьте ваше соединение и попробуйте снова." return 11 fi return 0 } perform_install_hysteria_binary() { local _tmpfile=$(mktemp) local _version=$(get_latest_version) if ! download_hysteria "$_version" "$_tmpfile"; then rm -f "$_tmpfile" exit 11 fi echo -ne "Установка исполняемого файла hysteria ... " if install -Dm755 "$_tmpfile" "$EXECUTABLE_INSTALL_PATH"; then echo "ок" else exit 13 fi rm -f "$_tmpfile" mkdir -p /etc/hysteria } perform_install_hysteria_systemd() { if [[ "x$FORCE_NO_SYSTEMD" == "x2" ]]; then return fi local _service_content=$(cat << 'EOF' [Unit] Description=Hysteria Server Service (config.yaml) After=network.target [Service] Type=simple ExecStart=/usr/local/bin/hysteria server --config /etc/hysteria/config.yaml WorkingDirectory=~ User=root Group=root Environment=HYSTERIA_LOG_LEVEL=info CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW NoNewPrivileges=true [Install] WantedBy=multi-user.target EOF ) install_content -Dm644 "$_service_content" "$SYSTEMD_SERVICES_DIR/hysteria-server.service" "1" systemctl daemon-reload } check_environment HYSTERIA_USER="root" HYSTERIA_HOME_DIR="/root" perform_install_hysteria_binary perform_install_hysteria_systemd green "Hysteria2 core успешно установлен!" } configure_hysteria() { yellow "Настройка сервера Hysteria2..." if [[ -n "$CUSTOM_SNI" ]]; then local sni_host="$CUSTOM_SNI" yellow "Используется кастомный SNI: $sni_host" else local sni_host="web.max.ru" fi local masquerade_url="$sni_host" local port="443" mkdir -p /etc/hysteria local auth_pwd=$(date +%s%N | md5sum | cut -c 1-16) local obfs_pwd=$(date +%s%N | md5sum | cut -c 1-16) openssl ecparam -genkey -name prime256v1 -out /etc/hysteria/private.key openssl req -new -x509 -days 36500 -key /etc/hysteria/private.key -out /etc/hysteria/cert.crt -subj "/CN=$sni_host" chmod 600 /etc/hysteria/cert.crt chmod 600 /etc/hysteria/private.key cat << EOF > /etc/hysteria/config.yaml listen: :$port tls: cert: /etc/hysteria/cert.crt key: /etc/hysteria/private.key obfs: type: salamander salamander: password: $obfs_pwd auth: type: password password: $auth_pwd masquerade: type: proxy proxy: url: https://$masquerade_url rewriteHost: true quic: initStreamReceiveWindow: 16777216 maxStreamReceiveWindow: 16777216 initConnReceiveWindow: 33554432 maxConnReceiveWindow: 33554432 EOF local server_ip=$(get_ip) cat << EOF > /root/hysteria2.txt hy2://$auth_pwd@$server_ip:$port?mport&security=tls&sni=$sni_host&allowInsecure=true&alpn&obfs=salamander&obfs-password=$obfs_pwd#Test EOF green "Настройка завершена!" echo yellow "IP сервера: $server_ip" yellow "Порт: $port" yellow "SNI: $sni_host" yellow "Пароль аутентификации: $auth_pwd" yellow "Пароль обфускации: $obfs_pwd" yellow "Маскировка: https://$masquerade_url" echo if [[ -n "$CUSTOM_SNI" ]]; then green "Использован кастомный SNI: $CUSTOM_SNI" fi } start_service() { yellow "Запуск службы Hysteria2..." systemctl daemon-reload systemctl enable hysteria-server systemctl start hysteria-server sleep 2 if systemctl is-active --quiet hysteria-server; then green "Служба Hysteria2 успешно запущена" else red "Ошибка запуска службы Hysteria2" systemctl status hysteria-server exit 1 fi } show_config() { if command -v qrencode &> /dev/null; then green "=== QR Code ===" qrencode -t ANSIUTF8 "$(cat /root/hysteria2.txt)" else yellow "Установите qrencode для генерации QR кода: apt install qrencode / yum install qrencode" fi } uninstall_hysteria() { red "Удаление Hysteria2..." systemctl stop hysteria-server 2>/dev/null || true systemctl disable hysteria-server 2>/dev/null || true rm -f /etc/systemd/system/hysteria-server.service rm -f /usr/local/bin/hysteria rm -rf /etc/hysteria rm -f /root/hysteria2.txt systemctl daemon-reload green "Hysteria2 полностью удален!" } check_hysteria_installed() { [[ -f "/usr/local/bin/hysteria" ]] } main() { if check_hysteria_installed; then red "Hysteria2 уже установлен!" echo read -p "Хотите переустановить? [y/N]: " reinstall case $reinstall in [yY]|[yY][eE][sS]) uninstall_hysteria ;; *) echo "Выход..." exit 0 ;; esac fi install_server_core configure_hysteria start_service show_config echo green "Установка Hysteria2 успешно завершена!" echo yellow "Конфиг клиента: /root/hysteria2.txt" yellow "Перезапуск службы: systemctl restart hysteria-server" yellow "Проверка статуса: systemctl status hysteria-server" echo yellow "Hysteria2 ключ:" cat /root/hysteria2.txt echo echo "Инструкции по настройке VPN приложений:" echo "https://github.com/YukiKras/wiki/blob/main/nastroikavpn.md" } main