Блок 13

Удалённый доступ: SSH и передача файлов

Linux: блок 13

> Что вас ждёт в этом блоке: вы впервые в курсе по-настоящему войдёте в другой компьютер через сеть — без клавиатуры и монитора у той машины, просто набрав команду в своём терминале. Именно так раб…

Обновлено: · DeeNet

Введение в блок

> Что вас ждёт в этом блоке: вы впервые в курсе по-настоящему войдёте в другой компьютер через сеть — без клавиатуры и монитора у той машины, просто набрав команду в своём терминале. Именно так работают системные администраторы с реальными серверами каждый день. Мы разберём протокол SSH от основ до продвинутых настроек, научимся копировать файлы между машинами тремя разными способами и настроим удобный конфиг для быстрого подключения.

>

> Что нужно знать перед началом: весь материал Блока 12 (IP-адреса, порты, DNS, сетевые команды). SSH — это сетевой протокол, работающий поверх всего, что мы там изучили: он использует IP-адрес для нахождения сервера, порт для обращения к нужной службе, и TCP для надёжной передачи данных.

Урок 13.1. Что такое SSH и зачем он нужен

Понять, зачем существует SSH, какую проблему он решает, как устроен «под капотом» на концептуальном уровне, и почему именно SSH стал стандартом де-факто для удалённого управления серверами во всём мире.

Теория

Представьте: вы арендовали сервер в дата-центре в другом городе (мы подробно поговорим об этом в Блоке 20). Там стоит компьютер с Ubuntu, работающий круглосуточно — но у него нет монитора, клавиатуры и мыши, подключённых физически. Как вы будете им управлять? Именно для этого и существует SSH.

SSH (Secure Shell, «безопасная оболочка») — это сетевой протокол и одновременно программа, которая позволяет безопасно управлять удалённым компьютером через терминал по сети. Ключевое слово здесь — безопасно.

Чтобы понять, почему безопасность принципиально важна, нужно сделать маленький исторический экскурс. До SSH администраторы использовали другие протоколы для удалённого доступа — прежде всего Telnet (существует с 1969 года). Telnet работал просто: вы подключались к удалённому компьютеру и вводили команды. Но у него была катастрофическая уязвимость: всё передавалось по сети в открытом виде, как обычный текст. Это означало, что любой, кто мог «прослушивать» сетевой трафик между вами и сервером (а это технически не так уж сложно в локальных сетях), мог видеть всё: ваш пароль, все команды, которые вы вводите, и все ответы сервера. В эпоху, когда серверы начали подключаться к интернету, это стало неприемлемым.

SSH создан в 1995 году финским программистом Тату Юлёненом именно как ответ на реальный инцидент: в его университетской сети кто-то запустил программу-сниффер (перехватчик трафика), которая собирала логины и пароли пользователей. Юлёнен понял, что нужен принципиально другой подход — протокол, при котором даже если злоумышленник перехватит весь передаваемый трафик, он не сможет ничего из него извлечь.

Как SSH решает проблему безопасности — криптография в двух словах.

SSH шифрует весь передаваемый трафик. Когда вы подключаетесь к серверу через SSH, происходит следующее:

  1. Установка соединения: клиент (ваш компьютер) и сервер «договариваются» об алгоритмах шифрования, которые будут использовать, и обмениваются специальными криптографическими данными для генерации общего секретного ключа сессии.
  2. Проверка подлинности сервера: ваш SSH-клиент проверяет, что вы подключаетесь именно к тому серверу, к которому намеревались, а не к машине злоумышленника, которая притворяется сервером (атака «человек посередине», man-in-the-middle). Для этого используется fingerprint (отпечаток) — уникальная криптографическая подпись сервера.
  3. Аутентификация пользователя: сервер проверяет, кто вы. Это можно делать двумя способами — паролем или SSH-ключами (урок 13.3 посвящён именно ключам).
  4. Шифрованный туннель: после успешной аутентификации все данные — ваши команды, ответы сервера, даже передаваемые файлы — передаются в зашифрованном виде. Перехватив трафик, злоумышленник увидит лишь бессмысленный набор байт.

Архитектура клиент-сервер. SSH работает по уже знакомой нам из Блока 12 (урок 12.5 про порты и службы) модели клиент-сервер:

Версии SSH. Существуют SSHv1 и SSHv2. Первая версия имела серьёзные криптографические уязвимости и сегодня считается устаревшей и небезопасной. Все современные системы используют исключительно SSHv2, и в этом курсе, говоря «SSH», мы всегда имеем в виду именно вторую версию.

Где применяется SSH на практике:

Практика

В этом вводном уроке мы не подключаемся к удалённым машинам (это будет в следующем уроке), а знакомимся с тем, что уже есть в вашей системе.

Шаг 1. Проверьте, установлен ли SSH-клиент в вашей системе:

```bash

ssh -V

```

Что вы увидите: строку вида OpenSSH_9.x, OpenSSL 3.x.x ... — версию установленного OpenSSH. Если команда не найдена, установите клиент: sudo apt install openssh-client.

[Скриншот терминала]

Шаг 2. Проверьте, установлен ли SSH-сервер (он нужен, чтобы другие могли подключаться к вашей машине; для практики следующего урока мы установим его явно):

```bash

dpkg -l | grep openssh

```

Что вы увидите: список установленных пакетов OpenSSH. Строка с openssh-client означает наличие клиента, строка с openssh-server — наличие сервера.

Шаг 3. Если SSH-сервер не установлен — установите его (он понадобится нам в следующем уроке для практики):

```bash

sudo apt install openssh-server

```

Что произойдёт: система установит пакет и автоматически запустит службу sshd. Можете убедиться в этом командой, знакомой из Блока 10:

```bash

sudo systemctl status ssh

```

Что вы увидите: строку Active: active (running) — служба работает.

[Скриншот терминала]

Шаг 4. Посмотрите, на каком порту слушает SSH-сервер (используем команду ss из урока 12.5, которую мы уже применяли для работы с портами):

```bash

sudo ss -tlnp | grep sshd

```

Что вы увидите: строку, подтверждающую, что процесс sshd слушает порт 22 (или другой, если сервер был ранее перенастроен).

[Скриншот терминала]

Разбор команд

Команда ssh -V

Команда dpkg -l | grep openssh

Команда sudo systemctl status ssh

Возможные ошибки

Почему возникает: пакет openssh-client не установлен (на минимальных серверных установках Ubuntu это возможно).

Как определить: запустить ssh — получить сообщение bash: ssh: command not found.

Как исправить: sudo apt install openssh-client.

Как избежать: на Ubuntu Desktop пакет обычно предустановлен; на Server-редакции может отсутствовать.

Почему возникает: чаще всего — конфликт портов (что-то другое уже занимает порт 22), реже — повреждённая установка.

Как определить: sudo systemctl status ssh покажет ошибку вместо active (running), а в логах (sudo journalctl -u ssh -n 30 — команда journalctl изучалась в Блоке 10) будет конкретная причина.

Как исправить: изучить сообщение об ошибке в логах и устранить причину; чаще всего достаточно sudo systemctl restart ssh.

Практические задания

  1. Найдите в уже изученном нами файле /etc/services (он упоминался в Блоке 12) строку, соответствующую SSH, и запишите в конспект, какой порт и протокол (TCP или UDP) там указан: grep -w ssh /etc/services.
  2. Прочитайте вывод команды ssh -V на своей системе и найдите в интернете информацию о том, какие криптографические алгоритмы поддерживает установленная у вас версия OpenSSH.
  3. Своими словами объясните в конспекте (не подглядывая), чем SSH принципиально отличается от Telnet, и почему этот протокол стал стандартом для удалённого управления серверами.

Проверка знаний

Вопрос 1. Что конкретно шифрует SSH при передаче данных по сети — только пароль при входе, или весь последующий трафик тоже?

Ответ: SSH шифрует весь передаваемый трафик целиком: и процесс аутентификации (включая пароль), и все команды, которые вы вводите, и все ответы сервера. После установки зашифрованного соединения ни одна передаваемая единица данных не проходит по сети в открытом виде.

