Add interactive SSH port and UFW modes
This commit is contained in:
parent
138affaa54
commit
feaa85a39b
2 changed files with 141 additions and 8 deletions
21
README.md
21
README.md
|
|
@ -8,7 +8,7 @@
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `ochenstarik-server-1.sh` | Создаёт swap-файл 2 ГБ и задаёт `vm.swappiness=20` | Да |
|
| `ochenstarik-server-1.sh` | Создаёт swap-файл 2 ГБ и задаёт `vm.swappiness=20` | Да |
|
||||||
| `ochenstarik-server-2.sh` | Обновляет систему, ставит серверные и офисные пакеты, настраивает часовой пояс и UFW | Да |
|
| `ochenstarik-server-2.sh` | Обновляет систему, ставит серверные и офисные пакеты, настраивает часовой пояс и UFW | Да |
|
||||||
| `ochenstarik-server-user-3.sh` | Создаёт администратора, устанавливает SSH-ключ, переносит SSH на порт 20202, включает fail2ban | После установки необходимых пакетов; проще всего сначала запустить скрипт 2 |
|
| `ochenstarik-server-user-3.sh` | Создаёт администратора, позволяет выбрать SSH-порт, включает fail2ban или отдельно добавляет правила UFW | После установки необходимых пакетов; проще всего сначала запустить скрипт 2 |
|
||||||
| `ochenstarik-server-tg-4.sh` | Отправляет уведомления в Telegram при успешном входе по SSH | После установки OpenSSH и `curl`; обычно после скрипта 2 или 3 |
|
| `ochenstarik-server-tg-4.sh` | Отправляет уведомления в Telegram при успешном входе по SSH | После установки OpenSSH и `curl`; обычно после скрипта 2 или 3 |
|
||||||
| `ochenstarik-server-vpn-5.sh` | Устанавливает Xray и направляет системный трафик через VLESS + REALITY | Да; зависимости устанавливаются автоматически |
|
| `ochenstarik-server-vpn-5.sh` | Устанавливает Xray и направляет системный трафик через VLESS + REALITY | Да; зависимости устанавливаются автоматически |
|
||||||
|
|
||||||
|
|
@ -88,12 +88,17 @@ timedatectl
|
||||||
|
|
||||||
Файл: `ochenstarik-server-user-3.sh`.
|
Файл: `ochenstarik-server-user-3.sh`.
|
||||||
|
|
||||||
Скрипт интерактивно запрашивает имя нового администратора, SSH-ключ и пароль. Затем он:
|
При каждом запуске скрипт предлагает два режима:
|
||||||
|
|
||||||
|
1. новая установка или повторная настройка администратора и SSH;
|
||||||
|
2. только добавление открытых портов в UFW без изменения пользователя и SSH.
|
||||||
|
|
||||||
|
В режиме новой установки скрипт интерактивно запрашивает имя администратора, SSH-порт, SSH-ключ и пароль. Затем он:
|
||||||
|
|
||||||
- создаёт или обновляет пользователя;
|
- создаёт или обновляет пользователя;
|
||||||
- добавляет пользователя в группу `sudo`;
|
- добавляет пользователя в группу `sudo`;
|
||||||
- запрещает вход `root` по SSH;
|
- запрещает вход `root` по SSH;
|
||||||
- переносит SSH на порт `20202`;
|
- переносит SSH на выбранный порт и добавляет для него правило UFW;
|
||||||
- настраивает fail2ban;
|
- настраивает fail2ban;
|
||||||
- по выбору управляет правилами UFW.
|
- по выбору управляет правилами UFW.
|
||||||
|
|
||||||
|
|
@ -111,7 +116,7 @@ sudo ./ochenstarik-server-user-3.sh
|
||||||
Не закрывая текущую сессию, откройте второй терминал и проверьте вход:
|
Не закрывая текущую сессию, откройте второй терминал и проверьте вход:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh -p 20202 ИМЯ_ПОЛЬЗОВАТЕЛЯ@IP_СЕРВЕРА
|
ssh -p ВЫБРАННЫЙ_ПОРТ ИМЯ_ПОЛЬЗОВАТЕЛЯ@IP_СЕРВЕРА
|
||||||
```
|
```
|
||||||
|
|
||||||
Только после успешной проверки можно удалить временное правило порта 22:
|
Только после успешной проверки можно удалить временное правило порта 22:
|
||||||
|
|
@ -120,6 +125,14 @@ ssh -p 20202 ИМЯ_ПОЛЬЗОВАТЕЛЯ@IP_СЕРВЕРА
|
||||||
sudo ufw delete allow 22/tcp
|
sudo ufw delete allow 22/tcp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Чтобы позднее открыть дополнительные порты, повторно запустите скрипт, выберите пункт `2` и введите правила через пробел или запятую:
|
||||||
|
|
||||||
|
```text
|
||||||
|
80 443/tcp 53/udp 40000
|
||||||
|
```
|
||||||
|
|
||||||
|
Для записей без протокола используется TCP. Допустимы только порты от `1` до `65535`. Если UFW неактивен, правила будут сохранены, но скрипт не включит брандмауэр автоматически во избежание потери SSH-доступа.
|
||||||
|
|
||||||
## 4. Telegram-уведомления о входах по SSH
|
## 4. Telegram-уведомления о входах по SSH
|
||||||
|
|
||||||
Файл: `ochenstarik-server-tg-4.sh`.
|
Файл: `ochenstarik-server-tg-4.sh`.
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,102 @@ require_command() {
|
||||||
command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"
|
command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_valid_port() {
|
||||||
|
local port="$1"
|
||||||
|
[[ "$port" =~ ^[0-9]{1,5}$ ]] || return 1
|
||||||
|
(( 10#$port >= 1 && 10#$port <= 65535 ))
|
||||||
|
}
|
||||||
|
|
||||||
|
select_action() {
|
||||||
|
local choice
|
||||||
|
|
||||||
|
printf '\nSelect an action:\n'
|
||||||
|
printf ' 1 - new installation or reconfigure the administrative user and SSH\n'
|
||||||
|
printf ' 2 - add open ports to UFW without changing SSH or users\n'
|
||||||
|
while :; do
|
||||||
|
read -rp 'Select [1]: ' choice
|
||||||
|
choice="${choice:-1}"
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
ACTION="install"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
ACTION="add-ports"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warn "Select 1 or 2"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
add_ufw_ports_interactive() {
|
||||||
|
local input normalized token port protocol rule
|
||||||
|
local -a tokens rules
|
||||||
|
local -A seen
|
||||||
|
|
||||||
|
require_command ufw
|
||||||
|
printf '\nEnter one or more ports separated by spaces or commas.\n'
|
||||||
|
printf 'TCP is used by default; specify UDP explicitly when needed.\n'
|
||||||
|
printf 'Example: 80 443/tcp 53/udp 40000\n'
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
read -rp 'Ports to open: ' input
|
||||||
|
normalized="${input//,/ }"
|
||||||
|
read -r -a tokens <<< "$normalized"
|
||||||
|
rules=()
|
||||||
|
seen=()
|
||||||
|
|
||||||
|
if (( ${#tokens[@]} == 0 )); then
|
||||||
|
warn "Enter at least one port"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
for token in "${tokens[@]}"; do
|
||||||
|
if [[ ! "$token" =~ ^([0-9]+)(/(tcp|udp))?$ ]]; then
|
||||||
|
warn "Invalid rule: $token; use PORT, PORT/tcp or PORT/udp"
|
||||||
|
rules=()
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
port="${BASH_REMATCH[1]}"
|
||||||
|
protocol="${BASH_REMATCH[3]:-tcp}"
|
||||||
|
if ! is_valid_port "$port"; then
|
||||||
|
warn "Port must be between 1 and 65535: $port"
|
||||||
|
rules=()
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
port="$((10#$port))"
|
||||||
|
|
||||||
|
rule="${port}/${protocol}"
|
||||||
|
if [[ -z "${seen[$rule]:-}" ]]; then
|
||||||
|
rules+=("$rule")
|
||||||
|
seen["$rule"]=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
(( ${#rules[@]} > 0 )) && break
|
||||||
|
done
|
||||||
|
|
||||||
|
for rule in "${rules[@]}"; do
|
||||||
|
log "Allowing ${rule} in UFW"
|
||||||
|
ufw allow "$rule"
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! LANG=C ufw status | grep -q '^Status: active'; then
|
||||||
|
warn "UFW is inactive. Rules were added but the firewall was not enabled automatically."
|
||||||
|
warn "Review SSH access first, then enable it with: ufw enable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '\nCurrent UFW status:\n'
|
||||||
|
ufw status verbose
|
||||||
|
}
|
||||||
|
|
||||||
collect_user_configuration() {
|
collect_user_configuration() {
|
||||||
local new_username ssh_public_key pass pass2 candidate_uid
|
local new_username ssh_port default_ssh_port saved_ssh_port
|
||||||
|
local ssh_public_key pass pass2 candidate_uid
|
||||||
local key_method source_username source_home source_key_file candidate_key key_test
|
local key_method source_username source_home source_key_file candidate_key key_test
|
||||||
|
|
||||||
log "Collecting configuration for a new administrative user"
|
log "Collecting configuration for a new administrative user"
|
||||||
|
|
@ -79,6 +173,24 @@ collect_user_configuration() {
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
|
|
||||||
|
default_ssh_port="20202"
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
saved_ssh_port="$(read_env_value SSH_PORT)"
|
||||||
|
if is_valid_port "$saved_ssh_port"; then
|
||||||
|
default_ssh_port="$saved_ssh_port"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
read -rp "SSH port [${default_ssh_port}]: " ssh_port
|
||||||
|
ssh_port="${ssh_port:-$default_ssh_port}"
|
||||||
|
if is_valid_port "$ssh_port"; then
|
||||||
|
ssh_port="$((10#$ssh_port))"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
warn "SSH port must be a number between 1 and 65535"
|
||||||
|
done
|
||||||
|
|
||||||
while :; do
|
while :; do
|
||||||
printf '\nSSH key setup:\n'
|
printf '\nSSH key setup:\n'
|
||||||
printf ' 1 - copy a working key from an existing user (recommended)\n'
|
printf ' 1 - copy a working key from an existing user (recommended)\n'
|
||||||
|
|
@ -151,7 +263,7 @@ collect_user_configuration() {
|
||||||
printf '%s' "$pass" | openssl passwd -6 -stdin > "$HASH_FILE"
|
printf '%s' "$pass" | openssl passwd -6 -stdin > "$HASH_FILE"
|
||||||
cat > "$ENV_FILE" <<EOF
|
cat > "$ENV_FILE" <<EOF
|
||||||
NEW_USERNAME=${new_username}
|
NEW_USERNAME=${new_username}
|
||||||
SSH_PORT=20202
|
SSH_PORT=${ssh_port}
|
||||||
SSH_PUBLIC_KEY=${ssh_public_key}
|
SSH_PUBLIC_KEY=${ssh_public_key}
|
||||||
PASSWORD_AUTH=no
|
PASSWORD_AUTH=no
|
||||||
PASSWORDLESS_SUDO=no
|
PASSWORDLESS_SUDO=no
|
||||||
|
|
@ -161,6 +273,15 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ "$EUID" -eq 0 ]] || die "Run this script as root"
|
[[ "$EUID" -eq 0 ]] || die "Run this script as root"
|
||||||
|
ACTION=""
|
||||||
|
select_action
|
||||||
|
|
||||||
|
if [[ "$ACTION" == "add-ports" ]]; then
|
||||||
|
add_ufw_ports_interactive
|
||||||
|
printf '\nDone. SSH and user settings were not changed.\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
require_command openssl
|
require_command openssl
|
||||||
require_command ssh-keygen
|
require_command ssh-keygen
|
||||||
[[ ! -L "$ENV_FILE" && ! -L "$HASH_FILE" ]] || die "Configuration files must not be symbolic links"
|
[[ ! -L "$ENV_FILE" && ! -L "$HASH_FILE" ]] || die "Configuration files must not be symbolic links"
|
||||||
|
|
@ -196,8 +317,7 @@ if id "$NEW_USERNAME" >/dev/null 2>&1; then
|
||||||
existing_uid="$(id -u "$NEW_USERNAME")"
|
existing_uid="$(id -u "$NEW_USERNAME")"
|
||||||
(( existing_uid >= 1000 && existing_uid != 65534 )) || die "Refusing to modify a system account: $NEW_USERNAME"
|
(( existing_uid >= 1000 && existing_uid != 65534 )) || die "Refusing to modify a system account: $NEW_USERNAME"
|
||||||
fi
|
fi
|
||||||
[[ "$SSH_PORT" =~ ^[0-9]+$ ]] || die "SSH_PORT must be numeric"
|
is_valid_port "$SSH_PORT" || die "SSH_PORT must be between 1 and 65535"
|
||||||
(( 10#$SSH_PORT >= 1 && 10#$SSH_PORT <= 65535 )) || die "SSH_PORT must be between 1 and 65535"
|
|
||||||
validate_boolean PASSWORD_AUTH "$PASSWORD_AUTH"
|
validate_boolean PASSWORD_AUTH "$PASSWORD_AUTH"
|
||||||
validate_boolean PASSWORDLESS_SUDO "$PASSWORDLESS_SUDO"
|
validate_boolean PASSWORDLESS_SUDO "$PASSWORDLESS_SUDO"
|
||||||
validate_boolean MANAGE_UFW "$MANAGE_UFW"
|
validate_boolean MANAGE_UFW "$MANAGE_UFW"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue