At the moment, Windows 10’s implementation of the OpenSSH client does not have the ssh-copy-id
command available. However, a PowerShell one-line command can mimic the ssh-copy-id
command and allow you to copy an SSH public key generated by the ssh-keygen command to a remote Linux device for passwordless login.
Generate an SSH Key
Note: If you have already generated an SSH keypair that you would like to use, skip this section and proceed to the Copy SSH Key to Remote Linux Device section.
First, open a new PowerShell window (not a Command Prompt window!) and generate a new SSH keypair with the ssh-keygen
command. By default, the public and private keys will be placed in the %USERPROFILE%/.ssh/
directory. The public key file we are interested in is named id_rsa.pub
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
PS C:\Users\Christopher> ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (C:\Users\Christopher/.ssh/id_rsa): Created directory 'C:\Users\Christopher/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in C:\Users\Christopher/.ssh/id_rsa. Your public key has been saved in C:\Users\Christopher/.ssh/id_rsa.pub. The key fingerprint is: SHA256:/mjkrJOQbRzCAwlSPYVBNcuxntm/Ms5/MMC15dCRrMc christopher@Christopher-Win10-VM-01 The key's randomart image is: +---[RSA 2048]----+ |oo.+o== o.o | |. o +. = o = | | o .+. . B | | +..+o o E | | *+.S. . | | o +...o | | o =. .o | | o.*o .. | | .=+++. | +----[SHA256]-----+ PS C:\Users\Christopher> |
Copy SSH Key to Remote Linux Device
Next, we use the below PowerShell one-line command to copy the contents of the id_rsa.pub
public key to a remote Linux device. Replace the {IP-ADDRESS-OR-FQDN}
with the IP address or FQDN (Fully Qualified Domain Name) of the remote Linux device you would like to copy the public key to.
1 |
type $env:USERPROFILE\.ssh\id_rsa.pub | ssh {IP-ADDRESS-OR-FQDN} "cat >> .ssh/authorized_keys" |
An example of this command is shown below. In this example, I am copying the contents of the id_rsa.pub
public key to a remote Linux device at IP address 192.168.30.31.
1 2 3 4 5 6 7 |
PS C:\Users\Christopher> type $env:USERPROFILE\.ssh\id_rsa.pub | ssh 192.168.30.31 "cat >> .ssh/authorized_keys" The authenticity of host '192.168.30.31 (192.168.30.31)' can't be established. ECDSA key fingerprint is SHA256:mTD0/WNCVZ/p/PFSkNDmLJtzIGb5eD7qj6erOQkomjM. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.30.31' (ECDSA) to the list of known hosts. ch[email protected]'s password: PS C:\Users\Christopher> |
Test Passwordless SSH Connectivity to Remote Linux Device
Finally, verify that you can SSH to the remote Linux device with the ssh
command. An example to a remote Linux device at IP address 192.168.30.31 is shown below. Note how a password did not need to be entered in order for us to establish SSH connectivity to the remote Linux device.
1 2 3 4 |
PS C:\Users\Christopher> ssh 192.168.30.31 Last login: Sat May 23 12:44:51 2020 from 192.168.10.139 [christopher@linux ~]$ who christopher pts/0 2020-05-24 19:35 (192.168.10.113) |
References
The instructions for this blog post were heavily inspired by Scott Hanselman’s blog post on the subject.
This post is licensed under
CC BY 4.0
by the author.
This following steps would do:
STEP-1: Generate RSA Key Pair
C:\Users\user>ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/user//.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/user//.ssh/id_rsa.
Your public key has been saved in /c/Users/user//.ssh/id_rsa.pub.
The key fingerprint is:
20:16:9b:0d:00:92:c4:34:99:51:20:b7:ef:50:c4:0f user@localhost
STE2-2: ssh-copy-id equivalent in windows
C:\Users\user>ssh user@remote "umask 077; test -d .ssh || mkdir .ssh ; cat >> .s
sh/authorized_keys || exit 1" < "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys
|| exit 1" < C:\Users\user\.ssh\id_rsa.pub
The authenticity of host 'remote (xx.xx.xxx.xx)' can't be established.
RSA key fingerprint is 99:99:73:74:fe:14:bc:91:c8:3b:ac:f4:95:99:4d:06.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'remote,xx.xx.xxx.xx' (RSA) to the list of known hosts.
*************************************************************************
This computer system is the property of Sample Corporation and is to
be used for business purposes. All information, messages, software and
hardware created, stored, accessed, received, or used by you through
this system is considered to be the sole property of Sample Corporation
and can and may be monitored, reviewed, and retained at any time. You
should have no expectation that any such information, messages or
material will be private. By accessing and using this computer, you
acknowledge and consent to such monitoring and information retrieval.
By accessing and using this computer, you also agree to comply with
all of Sample Company's policies and standards.
*************************************************************************
user@remote's password:[Enter Password for first time]
STEP-3: Passwordless authentication works!
C:\Users\user>ssh user@remote
*************************************************************************
This computer system is the property of Sample Corporation and is to
be used for business purposes. All information, messages, software and
hardware created, stored, accessed, received, or used by you through
this system is considered to be the sole property of Sample Corporation
and can and may be monitored, reviewed, and retained at any time. You
should have no expectation that any such information, messages or
material will be private. By accessing and using this computer, you
acknowledge and consent to such monitoring and information retrieval.
By accessing and using this computer, you also agree to comply with
all of Sample Company's policies and standards.
*************************************************************************
Last login: Wed Oct 14 14:37:13 2015 from localhost
SSH-ключи для авторизации — это простой и надежный способ получения доступа к удаленному узлу. В статье мы рассмотрим процесс настройки SSH-авторизации по ключу, а также покажем способы устранения некоторых известных ошибок.
Что такое SSH-ключ
Аббревиатура SSH означает Secure Shell, что дословно переводится как «безопасная оболочка». Если говорить точнее, SSH — это защищенный сетевой протокол с проверкой подлинности и шифрованием. Он используется для передачи файлов, управления сетью и удаленного доступа к операционной системе. Аббревиатура SSH также используется для описания набора инструментов, используемых для взаимодействия с одноименным протоколом.
Подключение через SSH можно просто охарактеризовать как подключение к командной строке удаленного узла. То есть любые команды, которые будут вводиться в терминал на основной машине будут работать так же, будто вы вводите их напрямую на удаленном узле, сидя с клавиатурой около него.
Так как SSH работает по системе «клиент-сервер», обязательное условие для работы этого протокола — наличие на удаленном узле демона SSH. Демон SSH — это ПО, которое прослушивает определенный сетевой порт и при прохождении аутентификации другим узлом создает необходимую среду для работы с ним.
В свою очередь на локальной машине должно быть установлено соответствующее ПО — SSH-клиент. Он взаимодействует с удаленным хостом и передает ему необходимые данные, которые нужны для прохождения аутентификации.
Пользователи Linux могут установить OpenSSH с помощью команды:
sudo apt-get install ssh
В некоторых ОС компоненты OpenSSH можно установить отдельно для клиента openssh-client и отдельно для сервера openssh-server.
Структура ключа
Можно сказать, что определение «SSH-ключ» составное, так как на самом деле это два ключа — открытый и закрытый. На узле A создаются и хранятся оба ключа, а на узел B передается только копия публичного SSH-ключа, что позволяет подключаться к узлу B с узла A.
Ключи могут быть сгенерированы с помощью различных алгоритмов, которые поддерживает текущая версия протокола SSH. Например, если использован тип шифрования RSA, то файлы будут именоваться следующим образом:
- id_rsa — закрытый ключ,
- id_rsa.pub — публичный (открытый) ключ.
В чем же разница открытого и закрытого ключа?
Открытые и закрытые SSH-ключи
Открытый (он же публичный) ключ используется для шифрования данных при обращении к удаленному узлу. Проще говоря, это набор символов, при помощи которых мы шифруем информацию. Он доступен всем. Не стоит бояться того, что открытый ключ может попасть в чужие руки, так как наличие одного лишь публичного SSH-ключа не дает злоумышленнику никаких преимуществ. Открытый SSH-ключ хранится на удаленном узле.
Закрытый (приватный) SSH-ключ — это ключ к данным. Он расшифровывает сами сообщения. Хранится он на устройстве, которое будет подключаться к удаленному узлу (на котором находится открытый ключ). Приватный ключ ни в коем случае нельзя передавать в чужие руки, в том числе через мессенджеры или файлообменники, во избежание утечки информации и персональных данных. Также рекомендуем сразу установить пароль на закрытый ключ, чтобы обеспечить ему дополнительную защиту.
Как работает SSH-авторизация?
Давайте представим, что Selectel — это сервер, а вы — клиент. Вы хотите подключиться к нам с использованием SSH-ключа. Предварительно вы уже создали пару ключей и передали публичный ключ нам. Алгоритм взаимодействия будет следующим:
- Вы должны изъявить свое желание подключиться к нам, то есть отправить запрос на подключение по TCP-порту.
- В случае установки TCP-соединения мы бмениваемся информацией о версиях наших SSH-протоколов. С помощью этой информации можно понять, какую именно конфигурацию (версию протоколов и алгоритмы работы) использовать. Самостоятельно узнать версию OpenSSH можно с помощью команды ssh -V.
- После согласования мы (сервер) направляем вам (клиенту) открытый ключ. Теперь уже вы решаете, доверять такому ключу или нет. В случае положительного ответа мы с вами генерируем сеансовый ключ, который будет использоваться для симметричного шифрования канала. Этот ключ существует, только пока существует канал (текущая сессия).
- Теперь следует аутентифицировать вас. Для этого вы отсылаете нам свой открытый ключ. Мы в свою очередь проверяем его со своим списком открытых SSH-ключей. Если совпадение найдено, мы генерируем случайное число, шифруем его открытым ключом и отправляем обратно. Вы как клиент расшифровываете сообщение закрытым ключом и отправляете полученные данные нам. В случае совпадения присланного числа с первоначальным аутентификация признается успешной.
Поздравляем! Теперь вам открыт доступ на сервер.
Типы ключей SSH
Как вы уже знаете, существуют два основных типа ключей — открытый и закрытый. Но также ключи можно разделить по типу шифрования.
Если мы введем в терминал команду ssh-keygen ?, то увидим справку, где у параметра -t указаны алгоритмы, которые можно использовать в данной системе:
~# ssh-keygen ?
…
[-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]
RSA — по умолчанию ssh-keygen использует в качестве параметра -t именно RSA, так как этот алгоритм обеспечивает наилучшую совместимость из всех, но требует большего размера ключа для обеспечения достаточной безопасности. Длина ключа по умолчанию составляет 3072 бит, но вы можете самостоятельно задать его размер от 1024 до 16384 бит с помощью опции -b команды ssh-keygen.
Имейте в виду, что, чем больше ключ, тем больше вычислительных мощностей и трафика будут задействовать устройства. Поэтому если вам нужна усиленная защита и для этого вы хотите увеличить длину ключа RSA, возможно, вам стоит рассмотреть алгоритмы на основе эллиптических кривых. При таких условиях они будут работать быстрее.
DSA — криптографический алгоритм с использованием открытого ключа для создания электронной подписи, но не для шифрования. Это значит, что только один узел сможет подписать сообщение, а другие смогут только проверить ее на корректность. Алгоритм основан на вычислительной сложности взятия логарифмов в конечных полях. Алгоритм DSA в сравнении с RSA показывает лучшие показатели при генерации подписи, но уступает по времени при ее проверке. Также отметим, что максимальная длина ключа данного типа — 1024 бит. Это не самый безопасный показатель в защите от взлома.
ECDSA — это реализация схемы цифровой подписи, основанная на использовании эллиптических кривых и модульной арифметики. Производительность данного алгоритма быстрее, чем у алгоритма RSA, так как для обеспечения шифрования требуются ключи гораздо меньшего размера. Однако у него есть минус: он более уязвим перед взломом с помощью квантовых вычислений, чем RSA.
ED25519 — это схема подписи на эллиптической кривой, которая обеспечивает лучшую безопасность, чем ECDSA и DSA, и хорошую производительность. Его главными преимуществами являются скорость. Однако данный алгоритм поддерживается только в версиях от OpenSSH 6.5.
ECDSA-SK и ED25519-SK — это те же ECDSA и ED25519, но поддерживающие аппаратный аутентификатор. Данные алгоритмы появились не так давно в версии OpenSSH 8.2. Они позволяют реализовать двухфакторную аутентификацию с помощью устройств, которые поддерживают протокол FIDO/U2F. Существует множество разновидностей физической аутентификации, например USB-токен, или другие виды устройств, подключаемые к оборудованию с помощью Bluetooth или NFC.
Добавить публичный ключ можно сразу при заказе сервера. Все добавленные ключи хранятся в разделе Серверы и оборудование → SSH-ключи.
Создание SSH-ключа
Параметры утилиты ssh-keygen
В Linux для создания SSH-ключей используется команда ssh-keygen. Далее приведены наиболее популярные параметры для этой команды и их описание.
-C comment
Создание нового комментария. Например, одной из самых известных команд является добавление комментария с информацией о том, кто, на какой машине и когда создал ключ:
ssh-keygen -C "$(whoami)@$(uname -n)-$(date -I)"
—p
Если указать данный параметр при вводе ssh-keygen, то вам будет предложено изменить старую секретную фразу на новую. Ввод команды будет выглядеть следующим образом:
ssh-keygen -p
Также вы можете задать все параметры для изменения секретной фразы сразу:
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
—t type
Задает тип создаваемого ключа. Чтобы узнать какие типы доступны для вашей версии, введите:
ssh-keygen -t ?
-v
Подробный режим. ssh-keygen будет печатать отладочные сообщения о ходе выполнения. Несколько опций -v увеличивают степень подробности информации (максимум 3).
Генерация SSH-ключей в Linux
Процесс создания SSH-ключей на базе Linux предельно прост. Вам необходимо лишь указать некоторые параметры, которые мы опишем далее.
Мы будем создавать ключ RSA. При вводе команды ssh-keygen опцию -t RSA можно не указывать явно, так как RSA является алгоритмом по умолчанию.
~# ssh-keygen
Generating public/private RSA key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
В последней строке вам предлагается выбрать путь, куда будут сохранены ключи. Если оставить поле пустым, будут созданы файлы с именами id_rsa.pub и id_rsa.
Enter passphrase (empty for no passphrase):
В данной строке предлагается создать кодовую фразу. Оставив строку пустой, дополнительной защиты не будет.
С одной стороны, не вводить кодовую фразу опасно. Если закрытый ключ попадет в руки злоумышленников, то у них может появиться доступ к серверу. В то же время, если вы введете кодовую фразу, в будущем это может доставить вам неудобства. Пароль придется вводить каждый раз при использовании SSH-подключения с этим ключом. Поэтому использование кодовой фразы остается на ваше усмотрение.
Как мы упоминали ранее, кодовую фразу можно будет установить (или заменить) самостоятельно, введя ssh-keygen -p, когда ключ уже будет создан.
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Uh6CVy4Voz0/70Am8j+hXOLBV21l4rMmiMLG5BTz3cE root@trexclient
The key's randomart image is:
+---[RSA 3072]----+
| =. . |
| .o* . E . o|
| . =+*. . + + |
| .o=.+. o = |
| *o.S.=o . o |
| *+=+=o. o |
| . +.*...o |
| +..o |
| ... |
+----[SHA256]-----+
Созданные файлы хранятся в директории /home/*SystemName*/.ssh/.
Генерация SSH-ключей в Windows с помощью Putty
Если вы хотите создать SSH-ключи на базе ОС Windows, самым популярным решением для этого будет использование программного обеспечения Putty. Скачать его можно с официального сайта по ссылке (актуальная версия на момент написания статьи — Putty 0.78). После установки программы вам будет доступно несколько .exe файлов.
Для создания SSH-ключей откройте puttygen.exe, выберите необходимый тип ключа и задайте его размер. Мы будем использовать RSA с длиной 3072.
Далее нажмите Генерировать и водите мышкой по экрану в свободной зоне до тех пор, пока генерация SSH-ключей не будет завершен. Это необходимо делать для того, чтобы задать псевдослучайность при создании ключей.
После генерации ключа вы можете вписать комментарий и кодовую фразу.
Далее необходимо сохранить на диск открытый и закрытый SSH-ключи, для этого нажмите на соответствующие кнопки в окне программы. Вы можете самостоятельно выбрать путь, куда сохранять данные ключи.
Putty сохраняет закрытые ключи с разрешением .ppk, что означает, что такой ключ можно будет использовать только с Putty. Чтобы сохранить секретный ключ в формате, пригодном для OpenSSH, нужно во вкладке Конвертация выбрать пункт «Экспортировать ключ в формате OpenSSH (новый формат)» и указать расположение нового файла (старый формат при конвертации из .pkk в OpenSSH сохраняет не все поля — например, комментарий).
Генерация SSH-ключей в Windows с помощью OpenSSH
Не так давно в ОС Windows добавили возможность использования инструментов OpenSSH. Пакет добавлен в ОС, начиная с Windows 10 и Windows Server 2019.
Установить клиент OpenSSH можно с помощью следующей команды в PowerShell:
Add-WindowsCapability -Online -Name OpenSSH.Client
Или же с помощью графического интерфейса: Параметры → Приложения → Дополнительные возможности → Добавить компонент. В списке предложенных компонентов необходимо найти Клиент OpenSSH и нажать кнопку Установить.
Проверить статус компонента можно командой:
Get-WindowsCapability -Online | ? Name -like 'OpenSSH.Client*'
Если в ответе команды статус Installed, то загрузка выполнена успешно.
Генерация SSH-ключей происходит таким же образом, как и в ОС Linux, с помощью ssh-keygen:
PS C:\Users\Administrator> ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\Administrator/.ssh/id_ed25519):
Created directory 'C:\Users\Administrator/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\Administrator/.ssh/id_ed25519.
Your public key has been saved in C:\Users\Administrator/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:1qBO0MIgYM+A80G1zZgUzW4QCYHKNuLgwaIR77sY2/U administrator@winselectel
The key's randomart image is:
+--[ED25519 256]--+
|===+=* |
|*.=+oBo |
|+= +Bo+ . |
|**o oo. o |
|Ooo .o S . |
|.o. o . |
|. .. . |
| =.. . |
|o o. E |
+----[SHA256]-----+
Созданные ключи можно найти в папке C:\Users\Administrator\.ssh, если она не была изменена при генерации.
Копирование открытого ключа на сервер
В данном разделе мы рассмотрим общий вариант копирования открытого SSH-ключа на сервер.
Копирование при помощи SSH-Copy-ID
Данный метод подойдет тем, чья ОС поддерживает команду SSH-Copy-ID, и удаленный сервер имеет доступ по SSH без ключа. Если это не так, попробуйте использовать второй или третий способ.
Синтаксис команды выглядит следующим образом:
-# ssh-copy-id username@remote_host
Обратите внимание на последние строки вывода:
-# ssh-copy-id root@5.159.102.80
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '5.159.102.80 (5.159.102.80)' can't be established.
ED25519 key fingerprint is SHA256:KSvVyjbijk+LQ7n3cEQd94qcyIcTDfaED+jRFzBBPGM.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Наш клиент запрашивает разрешение на продолжение подключения к удаленному узлу, так как встречает его впервые. Необходимо ввести yes. После успешного подключения ключи будут добавлены и мы увидим соответствующий вывод:
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@5.159.102.80's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@5.159.102.80'"
and check to make sure that only the key(s) you wanted were added.
Чтобы проверить, действительно ли скопировался открытый ключ, найдем искомый файл authorized_keys на удаленном узле и посмотрим его содержимое, так как именно в него добавляются открытые SSH-ключи.
~# cat /root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCoQ/EcDWqYKTKCLkd3gZcz98+wRSCTNVNmLUUF6HqWsl105sBX6vep4/xe6cc6zcYSCgFgcKGEK8h2QNIzw+DmdH2Ujxn6AaEkaNBS0b4AGMJSYREqCh6tRpTwBF1VVV5usLMQLz9/eh7HVhorCsHB6bdxk+M2sJOHxX1ikynnwc2cRs12uY/mWMfdLi6S1Q76NmgcfR/ICjyxXUcM3FlmUUsyzQJVyq7+pPr5ahodJw0LRKe3hRNPdQIiXOlNXn1tX7oIxcN9wZ5VR4ZwMORwNBZymZA3oS2Kr27cHvvIhwtEC92ouxd3ue1H8mBmexzbwW6S9Qom0pLiEclK4zRrKmmAWLgHV/2I7nzH6n3V+RFGttW3EOTKTI6n48tnKx7RKaM0qBpzqSAxanNaW3NRvrs++NSjb2LnZoLFoSf9YPLB6YrI6cO08vkWbesc/DWHic3BYPPEaj0rekj5dLJip+acdJw0AiG3dzwfw4ppmcv7zuQpanJYntpmLHoQV4E= root@trexclient
Как мы видим, публичный SSH-ключ клиента был успешно добавлен на сервер.
Примечание. Если на удаленном узле вы используете не стандартный порт в качестве порта для подключения по SSH, а любой другой, то необходимо при вводе команды ssh-copy-id указать дополнительные параметры:
ssh-copy-id ‘-p *port* username@remote_host’
После внесенных изменений необходимо перезапустить службы SSH.
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
Копирование ключа при помощи SSH
Данный метод подойдет тем, чья клиентская машина не поддерживает команду SSH-Copy-ID, но сервер имеет доступ по SSH.
В таком случае вы можете воспользоваться командой:
cat ~/.ssh/id_rsa.pub | ssh username@remote_host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
, где
- cat ~/.ssh/id_rsa.pub — вывод содержимого файла id_rsa.pub,
- ssh username@remote_host — подключение к удаленному серверу,
- «mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys» — проверка наличия директории /.ssh и перенаправление вывода первой команды в файл authorized_keys.
Чтобы проверить, действительно ли скопировался открытый ключ, точно так же, как в первом варианте, найдем искомый файл authorized_keys на удаленном узле и посмотрим его содержимое.
~# cat /root/.ssh/authorized_keys
После внесенных изменений необходимо перезапустить службы SSH.
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
Копирование пользователем вручную
Данный метод следует использовать тем, у кого нет SSH-доступа на удаленный сервер. Вам необходимо найти файл id_rsa.pub (при использовании Linux) или public (при использовании Windows) на клиентской машине, открыть его и скопировать все содержимое. Через консоль Linux это можно сделать, используя команду cat:
cat ~/.ssh/id_rsa.pub
Затем следует любым доступным вам способом подключиться к удаленному серверу, куда необходимо скопировать открытый SSH-ключ. В нашем случае это будет консольный доступ к облачному (виртуальному) серверу через панель my.selectel.ru.
Найдя все тот же файл authorized_keys, необходимо просто вставить в него то, что мы скопировали из файла id_rsa.pub на клиентской машине ранее. В случае, если вы генерировали SSH-ключи в ОС Windows с помощью Putty, необходимо так же скопировать публичный ключ в файл authorized_keys. Либо вы можете открыть консоль и использовать команду для загрузки ключа:
echo *Text* >> ~/.ssh/authorized_keys
Где *Text* — это скопированные вами данные из id_rsa.pub.
После внесенных изменений необходимо перезапустить службы SSH.
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
Использование SSH-ключей
Настройка аутентификации на сервере с помощью SSH-ключей из ОС Linux
Чтобы воспользоваться подключением по SSH с помощью ключей, необходимо из-под клиентской машины, на которой мы создавали ключи, ввести команду:
~# ssh username@remote_host
root@trexclient:~# ssh root@5.159.102.80
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-60-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
Last login: Sun Mar 5 12:31:34 2023 from 152.89.133.14
root@selectelserv:~#
Если имя пользователя на локальной машине и удаленном узле совпадают, можно сократить вводимую команду до:
~# ssh remote_host
Настройка аутентификации на сервере с помощью SSH-ключей из ОС Windows
Ранее мы уже скопировали открытый SSH-ключ, сгенерированный с помощью Putty, на удаленный узел. Теперь необходимо произвести подключение.
Для этого откройте putty.exe и введите IP-адрес удаленного узла и порт для подключения, а также проверьте, что в качестве типа подключения выбран SSH.
Далее пройдите по пути, указанному на скриншоте (Connection → SSH → Auth → Credentials):
В поле Private key file for authentication вставьте ссылку на приватный ключ, который необходимо использовать в данном подключении, и нажмите Open.
Перед вами откроется окно, в котором нужно ввести логин пользователя удаленного узла. В нашем случае — учетная запись root.
Подключение из ОС Windows с помощью OpenSSH аналогично подключению по SSH на сервере Linux:
C:\Users\Administrator> ssh hostname@remote_host
Если при генерации SSH-ключей была создана секретная фраза, то удаленный хост запросит ее подтверждение:
Enter passphrase for key 'C:\Users\Administrator/.ssh/id_ed25519':
Выполнение одной команды на удаленном узле
Если вам необходимо ввести лишь одну команду, можно не создавать целый сеанс, а ввести нужную команду после ssh hostname@remote_host.
ssh hostname@remote_host command
Технически сессия все-таки создается, и происходит аутентификация на основе введенных данных. Затем передается нужная команда command, и сеанс сразу же закрывается. Поэтому визуально кажется, что мы просто передали команду на удаленный узел.
Отпечаток SSH-ключа
Каждая пара SSH-ключей использует один криптографический отпечаток. Его можно использовать для идентификации ключей.
~# ssh-keygen -l
Enter file in which the key is (/root/.ssh/id_rsa):
Здесь вы можете оставить поле пустым, если автоматически выбран нужный вам ключ. Если это не так, введите местоположение интересующего вас файла. После этого на экран будет выведена подобная запись (длина ключа, отпечаток ключа, пользователь и хост, для которого был создан ключ, используемый алгоритм шифрования):
3072 SHA256:UxyIzKj93YXoldmfyP5K4/uKkHTu9UoG0nK9e93q57g root@trexclient (RSA)
Смена порта SSH
Дополнительной защитой доступа к вашему серверу может быть смена стандартного порта, на котором работает SSH. Перед сменой порта подключения необходимо открыть данный порт в файерволе с помощью команды:
sudo ufw allow *port*
Теперь приступим к изменению порта. В первую очередь, находясь на удаленном узле, необходимо открыть файл sshd_config:
sudo nano /etc/ssh/sshd_confog
Внутри этого файла найдите строку Port и укажите там свое значение, например, 4312.
Port 4312
После этого необходимо перезагрузить демон SSH:
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
Теперь при подключении к этому удаленному узлу необходимо указывать новый порт для подключения по SSH с помощью ключа -p:
ssh -p 4312 hostname@remote_host
Если вы хотите, чтобы -p 4312 не нужно было вводить каждый раз, можно изменить файл конфигурации SSH на локальной машине следующим образом:
nano ~/.ssh/config
Host *alias_name*
HostName *remote_host*
Port *port*
User *username*
Теперь при подключении к удаленному узлу с помощью команды ssh *AliasName* порт будет выбран автоматически согласно соответствующей записи в /config.
Проброс авторизации
Проброс авторизации — это аутентификация на другом сервере через сервер, к которому вы подключены, используя ключ на вашем локальном компьютере. Иными словами, мы с узла A подключаемся к узлу B, а узел B, используя данные узла A, присоединяется с их помощью к узлу C.
На первом узле мы ввели команду подключения с ключом -A, тем самым подключились к узлу host_B.
ssh -A root@*host_B*
На узле host_B мы ввели следующую команду и присоединились к узлу host_C под учетными данными первого узла.
root@host_B:~# ssh root@*host_C*
Таким образом, вы можете подключаться по SSH к любому другому устройству, к которому разрешен доступ с помощью вашего SSH-ключа, через промежуточное устройство.
Увеличение времени простоя
Время ожидания подключения может истечь — придется подключаться к системе заново. Чтобы этого избежать, можно настроить конфигурацию так, чтобы удаленный узел проверял активное SSH-соединение, отправляя клиенту echo-запросы каждые ServerAliveInterval секунд. Если клиент не ответит на запрос ServerAliveCountMax раз, то соединение будет разорвано.
Данные изменения нужно внести в конфигурацию файла /etc/ssh/sshd_config на сервере.
ServerAliveInterval *count*
ServerAliveCountMax *count*
Отключение проверки пароля
Ранее мы с вами настроили доступ по SSH с использованием SSH-ключей, но альтернативный вход по паролю по-прежнему включен. Чтобы обезопасить себя от возможного брутфорса (взлома пароля простым перебором), необходимо отключить возможность такого входа. Для этого на сервере нам необходимо открыть на редактирование файл конфигурации SSH под названием sshd_config:
sudo nano /etc/ssh/sshd_config
В нем найдем строку PasswordAuthentication, изменим ее значение с yes на no и сохраним изменения.
PasswordAuthentication no
Для того, чтобы изменения вступили в силу, следует перезагрузить службу SSH:
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
Теперь ваш сервер не будет рассматривать в качестве возможного варианта подключения по SSH использование пароля.
Устранение неполадок
Ключ игнорируется сервером
В редких случаях можно столкнуться с проблемой, что вы настроили все корректно, но не можете подключиться к серверу с использованием SSH-ключей. Видя следующий вывод, можно подумать, что сервер не видит ключ:
Permission denied (publickey).
Вероятнее всего, сервер SSH считает, что установлены неподходящие разрешения к некоторым каталогам. Для решения этой проблемы следует изменить права доступа.
Настройка удаленного узла
Полный доступ к папке .ssh только владельцу, остальным — полный запрет:
chmod rwx------ ~/.ssh
Права на запись и чтение для файла authorized_keys только владельцу, остальным — полный запрет:
chmod rw------- ~/.ssh/authorized_keys
Отмена записи группой и остальными пользователями:
chmod go-w ~/
Настройка локальной машины
Полный доступ к папке .ssh только владельцу, остальным — полный запрет:
chmod rwx------ ~/.ssh
Права на запись и чтение для файла ключа только владельцу, остальным — полный запрет:
chmod rw------- ~/.ssh/*key*
После применения этих политик ошибка должна исчезнуть.
Зашифрованный домашний каталог
Если у вас есть зашифрованный домашний каталог, то SSH не сможет получить доступ к файлу authorized_keys, пока вы не пройдете аутентификацию. Поэтому SSH по умолчанию будет использовать вход по паролю. Чтобы решить эту проблему, создайте папку вне домашнего каталога с именем /etc/ssh/*username*. Этот каталог должен иметь права доступа rwxr-xr-x и принадлежать пользователю. Переместите в него файл authorized_keys (authorized_keys должен иметь права доступа rw-r—r— и принадлежать пользователю).
Затем отредактируйте файл /etc/ssh/sshd_config и добавьте в него запись:
AuthorizedKeysFile /etc/ssh/%u/authorized_keys
Перезагрузите службу SSH.
sudo service ssh restart (для Ubuntu / Debian / Mint Linux)
sudo service sshd restart (для CentOS / RHEL / Fedora Linux)
При следующем подключении по SSH вам не нужно будет вводить пароль.
Анализ логов подключения
При возникновении ошибок во время подключения вы можете проанализировать файл /var/log/auth.log, в котором будут указаны все попытки подключения к системе, а также механизмы, использованные для аутентификации.
Также детальную информацию о подключении можно получить с помощью опций -v, -vv или -vvv. Чем больше ключей -v (но не более 3), тем подробнее будет лог.
ssh -vvv hostname@remote_host
Вызов справки
Подробное описание команды (ее параметров, значений и дрю.) вы можете найти в документации, которая вызывается командой man, например:
man ssh
man sshd
Заключение
В тексте мы рассмотрели создание и авторизацию с помощью SSH-ключей на базе ОС Linux и Windows, а также разобрали некоторые ошибки, которые могут возникать при использовании такого способа авторизации. Использование SSH-ключей не только упрощает способ авторизации, но и увеличивает степень защиты вашего сервера.
Авторизация по RSA-ключам уже давно стала стандартом — стандартом хорошим, удобным, логичным и правильным. Это надежно и безопасно. Однако, в то время пока юниксы уверенно идут по пути повсеместной интеграции SSH-управления, пока появляется множество утилит управления и наблюдения за инфраструктурой средствами SSH, Windows стоит в сторонке от этого прогресса. Здесь напряженка с клиентами, тяжело найти достойную консоль и терминал, есть вопросы к агентам — но всё это тема для отдельной статьи. Здесь же речь пойдет о том, как упростить первый этап в настройке нового сервера — заливку своего RSA-ключа.
Пользователи *nix-систем должны знать о существовании команды ssh-copy-id: это просто bash-скрипт следующего содержания:
#!/bin/sh # Shell script to install your public key on a remote machine # Takes the remote machine name as an argument. # Obviously, the remote machine must accept password authentication, # or one of the other keys in your ssh-agent, for this to work. ID_FILE="${HOME}/.ssh/id_rsa.pub" if [ "-i" = "$1" ]; then shift # check if we have 2 parameters left, if so the first is the new ID file if [ -n "$2" ]; then if expr "$1" : ".*\.pub" > /dev/null ; then ID_FILE="$1" else ID_FILE="$1.pub" fi shift # and this should leave $1 as the target name fi else if [ x$SSH_AUTH_SOCK != x ] && ssh-add -L >/dev/null 2>&1; then GET_ID="$GET_ID ssh-add -L" fi fi if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then GET_ID="cat \"${ID_FILE}\"" fi if [ -z "`eval $GET_ID`" ]; then echo "$0: ERROR: No identities found" >&2 exit 1 fi if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2 exit 1 fi # strip any trailing colon host=`echo $1 | sed 's/:$//'` { eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 || true)" || exit 1 cat <<EOF Now try logging into the machine, with "ssh '$host'", and check in: ~/.ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. EOF
Занимается этот скрипт тем, что заливает пользовательский публичный ключ (по-умолчанию ~/.ssh/id_rsa.pub
на указанный сервер для указанного пользователя. Да, пара строк кода, но они упрощают жизнь. Что же делать, если под рукой только Windows? Как обычно, писать свой костыль.
Я не первый кто этим озадачился. Здесь, например, предлагается однострочный батник, делающий всё то же самое:
type public_id | plink.exe username@hostname "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys"
Есть и более допиленное решение, уже небольшой скрипт, на вход которому необходимо передать адрес сервера, пароль и ключевой файл:
:: from http://serverfault.com/questions/224810/is-there-an-equivalent-to-ssh-copy-id-for-windows :: expected parameters :: [email protected] password [id_ras.pub] ::usage: ssh-copy-id [email protected] password [identity file] ::@echo off IF "%~3"=="" GOTO setdefault set /p id=<%3 GOTO checkparams :setdefault set /p id=<id_rsa.pub :checkparams IF "%~1"=="" GOTO promptp IF "%~2"=="" GOTO promptp2 :exec :: To accept the signature the first time echo y | plink.exe %1 -pw %2 "exit" :: now to actually copy the key echo %id% | plink.exe %1 -pw %2 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" GOTO end :promptp set /p 1="Enter [email protected]: " :promptp2 set /p 2="Enter password: " GOTO exec :end pause
Я же пошёл немного дальше и написал реализацию на PowerShell. Главное отличие: при запуске мы получаем диалоговое окно для выбора файла, содержащего публичный ключ, после чего следует небольшая проверка, что файл действительно подходит по формату и может быть использован для авторизации. Далее — всё то же самое: авторизуемся на сервере и копируем содержимое файла.
# ssh-copy-id analog for Windows systems # Script to install your public key on a remote machine # The remote machine must accept password authentication, # or one of the other keys in your Putty Agent, for this to work. # # (c) soar - http://soar.name # Dialog for public key selection Function Select-File() { [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms"); $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog; $OpenFileDialog.Filter = "Public Keys (*.pub) | *.pub"; $OpenFileDialog.ShowHelp = $true; # Without this line - dialog not appears.. I don't understand why. [void] $OpenFileDialog.ShowDialog(); $OpenFileDialog.filename; } Function ShowMessage($title, $content, $type) { [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms"); [void][Windows.Forms.Messagebox]::show($content, $title, $type); } # Returns current script directory, plink.exe must be in same place Function Get-ScriptDirectory { $Invocation = (Get-Variable MyInvocation -Scope 1).Value; Split-Path $Invocation.MyCommand.Path; } $pubKeyFile = Select-File if (! $pubKeyFile) { ShowMessage 'Need to select file' 'Please, select public key file for upload to remote host' 'OK'; Exit; } $pubKey = Get-Content -LiteralPath $pubKeyFile; if (! ($pubKey -is [string]) -or ! $pubKey.StartsWith("ssh-")) { ShowMessage "Wrong file?" "Selected file not looks like valid SSH public key. It must starts with `"ssh-`" and contain one line." "OK" Exit; } $plinkExecutable = Join-Path (Get-ScriptDirectory) "plink.exe"; if ($args.Length) { foreach ($arg in $args) { & $plinkExecutable -ssh $arg "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; echo `"$pubKey`" >> ~/.ssh/authorized_keys" } } else { $hostname = Read-Host "Please enter target hostname (user@hostname):"; if ($hostname) { & $plinkExecutable -ssh $hostname "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; echo `"$pubKey`" >> ~/.ssh/authorized_keys" } } Write-Host "Press any key to continue ..." $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Данный скрипт использует plink, поэтому plink.exe
должен лежать рядом, в той же директории, что и скрипт.
21 Feb 2023 |
Create ssh-copy-id script for Windows |
Those of us who use linux with keyless logins and ssh , usually find the utility ssh-copy-id as a convenient way to copy the ssh ke into the authorized keys files of the destination server. This works great on Linux systems, but windows (and also Mac) don’t have a native version fo ssh-copy-id, of course you could find scripts online that do this.. but many are overkill basically re-creating the entire ssh client in code just for the purpose of copying over a single key. Also since this is a securtity realted operation , you want to be confident those scripts are only doing what they say they’re doing.
With that said I hope to address these issues in this post and show you a quick, short and most importantly easy to modify powershell script that you can use in any modern version of Windows.
Security and Concerns
Finally there’s security concerns about using these scripts, unless you go over everly line of of code you’re never really sure what they’re doing with your key. Because of this the code velow is short, in native powershell and very easy to use, you litterally can read the code in this post and res-assured it’s only doing what it’s supposed to.
SSH-COPY-ID in Powershell
Windows Powershell is the defacto Widnows command line programming language replacing the traditional DOS batch files, and has been in available since around Windows 7 (circa 2007) . You can find a useful Powershell cheat sheet here:
param ( [Parameter(Mandatory=$true)] [string]$connectionString, [Parameter(Mandatory=$true)] [string]$publicKeyFile ) $connectionParts = $connectionString.Split('@') if ($connectionParts.Length -ne 2) { throw "Invalid connection string format. Must be in the format 'user@hostname:port'" } $username = $connectionParts[0] $hostParts = $connectionParts[1].Split(':') $hostname = $hostParts[0] if ($hostParts.Length -gt 1) { $port = $hostParts[1] } else { $port = 22 } $sshDir = "$env:USERPROFILE\.ssh" if (!(Test-Path -Path $sshDir)) { New-Item -ItemType Directory -Path $sshDir | Out-Null } $sshPubKey = Get-Content $publicKeyFile $sshPubKeyFileName = Split-Path $publicKeyFile -Leaf $sshAuthorizedKeysFile = "$sshDir\authorized_keys" $sshConnection = New-SSHSession -ComputerName $hostname -Credential $username -Port $port $sshAuthorizedKeys = Invoke-SSHCommand -SessionId $sshConnection.SessionId -Command "cat $sshAuthorizedKeysFile" | Select-Object -ExpandProperty Output if ($sshAuthorizedKeys -notcontains $sshPubKey) { Invoke-SSHCommand -SessionId $sshConnection.SessionId -Command "echo `"$sshPubKey`" >> $sshAuthorizedKeysFile" } Write-Output "Public key added to $hostname authorized_keys file" ?
This script requires the New-SSHSession
and Invoke-SSHCommand
cmdlets, which are available in the PowershellSSH
module. You can install this module by running Install-Module -Name PowershellSSH
.
How it works
The script takes three parameters: the username on the remote host, the hostname or IP address of the remote host, and the path to the public key file. The script then creates the ~/.ssh
directory on the remote host if it doesn’t exist, reads the public key from the specified file, and adds it to the authorized_keys
file on the remote host if it’s not already there. Finally, the script outputs a message indicating that the public key was added to the authorized_keys
file.
To use this script, save it to a file with a .ps1
extension, and then run it with the required parameters. For example:
.\ssh-copy-id.ps1 user@remotehost:port -publicKeyFile C:\Users\myuser\.ssh\id_rsa.pub