Вопрос 2. Какие два компонента должны быть установлены на разных машинах, чтобы SSH-подключение стало возможным, и как называются соответствующие пакеты в Ubuntu?

Ответ: На машине, к которой подключаются (сервер), должен быть установлен и запущен SSH-сервер — пакет openssh-server (демон sshd, слушающий порт 22). На машине, с которой подключаются (клиент), должен быть установлен SSH-клиент — пакет openssh-client (команда ssh).

Итоги урока

Вы изучили: историю SSH и проблему, которую он решил (небезопасность Telnet), принцип шифрования трафика, архитектуру клиент-сервер, стандартный порт 22, пакеты openssh-client и openssh-server.

Вы умеете: проверить наличие и версию SSH-клиента и сервера, убедиться в работе службы sshd.

В следующем уроке потребуется: понимание того, что SSH-сервер должен быть запущен на машине, к которой мы подключаемся, — именно это вы настроили на шаге 3 практики.

Урок 13.2. Подключение к удалённому серверу: `ssh user@host`

Выполнить первое реальное SSH-подключение, понять синтаксис команды ssh, разобраться с процессом аутентификации, с тем, что такое known_hosts, и освоить типичные параметры команды.

Теория

Базовый синтаксис команды ssh:

```

ssh [опции] пользователь@хост

```

Здесь:

Что происходит при первом подключении к новому серверу.

Когда вы первый раз подключаетесь к какому-то серверу, SSH-клиент не знает этого сервера. Прежде чем установить соединение, он показывает вам нечто подобное:

```

The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.

ED25519 key fingerprint is SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdef.

This key is not known by any other names.

Are you sure you want to continue connecting (yes/no/[fingerprint])?

```

Это не ошибка — это важный механизм защиты. SSH-сервер имеет свой уникальный криптографический ключ (host key, «ключ хоста»), который и идентифицирует именно этот сервер. Клиент говорит вам: «Я вижу этот сервер впервые и не могу подтвердить его подлинность. Вот его отпечаток (fingerprint) — проверьте, тот ли это сервер, к которому вы хотите подключиться».

На практике при подключении к своей виртуальной машине или заведомо известному серверу вы просто вводите yes. Клиент сохраняет fingerprint сервера в файле ~/.ssh/known_hosts (в домашней папке вашего пользователя, в скрытой папке .ssh — о скрытых файлах и папках мы говорили в уроке 5.4). При всех последующих подключениях к тому же адресу SSH автоматически сверяет fingerprint с сохранённым — если он совпадает, всё в порядке. Если fingerprint изменился (например, на сервере была переустановлена ОС, что меняет его ключи), SSH выдаст серьёзное предупреждение — потому что это может означать атаку подмены сервера.

Что происходит после подтверждения.

После ввода yes SSH запрашивает пароль пользователя на удалённой машине. Важно: вводимые символы не отображаются — это стандартное поведение, которое мы уже видели в уроке 8.3 при работе с sudo. После правильного ввода пароля вы получаете приглашение командной строки удалённой машины — с этого момента все команды, которые вы набираете в своём терминале, выполняются на удалённой машине.

Как понять, на какой машине вы сейчас работаете. Приглашение командной строки изменится: вместо user@mycomputer:~$ вы увидите что-то вроде user@remoteserver:~$. Имя хоста (часть после @) — это имя той машины, на которой выполняются команды. Команды whoami и hostname (показывает имя текущей машины) мгновенно прояснят ситуацию.

Завершение SSH-сессии. Чтобы выйти из удалённой машины и вернуться в свой локальный терминал, используйте команду exit или нажмите Ctrl+D — оба способа закрывают SSH-сессию.

Практика на одной машине через loopback. Для практики этого урока вам не обязательно иметь вторую физическую машину. Вы можете подключиться к localhost (IP-адрес 127.0.0.1 — loopback-адрес, который мы изучали в уроке 12.5) — то есть ваша машина выступит одновременно и SSH-клиентом, и SSH-сервером. Это полностью реальный SSH, отличается только то, что клиент и сервер находятся на одном физическом компьютере.

Дополнительные параметры команды ssh, которые часто используются:

Практика

Для практики этого урока нам нужны два пользователя на одной машине (чтобы наглядно показать: вы входите не как «себя», а как другой пользователь). Создадим тестового пользователя.

Шаг 1. Убедитесь, что SSH-сервер запущен (мы делали это в предыдущем уроке):

```bash

sudo systemctl status ssh

```

Должен быть статус active (running). Если нет — sudo systemctl start ssh.

Шаг 2. Создайте тестового пользователя специально для практики SSH (команды useradd и passwd мы подробно изучили в уроке 8.4):

```bash

sudo useradd -m -s /bin/bash sshtest

sudo passwd sshtest

```

Введите простой запоминаемый тестовый пароль дважды, например TestPass123.

Шаг 3. Выполните SSH-подключение к localhost под именем тестового пользователя:

```bash

ssh sshtest@localhost

```

Что произойдёт: при первом подключении SSH спросит подтверждение fingerprint. Введите yes.

[Скриншот терминала с вопросом о fingerprint]

Шаг 4. После ввода пароля вы окажетесь в SSH-сессии. Обратите внимание на изменившееся приглашение командной строки — теперь там указано имя пользователя sshtest. Убедитесь в этом:

```bash

whoami

hostname

pwd

```

Что вы увидите: whoami вернёт sshtest (не ваш обычный пользователь!), hostname — имя вашей машины, pwd — домашнюю папку пользователя sshtest (/home/sshtest). Это наглядно демонстрирует, что SSH создаёт полноценный сеанс работы от имени другого пользователя.

[Скриншот терминала]

Шаг 5. Попробуйте несколько команд в SSH-сессии — они выполняются точно так же, как если бы вы сидели за этой машиной:

```bash

ls -la

echo "Я внутри SSH-сессии!"

date

```

Шаг 6. Посмотрите файл known_hosts, который SSH создал при первом подключении, перед тем как выйти из сессии (откройте второй терминал или сначала посмотрите, потом выйдите):

```bash

exit

```

Теперь вы вернулись в локальный терминал. Проверьте файл known_hosts:

```bash

cat ~/.ssh/known_hosts

```

Что вы увидите: строку с fingerprint сервера localhost, который SSH сохранил при первом подключении. При следующих подключениях к localhost SSH будет автоматически сверять fingerprint с этой записью.

[Скриншот файла known_hosts]

Шаг 7. Подключитесь снова, на этот раз указав порт явно (хотя 22 — это значение по умолчанию, так что результат тот же):

```bash

ssh -p 22 sshtest@localhost

```

На этот раз вопроса о fingerprint не будет — SSH уже «знает» этот сервер.

```bash

exit

```

Шаг 8. Удалите тестового пользователя после практики:

```bash

sudo userdel -r sshtest

```

Разбор команд

Команда ssh

Команда exit

Команда hostname

Возможные ошибки

Почему возникает: SSH-сервер не запущен на целевой машине, или запущен на другом порту, или заблокирован firewall.

Как определить: запустить ssh -v user@host для подробного вывода; проверить на сервере sudo systemctl status ssh и sudo ss -tlnp | grep sshd.

Как исправить: запустить SSH-сервер (sudo systemctl start ssh) или убедиться в правильности порта.

Как избежать: перед первым подключением к серверу убедиться, что там установлен и запущен openssh-server.

Почему возникает: сервер был переустановлен (что генерирует новые ключи), или вы подключаетесь к другой машине с тем же IP, или (в редких случаях!) реальная атака подмены сервера.

Как определить: SSH выводит предупреждение с красным текстом REMOTE HOST IDENTIFICATION HAS CHANGED! и указывает номер строки в файле ~/.ssh/known_hosts, которая конфликтует.

Как исправить: если вы точно знаете, что сервер был переустановлен (или изменился IP) — удалите конфликтующую строку из known_hosts: ssh-keygen -R хост_или_ip — и подключитесь снова, подтвердив новый fingerprint. Если причина смены fingerprint вам неизвестна — отнеситесь к этому серьёзно и выясните причину, прежде чем подтверждать.

Как избежать: при переустановке сервера заранее предупреждать себя (и коллег) о том, что fingerprint изменится.

