Добавить install.sh
This commit is contained in:
508
install.sh
Normal file
508
install.sh
Normal file
@@ -0,0 +1,508 @@
|
|||||||
|
#!/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
|
||||||
Reference in New Issue
Block a user