Почему возникает: неправильный пароль, не тот пользователь, или аутентификация по паролю отключена в настройках SSH-сервера.

Как определить: убедиться, что вводите правильный пароль именно пользователя на удалённой машине. Запустить ssh -v user@host для диагностики.

Как исправить: проверить правильность имени пользователя и пароля. Если на сервере отключена аутентификация по паролю — нужно использовать SSH-ключи (следующий урок).

Практические задания

  1. Подключитесь к localhost под своим собственным именем пользователя (без @localhost — SSH использует текущее имя пользователя по умолчанию; просто ssh localhost), выполните команды whoami, uname -a и uptime в SSH-сессии, сделайте скриншот для конспекта, затем выйдите.
  2. Попробуйте выполнить одну команду на «сервере» без открытия интерактивного терминала: ssh ваш_пользователь@localhost 'ls /etc | head -10' — изучите, как это работает.
  3. Найдите файл ~/.ssh/known_hosts и изучите его содержимое: сколько записей там уже есть, что означает каждая колонка каждой строки.

Проверка знаний

Вопрос 1. Почему при первом подключении к новому серверу SSH показывает fingerprint и просит подтверждение — разве это не лишнее неудобство?

Ответ: Это важный механизм защиты от атаки «человек посередине» (man-in-the-middle). Файл known_hosts запоминает fingerprint каждого сервера. При следующих подключениях SSH автоматически проверяет, что fingerprint не изменился — это гарантирует, что вы подключаетесь именно к тому серверу, а не к машине злоумышленника, которая перехватила ваш запрос.

Вопрос 2. Вы подключились по SSH к серверу и хотите выяснить, что именно выполняет сервер прямо сейчас — как это сделать, не выходя из SSH-сессии?

Ответ: Находясь в SSH-сессии, можно использовать все уже изученные команды — например, top или htop (Блок 11) для просмотра активных процессов, df -h для состояния дисков (Блок 9), systemctl status для состояния служб (Блок 10). SSH предоставляет полноценный терминальный доступ, ничем не отличающийся от работы непосредственно за клавиатурой сервера.

Итоги урока

Вы изучили: синтаксис команды ssh, процесс первого подключения и fingerprint, файл known_hosts, важные параметры -p, -v, -i.

Вы умеете: подключаться к серверу (и к localhost) по SSH с аутентификацией по паролю, выполнять команды в SSH-сессии, корректно выходить из сессии.

В следующем уроке потребуется: понимание того, что SSH-соединение устанавливается успешно — следующий шаг замена аутентификации по паролю на значительно более безопасные SSH-ключи.

Урок 13.3. SSH-ключи: `ssh-keygen` и `ssh-copy-id`

Освоить аутентификацию по SSH-ключам — более безопасный и удобный способ входа на сервер, не требующий ввода пароля каждый раз и практически исключающий взлом перебором.

Теория

Мы уже умеем входить на сервер по паролю. Почему этого недостаточно и зачем нужны ключи?

Проблемы аутентификации по паролю:

  1. Уязвимость к перебору (brute force). Злоумышленник может написать программу, которая будет перебирать тысячи паролей в секунду, пытаясь угадать ваш. Слабые пароли (и даже многие «средние») могут быть подобраны так.
  2. Неудобство. При каждом подключении нужно вводить пароль — это утомительно, если вы подключаетесь к серверам десятки раз в день, как это делают реальные администраторы.
  3. Опасность подбора. Если сервер доступен из интернета, на порту 22 постоянно идут автоматические попытки подключения — это можно увидеть в логах реального сервера. Боты сканируют весь диапазон IP-адресов и пробуют стандартные пароли.

SSH-ключи решают все эти проблемы. Они основаны на асимметричной криптографии — математическом принципе, при котором генерируются два связанных ключа:

Как работает аутентификация по ключам (упрощённо):

  1. Вы инициируете подключение к серверу.
  2. Сервер проверяет, есть ли в файле ~/.ssh/authorized_keys публичный ключ, соответствующий тому, что предъявляет клиент.
  3. Сервер отправляет клиенту случайное «задание» (challenge), зашифрованное вашим публичным ключом.
  4. Только тот, у кого есть соответствующий приватный ключ, может расшифровать это задание и дать правильный ответ.
  5. Клиент расшифровывает задание приватным ключом и отправляет ответ.
  6. Сервер проверяет ответ — если всё верно, вы вошли, без ввода пароля.

Суть: приватный ключ никогда не покидает вашу машину. Взломать такую аутентификацию перебором практически невозможно — математически это потребовало бы вычислительных ресурсов, которых не существует.

Типы ключей. SSH поддерживает несколько криптографических алгоритмов для ключей:

Passphrase — ещё один уровень защиты. При создании ключа SSH предлагает установить passphrase (кодовую фразу) — это пароль, которым зашифрован сам файл приватного ключа на вашем диске. Если злоумышленник получит файл вашего приватного ключа (например, украдёт ноутбук), он всё равно не сможет его использовать без passphrase. Для учебных ключей passphrase можно не устанавливать (нажать Enter дважды), но для реальных рабочих ключей она настоятельно рекомендуется.

Где хранятся ключи. По умолчанию всё, связанное с SSH, хранится в папке ~/.ssh/ (в домашней папке текущего пользователя):

Команда ssh-keygen генерирует пару ключей (приватный + публичный).

Команда ssh-copy-id копирует ваш публичный ключ на сервер, добавляя его в файл ~/.ssh/authorized_keys нужного пользователя. Это удобная утилита, которая автоматически делает то, что иначе пришлось бы делать вручную.

Практика

Шаг 1. Создайте тестового пользователя для практики:

```bash

sudo useradd -m -s /bin/bash sshkeytest

sudo passwd sshkeytest

```

Шаг 2. Сгенерируйте пару SSH-ключей типа Ed25519:

```bash

ssh-keygen -t ed25519 -C "учебный ключ для курса Linux"

```

Что произойдёт: команда задаст три вопроса:

  1. Enter file in which to save the key (/home/ваш_пользователь/.ssh/id_ed25519): — путь для сохранения ключа. Нажмите Enter, чтобы принять путь по умолчанию.
  2. Enter passphrase (empty for no passphrase): — кодовая фраза. Для этого учебного ключа нажмите Enter (без passphrase), чтобы упростить практику.
  3. Enter same passphrase again: — подтверждение. Снова Enter.

Что вы увидите: характерный «рисунок» из символов — визуализация fingerprint нового ключа (это просто красивое представление, не несёт функциональной нагрузки), а также строки с путями к созданным файлам.

[Скриншот терминала]

Шаг 3. Убедитесь, что ключи созданы:

```bash

ls -la ~/.ssh/

```

Что вы увидите: как минимум файлы id_ed25519 (приватный ключ, права 600) и id_ed25519.pub (публичный ключ, права 644). Обратите особое внимание на права доступа — SSH намеренно делает приватный ключ нечитаемым для других пользователей.

Шаг 4. Посмотрите на публичный ключ (его можно свободно показывать — это не секрет):

```bash

cat ~/.ssh/id_ed25519.pub

```

Что вы увидите: одну длинную строку вида ssh-ed25519 AAAA...длинный набор символов... учебный ключ для курса Linux. Именно эту строку нужно добавлять в ~/.ssh/authorized_keys на серверах.

[Скриншот публичного ключа]

Шаг 5. Скопируйте публичный ключ на «сервер» (в нашем случае — для пользователя sshkeytest на localhost):

```bash

ssh-copy-id sshkeytest@localhost

```

Что произойдёт: ssh-copy-id спросит пароль пользователя sshkeytest (последний раз — после этого пароль больше не понадобится!) и добавит ваш публичный ключ в файл /home/sshkeytest/.ssh/authorized_keys.

Что вы увидите: сообщение вида Number of key(s) added: 1 и инструкцию, как теперь подключиться.

[Скриншот результата ssh-copy-id]

Шаг 6. Теперь подключитесь по SSH — на этот раз без ввода пароля:

```bash

ssh sshkeytest@localhost

```

Что вы увидите: немедленный вход без запроса пароля! Именно это и делает ключевую аутентификацию такой удобной при частых подключениях.

```bash

whoami

exit

```

[Скриншот беспарольного входа]

Шаг 7. Убедитесь, что произошло «под капотом» — посмотрите файл authorized_keys на стороне «сервера»:

```bash

sudo cat /home/sshkeytest/.ssh/authorized_keys

```

Что вы увидите: ту самую строку вашего публичного ключа, которую ssh-copy-id туда положила.

Шаг 8. Очистите тестовое окружение:

```bash

sudo userdel -r sshkeytest

```

Разбор команд

Команда ssh-keygen

Команда ssh-copy-id

Возможные ошибки

Почему возникает: неправильные права доступа на папку ~/.ssh или файл authorized_keys на сервере (SSH намеренно игнорирует ключи с неправильными правами — это мера безопасности).

Как определить: запустить ssh -v user@host — в подробном выводе будет видно, что SSH пробует ключ, но сервер его отклоняет; проверить права на сервере: ls -la ~/.ssh/.

Как исправить: установить правильные права:

```bash

chmod 700 ~/.ssh

chmod 600 ~/.ssh/authorized_keys

```

Как избежать: использовать ssh-copy-id (она устанавливает правильные права автоматически) вместо ручного копирования ключа.

Почему возникает: невнимательность при ответе на вопрос подтверждения перезаписи.

Как определить: после этой ошибки вы больше не можете войти на серверы, где был зарегистрирован старый ключ — только если у вас есть доступ по паролю или другой ключ.

Как исправить: если доступ по паролю сохранён — войти по паролю и добавить новый публичный ключ в authorized_keys; если доступ полностью утерян — потребуется «аварийный» доступ к серверу через консоль провайдера (это ситуация, которую важно предотвращать превентивно).

Как избежать: хранить резервные копии пары ключей в безопасном месте (например, зашифрованном хранилище паролей); никогда не генерировать новый ключ, не убедившись, что старый больше не нужен или уже сохранён.

Практические задания

  1. Создайте второй SSH-ключ, но уже RSA типа с длиной 4096 бит и нестандартным именем файла (-f ~/.ssh/id_rsa_test). Сравните размер файлов приватных ключей Ed25519 и RSA командой ls -la ~/.ssh/.
  2. Вручную (без ssh-copy-id) добавьте свой публичный ключ в файл ~/.ssh/authorized_keys для своего же пользователя (создайте файл, если он не существует), соблюдая правильные права доступа — и проверьте, что можете войти ssh localhost без пароля.
  3. Изучите содержимое приватного ключа ~/.ssh/id_ed25519 — посмотрите его структуру (cat ~/.ssh/id_ed25519), убедитесь, что начинается с -----BEGIN OPENSSH PRIVATE KEY-----. Объясните в конспекте, почему этот файл нельзя передавать кому-либо ни при каких обстоятельствах.

Проверка знаний

Вопрос 1. Почему аутентификация по SSH-ключам считается безопаснее аутентификации по паролю?

Ответ: Потому что приватный ключ практически невозможно «угадать» перебором (его математическая сложность многократно превышает любой пароль), он никогда не передаётся по сети (только результат криптографической операции), и даже если злоумышленник перехватит весь трафик SSH-сессии — он не получит ничего полезного для воспроизведения аутентификации.

Вопрос 2. Зачем нужна passphrase для приватного ключа, если ключевая аутентификация и так безопаснее парольной?

Ответ: Passphrase шифрует сам файл приватного ключа на диске. Без неё, если злоумышленник физически получит доступ к вашему компьютеру и скопирует файл приватного ключа — он сможет использовать его для входа на все ваши серверы. С passphrase файл ключа без знания фразы бесполезен. Это дополнительный уровень защиты на случай компрометации вашего локального устройства.

Итоги урока

Вы изучили: принцип асимметричной криптографии применительно к SSH, типы ключей (Ed25519, RSA), назначение passphrase, структуру папки ~/.ssh/, файл authorized_keys.

Вы умеете: генерировать SSH-ключи командой ssh-keygen, копировать публичный ключ на сервер через ssh-copy-id, входить на сервер без пароля.

В следующем уроке потребуется: наличие рабочей пары SSH-ключей — в следующем уроке мы настроим удобный файл конфигурации, чтобы не вводить длинные команды подключения каждый раз.

Урок 13.4. Файл конфигурации `~/.ssh/config`

Научиться использовать файл ~/.ssh/config для создания коротких псевдонимов серверов, хранения параметров подключения и значительного упрощения повседневной работы с SSH.

Теория

Представьте, что вы администрируете несколько серверов. Каждый раз набирать что-то вроде:

```bash

ssh -p 2222 -i ~/.ssh/id_rsa_production admin@203.0.113.42

```

— утомительно и легко ошибиться. Именно для решения этой проблемы существует файл ~/.ssh/config.

~/.ssh/config — текстовый файл конфигурации SSH-клиента, находящийся в папке ~/.ssh/ в домашней папке текущего пользователя. В нём можно задать параметры подключения для конкретных серверов (или групп серверов) и назначить им короткие псевдонимы.

Базовая структура файла:

```

Host псевдоним

HostName адрес_или_имя_сервера

User имя_пользователя

Port порт

IdentityFile путь/к/приватному/ключу

```

После этого вместо длинной команды вы просто пишете:

```bash

ssh псевдоним

```

SSH-клиент сам подставит все нужные параметры из конфига.

Ключевые директивы файла конфигурации:

*Секция Host — настройки для всех подключений.* Если использовать Host (звёздочка — это шаблон, означающий «любой хост»), то настройки в этой секции применяются ко всем SSH-подключениям. Это удобно для глобальных настроек, например ServerAliveInterval.

Важно: порядок секций имеет значение. SSH-клиент читает конфиг сверху вниз и использует первое найденное значение для каждого параметра. Более специфичные правила (для конкретного хоста) должны стоять раньше более общих (например, Host *).

Права доступа к файлу конфигурации. Файл ~/.ssh/config должен иметь права 600 (только владелец может читать и писать) — в противном случае SSH откажется его использовать с ошибкой Bad owner or permissions on ~/.ssh/config.

Практика

Шаг 1. Убедитесь, что папка ~/.ssh/ существует (она должна была создаться в предыдущем уроке при генерации ключей):

```bash

ls -la ~/.ssh/

```

Шаг 2. Создайте файл конфигурации (или откройте существующий, если он есть) с помощью редактора nano (мы подробно изучали его в Блоке 7):

```bash

nano ~/.ssh/config

```

Шаг 3. Введите следующее содержимое (адаптируйте под свою систему):

```

Host local

HostName localhost

User ваш_пользователь

Port 22

IdentityFile ~/.ssh/id_ed25519

Host *

ServerAliveInterval 60

ServerAliveCountMax 3

```

Замените ваш_пользователь на ваше реальное имя пользователя в системе (результат команды whoami).

Сохраните файл: Ctrl+O, Enter, Ctrl+X.

Шаг 4. Установите правильные права доступа на файл конфигурации:

```bash

chmod 600 ~/.ssh/config

```

Проверьте:

```bash

ls -la ~/.ssh/config

```

Что вы увидите: -rw------- в начале строки — права 600.

[Скриншот терминала]

Шаг 5. Теперь подключитесь к localhost, используя только псевдоним из конфига:

```bash

ssh local

```

Что произойдёт: SSH прочитает конфиг, найдёт секцию Host local, подставит все параметры и подключится к localhost с нужным пользователем и ключом — всё автоматически.

```bash

whoami

hostname

exit

```

[Скриншот успешного подключения по псевдониму]

Шаг 6. Добавьте ещё одну секцию в конфиг — на этот раз с нестандартным портом (сымитируем ситуацию, когда SSH на сервере перенесён на порт 2222):

```bash

nano ~/.ssh/config

```

Добавьте перед секцией Host *:

```

Host localtest2222

HostName localhost

User ваш_пользователь

Port 2222

IdentityFile ~/.ssh/id_ed25519

```

Сохраните.

Шаг 7. Просмотрите итоговый файл конфигурации:

```bash

cat ~/.ssh/config

```

[Скриншот файла конфигурации]

Шаг 8. Попробуйте использовать функцию автодополнения Tab с псевдонимами из конфига — в современных системах bash дополняет имена хостов из ~/.ssh/config. Наберите ssh lo и нажмите Tab.

Разбор команд

Файл ~/.ssh/config — директивы

Это не команда, а конфигурационный файл. Рассмотрим основные директивы подробнее:

Приоритет настроек:

  1. Опции командной строки (высший приоритет).
  2. Файл ~/.ssh/config (пользовательский).
  3. Файл /etc/ssh/ssh_config (системный, для всех пользователей).

Возможные ошибки

Почему возникает: права на файл ~/.ssh/config не равны 600 (например, 644 — читать могут другие пользователи, что SSH считает небезопасным).

Как определить: при попытке подключиться SSH выводит это сообщение.

Как исправить: chmod 600 ~/.ssh/config.

Как избежать: после создания файла конфигурации сразу выполнять chmod 600 ~/.ssh/config.

Почему возникает: чаще всего — опечатка или неправильный отступ в файле (директивы внутри секции Host должны иметь отступ — пробел или Tab в начале строки; без отступа SSH воспринимает строку как начало новой «глобальной» директивы или нераспознанную строку).

Как определить: проверить файл внимательно, сравнить с примером выше. Можно запустить ssh -v псевдоним — в подробном выводе будет видно, какие параметры были применены из конфига.

Как исправить: исправить синтаксис файла (убедиться в наличии отступов у всех директив внутри секций Host).

Почему возникает: некоторые версии bash или конфигурации системы не включают автодополнение для SSH-хостов по умолчанию.

Как исправить: это несущественная проблема, которую можно решить установкой дополнительных пакетов для автодополнения (bash-completion). Псевдоним при этом всё равно работает при полном наборе.

Практические задания

  1. Добавьте в файл ~/.ssh/config секцию Host * с директивами ServerAliveInterval 60 и ServerAliveCountMax 3, если вы ещё не сделали этого в практике урока. Объясните в конспекте, что именно эти настройки делают.
  2. Создайте в конфиге псевдоним для подключения к localhost под другим именем пользователя (сначала создайте тестового пользователя, добавьте свой публичный ключ в его authorized_keys, опишите подключение в конфиге, проверьте что псевдоним работает, затем удалите тестового пользователя).
  3. Изучите системный файл /etc/ssh/ssh_config (это конфигурация клиента для всей системы, в отличие от пользовательского ~/.ssh/config): cat /etc/ssh/ssh_config — запишите в конспект три директивы, которые там присутствуют, и объясните, что они означают.

Проверка знаний

Вопрос 1. Почему SSH отказывается использовать файл ~/.ssh/config с правами 644, но принимает тот же файл с правами 600?

Ответ: Права 644 означают, что файл могут читать другие пользователи системы. Файл конфигурации SSH может содержать пути к приватным ключам и другую чувствительную информацию — если другие пользователи смогут его прочитать, это нарушит безопасность. Права 600 гарантируют, что файл доступен только владельцу, что SSH считает минимально приемлемым уровнем безопасности.

Вопрос 2. Если в файле ~/.ssh/config две секции — Host myserver с Port 2222 и Host * с Port 22 — какой порт будет использован при подключении командой ssh myserver?

Ответ: Порт 2222, из секции Host myserver. SSH читает конфиг сверху вниз и использует первое найденное значение для каждого параметра. Секция Host myserver стоит раньше Host *, поэтому её значение Port 2222 будет найдено первым и применено.

Итоги урока

Вы изучили: структуру файла ~/.ssh/config, основные директивы (Host, HostName, User, Port, IdentityFile, ServerAliveInterval), порядок приоритета настроек.

Вы умеете: создавать псевдонимы для серверов в конфиге SSH, подключаться одним коротким словом вместо длинной команды, настраивать глобальные параметры для всех подключений.

В следующем уроке потребуется: всё, что вы знаете об SSH — теперь мы начнём использовать его не просто для входа в терминал, но и для передачи файлов.

Урок 13.5. Копирование файлов: `scp`

Освоить команду scp (Secure Copy) — простейший способ скопировать файл с одной машины на другую через SSH-соединение.

Теория

Войти на сервер через SSH — это хорошо, но часто нужно не только работать в терминале, но и перемещать файлы между машинами: загрузить конфигурационный файл на сервер, скачать с сервера лог-файл для анализа, скопировать резервную копию с одного сервера на другой.

scp (Secure Copy Protocol, «протокол защищённого копирования») — это команда, которая копирует файлы между локальным и удалённым компьютером (или между двумя удалёнными компьютерами) через уже знакомый нам зашифрованный SSH-протокол. Это, по сути, команда cp (которую мы изучали в уроке 5.5), расширенная для работы через сеть.

Синтаксис scp для основных случаев:

```

scp локальный_файл пользователь@хост:/путь/на/сервере/

scp пользователь@хост:/путь/на/сервере/файл /локальный/путь/

scp пользователь1@хост1:/путь/к/файлу пользователь2@хост2:/путь/назначения/

```

Запись пользователь@хост:/путь — это «адрес» файла на удалённой машине, аналогичный URL. Двоеточие : разделяет адрес сервера и путь на нём.

Важные особенности scp:

Когда использовать scp vs. другие способы:

Заметка о будущем scp. В последних версиях OpenSSH (начиная с версии 9.0) scp по умолчанию использует протокол SFTP «под капотом», а не оригинальный SCP-протокол. Это техническая деталь, которая не меняет синтаксис и поведение команды для пользователя, но улучшает безопасность и совместимость.

Практика

Для практики создадим тестовые файлы и попрактикуемся в их копировании через localhost.

Шаг 1. Создайте несколько тестовых файлов для практики:

```bash

mkdir -p ~/scp_test/source

echo "Содержимое тестового файла 1" > ~/scp_test/source/file1.txt

echo "Содержимое тестового файла 2" > ~/scp_test/source/file2.txt

mkdir ~/scp_test/source/subdir

echo "Файл в подпапке" > ~/scp_test/source/subdir/file3.txt

ls -R ~/scp_test/source/

```

Шаг 2. Скопируйте один файл с «локальной» машины на «удалённую» (в нашем случае оба конца — localhost, но принцип тот же):

```bash

scp ~/scp_test/source/file1.txt ваш_пользователь@localhost:/tmp/

```

Что произойдёт: scp установит SSH-соединение (используя ключ из ~/.ssh/config или запросив пароль) и скопирует файл. Вы увидите прогресс: имя файла, прогресс-бар, скорость и время.

```

file1.txt 100% 32 0.5KB/s 00:00

```

[Скриншот терминала с выводом scp]

Шаг 3. Убедитесь, что файл появился на «сервере»:

```bash

ls -la /tmp/file1.txt

cat /tmp/file1.txt

```

Шаг 4. Скопируйте файл с «удалённой» машины на «локальную» (обратное направление) — скачайте файл с сервера:

```bash

mkdir ~/scp_test/destination

scp ваш_пользователь@localhost:/tmp/file1.txt ~/scp_test/destination/downloaded_file1.txt

```

Что произойдёт: файл /tmp/file1.txt с «сервера» скопируется в ~/scp_test/destination/downloaded_file1.txt на локальной машине с новым именем.

```bash

cat ~/scp_test/destination/downloaded_file1.txt

```

[Скриншот результата]

Шаг 5. Скопируйте папку целиком с помощью параметра -r:

```bash

scp -r ~/scp_test/source/ ваш_пользователь@localhost:/tmp/scp_source_copy/

```

Что произойдёт: скопируется вся папка source со всем содержимым, включая подпапки.

```bash

ls -R /tmp/scp_source_copy/

```

Шаг 6. Скопируйте сразу несколько файлов за один вызов:

```bash

scp ~/scp_test/source/file1.txt ~/scp_test/source/file2.txt ваш_пользователь@localhost:/tmp/

```

Шаг 7. Используйте псевдоним из ~/.ssh/config (если вы настроили его в предыдущем уроке):

```bash

scp ~/scp_test/source/file2.txt local:/tmp/

```

Что вы видите: scp поддерживает псевдонимы из ~/.ssh/config — так же как ssh.

Шаг 8. Очистите тестовые данные:

```bash

rm -r ~/scp_test

rm /tmp/file1.txt /tmp/file2.txt

rm -r /tmp/scp_source_copy/

```

Разбор команд

Команда scp

Возможные ошибки

Почему возникает: пользователь, под которым установлено SSH-соединение, не имеет прав записи в указанную директорию.

Как определить: сообщение об ошибке явно содержит Permission denied.

Как исправить: выбрать другую директорию (например, /tmp/ или домашнюю папку пользователя), или войти по SSH на сервер и создать директорию с нужными правами.

Как избежать: проверять права доступа на директорию назначения перед копированием.

Почему возникает: неправильный путь, или промежуточные директории не существуют.

Как определить: сообщение явно говорит об отсутствии пути.

Как исправить: войти по SSH, создать необходимые директории командой mkdir -p.

Как избежать: убедиться в правильности пути, предварительно просмотрев его через SSH.

Практические задания

  1. Напишите команду scp, которая скопирует весь каталог ~/.ssh/ с одного хоста на другой (подсказка: понадобится параметр для рекурсии), но не выполняйте её — просто запишите и объясните в конспекте, что именно она сделает и почему в реальной жизни копировать приватные ключи по сети было бы опасной практикой.
  2. Ограничьте скорость передачи при копировании файла до 100 Кбит/с (-l 100) и сравните время с копированием без ограничения — когда эта опция была бы полезна на практике?
  3. Используя scp, скопируйте системный файл /etc/hosts с «сервера» (localhost) в свою домашнюю папку под именем hosts_backup.txt. Изучите его содержимое и объясните в конспекте, что означают строки в этом файле (мы говорили о нём в уроке 12.4).

Проверка знаний

Вопрос 1. Чем scp принципиально отличается от обычной команды cp, изученной в уроке 5.5?

Ответ: cp копирует файлы в пределах одной машины. scp копирует файлы между разными машинами по сети, используя зашифрованное SSH-соединение. В остальном логика использования схожа: указываешь источник и назначение, для рекурсивного копирования папок добавляешь -r.

Вопрос 2. Почему при указании нестандартного порта в scp используется заглавная -P, а не строчная -p как в команде ssh?

Ответ: Это историческая несовместимость: в scp строчная -p уже была «занята» другим значением (preserve — сохранение временных меток и прав файлов). Когда добавляли опцию порта, пришлось использовать заглавную букву. Это частая ловушка при работе с инструментами SSH, которую важно запомнить.

Итоги урока

Вы изучили: синтаксис scp для копирования файлов в обоих направлениях (локальная→удалённая и удалённая→локальная), параметры -r, -P, -C, -l, особенность заглавной -P для порта.

Вы умеете: копировать файлы и папки через сеть одной командой, ограничивать скорость передачи, использовать псевдонимы из ~/.ssh/config.

В следующем уроке потребуется: понимание того, что SSH используется для передачи файлов — в следующем уроке рассмотрим более интерактивный способ работы с файлами на удалённой машине через SFTP.

Урок 13.6. Интерактивная работа с файлами: `sftp`

Освоить sftp — интерактивный файловый клиент для работы с удалённой машиной в режиме диалога, аналог FTP, но полностью безопасный.

Теория

sftp (SSH File Transfer Protocol, «протокол передачи файлов через SSH») — это интерактивный инструмент для работы с файлами на удалённой машине. В отличие от scp, который работает как одна команда (указал источник, назначение, нажал Enter — файл скопирован), sftp открывает интерактивный сеанс, в котором вы можете перемещаться по директориям, просматривать содержимое папок, скачивать и загружать несколько файлов по очереди — примерно так же, как файловый менеджер, но в терминале.

Аналогия с обычным FTP. Если вы когда-либо пользовались FTP-клиентами (FileZilla, WinSCP) — sftp работает по той же логике, но полностью зашифрован, используя SSH «под капотом». Буква «s» в начале означает именно это: Secure (защищённый) FTP. Важно не путать: SFTP — это совсем другой протокол, чем FTPS (FTP с SSL-шифрованием); они похожи по назначению, но технически устроены по-разному.

Команды внутри SFTP-сессии делятся на две группы:

Чтобы выйти из SFTP-сессии: exit или quit или Ctrl+D.

Когда sftp удобнее scp:

Когда scp или rsync лучше sftp:

Практика

Шаг 1. Создайте тестовые файлы для практики:

```bash

mkdir -p ~/sftp_test

echo "Файл для загрузки на сервер" > ~/sftp_test/upload_me.txt

echo "Ещё один файл" > ~/sftp_test/another.txt

```

Шаг 2. Запустите SFTP-сессию к localhost:

```bash

sftp ваш_пользователь@localhost

```

Что вы увидите: после успешного подключения появится приглашение sftp> вместо привычного $. Это означает, что вы внутри SFTP-сессии.

[Скриншот приглашения sftp>]

Шаг 3. Изучите состояние и навигацию по удалённой машине:

```

sftp> pwd

sftp> ls

sftp> ls -la

sftp> cd /tmp

sftp> pwd

sftp> ls

```

Что вы увидите: команды работают так же, как в обычном терминале, но выполняются на удалённой стороне. pwd покажет текущую директорию на сервере.

[Скриншот навигации]

Шаг 4. Проверьте текущую директорию на локальной машине (используем l-префикс):

```

sftp> lpwd

sftp> lls

sftp> lcd ~/sftp_test

sftp> lpwd

sftp> lls

```

Что вы увидите: lpwd и lls работают с вашей локальной машиной — вы видите локальные пути и файлы, не выходя из SFTP-сессии.

Шаг 5. Загрузите файл на удалённую машину (команда put):

```

sftp> cd /tmp

sftp> put upload_me.txt

sftp> ls

```

Что произойдёт: файл upload_me.txt из текущей локальной директории (мы перешли туда через lcd на шаге 4) загрузится в текущую удалённую директорию (/tmp).

[Скриншот загрузки файла]

Шаг 6. Скачайте файл с удалённой машины (команда get):

```

sftp> get /etc/os-release

sftp> lls

```

Что произойдёт: файл /etc/os-release с «сервера» скачается в текущую локальную директорию (~/sftp_test). Команда lls покажет, что он там появился.

Шаг 7. Загрузите несколько файлов сразу с помощью mput:

```

sftp> mput ~/sftp_test/*.txt

```

Что произойдёт: все файлы .txt из указанной локальной папки загрузятся на сервер в текущую удалённую директорию.

Шаг 8. Создайте папку на удалённой машине прямо из SFTP-сессии:

```

sftp> mkdir /tmp/sftp_uploads

sftp> ls /tmp/

```

Шаг 9. Выйдите из SFTP-сессии:

```

sftp> exit

```

Что вы увидите: возврат в обычную командную строку.

[Скриншот выхода из sftp]

Шаг 10. Очистите тестовые данные:

```bash

rm -r ~/sftp_test

rm /tmp/upload_me.txt /tmp/another.txt

rmdir /tmp/sftp_uploads

```

Разбор команд

Команда sftp

Команды внутри SFTP-сессии (полный список основных):

| Команда | Действие |

|---|---|

| pwd | Текущая директория на сервере |

| lpwd | Текущая директория на локальной машине |

| ls [путь] | Список файлов на сервере |

| lls [путь] | Список файлов локально |

| cd путь | Перейти в директорию на сервере |

| lcd путь | Перейти в директорию локально |

| mkdir путь | Создать директорию на сервере |

| rmdir путь | Удалить директорию на сервере |

| rm файл | Удалить файл на сервере |

| rename старое новое | Переименовать файл на сервере |

| get удал. [лок.] | Скачать файл с сервера |

| put лок. [удал.] | Загрузить файл на сервер |

| mget шаблон | Скачать несколько файлов |

| mput шаблон | Загрузить несколько файлов |

| exit / quit | Выйти из сессии |

| help | Показать справку по командам |

Возможные ошибки

Почему возникает: попытка скачать файл, на чтение которого у вашего пользователя нет прав (вспомните урок 8.6 про права доступа и особый статус файла /etc/shadow).

Как определить: явное сообщение Permission denied.

Как исправить: скачать файл можно только если у вас достаточно прав (root или специальные права). Для большинства системных файлов это невозможно без sudo, а SFTP не поддерживает sudo внутри сессии. Если доступ нужен — войти по SSH и использовать sudo cp файл /tmp/, затем скачать через SFTP из /tmp/.

Почему возникает: в SFTP шаблоны раскрываются иначе, чем в bash — в некоторых ситуациях может потребоваться правильно экранировать или настроить поведение.

Как исправить: попробовать mget "*.log", или вручную указать нужные файлы через несколько команд get.

Практические задания

  1. Запустите SFTP-сессию к localhost и скачайте файл /etc/hostname на локальную машину. Затем прямо в SFTP-сессии создайте директорию /tmp/my_sftp_dir и загрузите в неё любой локальный файл из вашей домашней папки. Выйдите из сессии и проверьте результат.
  2. Используя SFTP-команду help внутри сессии, изучите полный список доступных команд. Найдите три команды, которые мы не рассматривали в уроке, и объясните в конспекте их назначение.
  3. Объясните в конспекте сценарий, когда SFTP удобнее, чем scp: например, вам нужно «обследовать» незнакомый сервер, найти нужные конфигурационные файлы и скачать несколько из них — опишите последовательность действий.

Проверка знаний

Вопрос 1. Как в SFTP-сессии узнать, в какой директории вы сейчас находитесь на локальной машине, не выходя из сессии?

Ответ: Командой lpwd (local pwd, «локальный pwd»). В SFTP-сессии команды с префиксом l выполняются на локальной машине: lpwd — текущая локальная директория, lls — список файлов в ней, lcd путь — сменить локальную директорию.

Вопрос 2. В чём принципиальное отличие sftp от scp с точки зрения использования?

Ответ: scp — это одна не-интерактивная команда: вы указываете источник и назначение, она копирует и завершается. sftp — это интерактивный сеанс, в котором вы можете «ходить» по директориям сервера командами cd/ls, просматривать файлы, и выполнять несколько операций загрузки/скачивания последовательно, не завершая сеанс между ними.

Итоги урока

Вы изучили: что такое SFTP, чем отличается от SCP и FTP, все основные команды внутри SFTP-сессии (включая l-префиксные команды для локальной машины), команды get/put/mget/mput.

Вы умеете: запускать SFTP-сессию, навигировать по удалённой и локальной файловой системе одновременно, скачивать и загружать файлы в интерактивном режиме.

В следующем уроке потребуется: понимание задачи «синхронизации» файлов между машинами — следующий инструмент, rsync, решает её намного эффективнее.

Урок 13.7. Эффективная синхронизация файлов: `rsync` через сеть

Освоить rsync — наиболее мощный инструмент синхронизации файлов, умеющий передавать только изменившиеся части файлов, возобновлять прерванные передачи и работать как по SSH, так и локально.

Теория

Представьте: у вас на сервере есть папка с проектом размером 10 ГБ. Вы изменили два небольших файла и хотите обновить локальную копию. scp -r скопирует все 10 ГБ заново. rsync скопирует только изменившиеся файлы, а если они большие — даже только изменившиеся блоки внутри файлов. Это может сократить время передачи с часов до секунд.

rsync (Remote Sync, «удалённая синхронизация») — утилита для эффективной синхронизации файлов и директорий. Главное, что отличает её от scp:

  1. Дельта-передача (delta transfer algorithm). rsync сравнивает файлы на источнике и на приёмнике и передаёт только изменения — отличающиеся блоки данных. Если файл почти не изменился, передаётся лишь небольшая «дельта» (разница), а не весь файл целиком.
  2. Возобновление прерванных передач. Если соединение оборвалось посредине — при следующем запуске rsync продолжит с того места, где остановился (а не начнёт с нуля).
  3. Гибкие фильтры. Можно легко исключить определённые файлы или папки (--exclude).
  4. Работа и локально, и через сеть. rsync можно использовать и для синхронизации папок на одной машине (без сети), и через SSH (с указанием удалённого хоста).
  5. Сохранение метаданных. С нужными параметрами rsync сохраняет права доступа, временные метки, символические ссылки и другие атрибуты файлов.

Синтаксис rsync через SSH:

```bash

rsync [опции] /локальная/папка/ пользователь@хост:/удалённая/папка/

rsync [опции] пользователь@хост:/удалённая/папка/ /локальная/папка/

```

Критично важный нюанс: слэш в конце пути!

Это одна из самых распространённых причин путаницы при работе с rsync:

Пример:

```bash

rsync /source/dir/ user@host:/dest/ # → /dest/file1, /dest/file2 ...

rsync /source/dir user@host:/dest/ # → /dest/dir/file1, /dest/dir/file2 ...

```

Запомните это правило — оно сэкономит вам много времени и нервов.

Наиболее полезная комбинация параметров для реальной работы:

```bash

rsync -avz --progress источник назначение

```

Важный параметр --delete. По умолчанию rsync только добавляет и обновляет файлы в назначении, но не удаляет те, которых уже нет в источнике. Если вы хотите настоящую «зеркальную» синхронизацию (назначение должно стать точной копией источника), добавьте --delete — тогда файлы, удалённые в источнике, будут удалены и в назначении. Используйте этот параметр осторожно.

Проверка без выполнения (-n или --dry-run). Перед реальной синхронизацией (особенно с --delete) крайне рекомендуется сначала сделать «холостой прогон»: добавьте -n или --dry-runrsync покажет, что собирается сделать, но ничего не изменит реально. Это позволяет проверить правильность команды без риска потерять данные.

Практика

Шаг 1. Убедитесь, что rsync установлен (в Ubuntu обычно предустановлен):

```bash

rsync --version

```

Если не найден: sudo apt install rsync.

Шаг 2. Создайте тестовую структуру директорий:

```bash

mkdir -p ~/rsync_source/{docs,images,configs}

echo "Документ 1" > ~/rsync_source/docs/doc1.txt

echo "Документ 2" > ~/rsync_source/docs/doc2.txt

echo "Конфиг приложения" > ~/rsync_source/configs/app.conf

echo "Данные" > ~/rsync_source/data.bin

ls -R ~/rsync_source/

```

Шаг 3. Выполните «холостой прогон» перед реальной синхронизацией:

```bash

rsync -avzn ~/rsync_source/ ваш_пользователь@localhost:/tmp/rsync_dest/

```

Что вы увидите: список файлов, которые rsync собирается скопировать, но ничего не изменится реально (флаг -n). Проверьте, что список соответствует ожиданиям.

[Скриншот dry-run]

Шаг 4. Выполните реальную синхронизацию:

```bash

rsync -avz --progress ~/rsync_source/ ваш_пользователь@localhost:/tmp/rsync_dest/

```

Что вы увидите: список передаваемых файлов с прогрессом и итоговую статистику (сколько файлов передано, сколько байт, скорость передачи).

[Скриншот реальной синхронизации с прогрессом]

Шаг 5. Проверьте результат:

```bash

ls -R /tmp/rsync_dest/

```

Шаг 6. Измените несколько файлов в источнике и добавьте новый:

```bash

echo "Обновлённый документ 1" > ~/rsync_source/docs/doc1.txt

echo "Новый документ 3" > ~/rsync_source/docs/doc3.txt

```

Шаг 7. Запустите rsync снова и посмотрите — он передаст только изменившееся:

```bash

rsync -avz --progress ~/rsync_source/ ваш_пользователь@localhost:/tmp/rsync_dest/

```

Что вы увидите: на этот раз будут переданы только docs/doc1.txt (изменён) и docs/doc3.txt (новый). Файлы doc2.txt, app.conf, data.bin не трогаются — они не изменились. Вот в чём сила rsync.

[Скриншот инкрементальной синхронизации]

Шаг 8. Попробуйте исключить определённые файлы при синхронизации:

```bash

rsync -avz --exclude='*.conf' ~/rsync_source/ ваш_пользователь@localhost:/tmp/rsync_dest2/

```

Что произойдёт: все файлы скопируются, кроме configs/app.conf (он соответствует шаблону *.conf).

```bash

ls -R /tmp/rsync_dest2/

```

Шаг 9. Используйте rsync для локальной синхронизации (без сети — просто чтобы увидеть, что это тоже работает):

```bash

rsync -av ~/rsync_source/ ~/rsync_local_backup/

```

Шаг 10. Очистите тестовые данные:

```bash

rm -r ~/rsync_source ~/rsync_local_backup

rm -r /tmp/rsync_dest /tmp/rsync_dest2

```

Разбор команд

Команда rsync

Итоговое сравнение инструментов передачи файлов:

| Инструмент | Лучше подходит для... |

|---|---|

| scp | Быстро скопировать один-два файла |

| sftp | Интерактивная работа с файлами (просмотр, загрузка/скачивание нескольких файлов) |

| rsync | Синхронизация папок, резервное копирование, повторяемые задачи, большие объёмы |

Возможные ошибки

Почему возникает: --delete удаляет из назначения файлы, которых нет в источнике — если перепутать источник и назначение местами, можно удалить «нужные» файлы и заменить «ненужными».

Как определить: данные пропали после rsync с --delete.

Как исправить: восстановить из резервной копии (если есть).

Как избежать: всегда использовать -n/--dry-run перед реальным запуском rsync с --delete. Никогда не запускать с --delete без предварительной проверки.

Почему возникает: отсутствует -a (или -t) — без сохранения временных меток rsync не может определить, изменился ли файл, и передаёт всё заново.

Как исправить: добавить флаг -a к команде rsync.

Почему возникает: непонимание разницы rsync src/ и rsync src.

Как определить: в назначении появляется лишний уровень вложенности (или наоборот — содержимое «вываливается» туда, куда не ожидалось).

Как исправить: чётко запомнить правило слэша (разобрано в теории). При сомнениях — сначала -n dry-run.

Практические задания

  1. Создайте локальную папку-«источник» с несколькими файлами и папку-«назначение». Синхронизируйте их с помощью rsync -av. Затем удалите один файл из источника и запустите rsync -avn --delete (dry-run), чтобы увидеть, что будет удалено. Потом запустите без -n и убедитесь, что файл действительно удалился из назначения.
  2. Синхронизируйте папку на localhost через SSH с флагами -avz --progress, добавив исключение для файлов с расширением .log (--exclude='*.log'). Создайте несколько .log-файлов в источнике и убедитесь, что они не передаются.
  3. Объясните в конспекте, почему команда rsync -av ~/docs/ backup:~/docs/ будет работать быстрее при повторном запуске, чем scp -r ~/docs/ backup:~/ при тех же условиях.

Проверка знаний

Вопрос 1. Что такое «дельта-передача» в rsync и почему она важна для резервного копирования больших объёмов данных?

Ответ: Дельта-передача — это механизм, при котором rsync передаёт не весь файл, а только изменившиеся блоки. Если в файле размером 1 ГБ изменились только 10 МБ, будет передано лишь 10 МБ. Для резервного копирования больших объёмов это критически важно: вместо ежедневного копирования терабайт данных передаются лишь реально изменившиеся части, что экономит время, трафик и место.

Вопрос 2. Зачем использовать --dry-run перед реальным запуском rsync с --delete?

Ответ: --delete удаляет из назначения файлы, отсутствующие в источнике. Если источник и назначение перепутаны или шаблоны --exclude настроены неверно — можно уничтожить нужные данные. --dry-run позволяет увидеть, что именно rsync собирается удалить и скопировать, без реального выполнения. Это «страховка» перед потенциально разрушительной операцией.

Итоги урока

Вы изучили: принцип дельта-передачи, параметры -avz, --delete, --dry-run, --exclude, правило слэша, сравнение scp/sftp/rsync.

Вы умеете: синхронизировать файлы и папки через SSH с помощью rsync, делать инкрементальные резервные копии, безопасно проверять команды через dry-run.

В следующем уроке (первый урок Блока 14) потребуется: понимание, что SSH — это критически важный сервис с точки зрения безопасности, и его правильная настройка — основа защиты любого Linux-сервера.

Мини-проект блока

Задача: создать практическую систему, которая объединяет всё, что изучено в блоке: SSH-ключи, конфиг, и rsync для автоматического резервного копирования.

Что нужно сделать:

  1. Настройте SSH-ключи и конфиг (если ещё не сделано): убедитесь, что у вас есть пара ключей Ed25519, и создайте запись в ~/.ssh/config для подключения к localhost под псевдонимом backup-host (для учебных целей используем localhost как «сервер бэкапов»).
  1. Создайте структуру «важных данных» для резервного копирования:

```bash

mkdir -p ~/important/{documents,projects,configs}

echo "Важный документ" > ~/important/documents/report.txt

echo "Код проекта" > ~/important/projects/app.py

cp ~/.ssh/config ~/important/configs/ssh_config.bak

```

  1. Напишите команду rsync для резервного копирования папки ~/important/ на «сервер» в директорию /tmp/backup/ с параметрами -avz --progress --delete. Сначала выполните dry-run, затем реальную синхронизацию.
  1. Проверьте инкрементальность: измените один файл в ~/important/, добавьте один новый файл, удалите один файл. Запустите rsync снова и убедитесь, что он передал только изменения.
  1. Напишите bash-скрипт ~/backup.sh (мы изучим скрипты подробно в Блоке 15, но здесь попробуем самое простое):

```bash

#!/bin/bash

rsync -avz --delete ~/important/ backup-host:/tmp/backup/

echo "Резервное копирование завершено: $(date)"

```

Сделайте скрипт исполняемым: chmod +x ~/backup.sh.

Запустите и убедитесь, что он работает: ./backup.sh.

  1. Задокументируйте в конспекте: какие SSH-ключи используются, что означает каждый параметр rsync в скрипте, и почему эта связка (SSH-ключи + rsync) лучше ручного копирования.

Критерий готовности: скрипт ~/backup.sh запускается без ввода пароля (благодаря SSH-ключам) и корректно синхронизирует папку, передавая только изменившиеся файлы при повторном запуске.

Контрольные вопросы

  1. Объясните, что такое fingerprint SSH-сервера, где он хранится на стороне клиента и зачем SSH проверяет его при каждом подключении.
  2. В чём разница между приватным и публичным SSH-ключом? Какой из них кладётся на сервер, а какой остаётся у вас?
  3. Какой параметр команды scp используется для копирования директорий, и почему в scp порт указывается через -P, а не -p?
  4. Перечислите три команды с l-префиксом, доступные внутри SFTP-сессии, и объясните, что они делают.
  5. Что произойдёт при запуске rsync -av ~/source/ user@host:/dest/ если в /dest/ уже есть файлы, которых нет в ~/source/?
  6. Объясните правило слэша в конце пути для rsync на конкретном примере.
  7. Какой файл нужно создать и настроить на стороне SSH-сервера, чтобы пользователь мог войти по ключу? Каковы правильные права доступа на этот файл?

Выводы по блоку

В этом блоке вы совершили качественный скачок: перешли от работы с одной машиной к управлению машинами через сеть. Это и есть суть профессии системного администратора — умение работать с серверами, находящимися в любой точке мира, из любого места, где есть интернет-соединение.

Вы разобрались в том, почему SSH вытеснил небезопасный Telnet, как работает криптография «под капотом» этого протокола, и почему SSH-ключи надёжнее паролей. Вы умеете не просто войти на сервер, но и удобно организовать работу через файл ~/.ssh/config, передавать файлы тремя разными инструментами под разные задачи, и синхронизировать данные инкрементально с помощью rsync.

Этот материал будет использоваться во всех следующих блоках: в Блоке 14 (безопасность SSH), в Блоке 15 (скрипты через SSH), в Блоке 16 (Git через SSH), в Блоке 20 (администрирование VPS).

Список изученных тем

Рекомендации перед переходом

Убедитесь, что вы умеете:

В Блоке 14 мы будем работать непосредственно с безопасностью сервера, и SSH станет центральной темой — мы научимся отключать аутентификацию по паролю (оставив только ключи), менять порт SSH, настраивать Fail2Ban против перебора паролей. Всё это строится на фундаменте, заложенном в этом блоке.