хранение открытых ключей SSH в DNS
В этой статье описывается, как организовать хранение открытых ключей SSH в DNS и обеспечить дополнительную проверку подлинности удаленного хоста с их помощью.
Описываемый способ повышения безопасности SSH является спорным. Если кому-то удалось выполнить MITM-атаку и внедриться внутрь SSH-сеанса, он точно также сможет выполнить и DNS-spoofing. Он будет намного более ценным, когда будет доступна поддержка DNSSEC.
При подключении к очередному новому SSH-серверу вам на экран выдается приглашение с информацией об открытом ключе сервера. Тем самым сервер пытается доказать вам свою подлинность. Как вы проверяете, что этот сервер действительно тот, за кого себя выдает? В идеале, вы должны знать отпечаток ключа сервера, который можно получить с помощью команды ssh-keygen, находясь на самом сервере.
igor@chub:in$ ssh xgu.ru
The authenticity of host 'xgu.ru (194.150.93.78)' can't be established.
RSA key fingerprint is fb:a6:01:55:48:7d:2b:2c:23:ff:37:99:c8:0e:65:36.
Are you sure you want to continue connecting (yes/no)? no
Host key verification failed.
igor@chub:in$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
1024 fb:a6:01:55:48:7d:2b:2c:23:ff:37:99:c8:0e:65:36 /etc/ssh/ssh_host_rsa_key.pub
Вы должны знать отпечатки ключей (key fingerprint) - записать их или сохранить на каком-то носителе, который всегда с вами.
После первого подключения ключ сохраняется в файле ~/.ssh/known_hosts (либо вместе с именем/адресов хоста, которому соответствует ключ, либо, в более новых версиях, с хэшем этого адреса; если нужно хранить адрес не в хэшированном виде, установите HashKnownHosts no в /etc/ssh/ssh_config или в ~/.ssh/config). При последующих подключениях сравнение происходит с этим ключом. Если замечены отличия, ssh сообщит вам о них, и подключиться, в общем случае, уже не получится.
Наиболее небезопасным является именно момент первого подключения и первого набора слова yes. Некоторые организации размещают свои ключи на доступных по сети ресурсах, например, в вебе, другие полагаются на то, что пользователь/администратор запомнит эти ключи сам. Как правило, в последнем случае yes просто набирается вслепую.
построение списка ключей
Клиент ssh помимо традиционно используемого пользовательского файла ~/.ssh/known_hosts в поисках отпечатков ключей может читать и глобальный файл /etc/ssh/ssh_known_hosts, если он существует.
Создать такой файл, который будет содержать, например, ключи хостов в локальной сети, можно с помощью программы ssh-keyscan.
ssh-keyscan -t rsa,dsa cfmaster.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa cfmaster >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa mine.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa mine >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa yours.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa yours >> /etc/ssh/ssh_known_hosts
или еще проще:
for host in {cfmaster,mine,yours}{,.my.flat}
do
ssh-keyscan -t rsa,dsa $host
done
Обратите внимание, что для каждого хоста команда выполняется дважды: с его коротким и длинным именем. Ключ ищется по имени, которое точно соответствует имени, указанному при вызове ssh. При доступе по IP-адресам в данном случае приглашение будет по-прежнему выводиться.
хранение открытых ключей SSH в DNS
В современных версиях SSH-клиентов есть возможность проверить ключ на соответствие ключу, хранящемуся в DNS. Эта возможность включается при помощи опции VerifyHostKeyDNS в конфигурационном файле программы ssh.
Если ключ найден в DNS, сообщение будет выглядеть так:
%$ ssh localhost -o "VerifyHostKeyDNS=yes"
yes authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
В противном слуае сообщение будет выглядеть иначе:
RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
Создание записей DNS о ключах выполняется так:
%$ ssh-keygen -r $(hostname --fqdn) -f /etc/ssh/ssh_host_rsa_key.pub
xgu.ru. IN SSHFP 1 1 4db0d50059205a85dc890b6ce430e1af96ac0f74
Будет создана SSHFP-запись на основе существующего файла.
Также можно использовать скрипт:
#!/usr/bin/gawk -f
BEGIN {
hostname=ARGV[1]
keygen="ssh-keygen -gr " hostname " -f /dev/stdin"
while(keygen | getline) {
if($8) {
rr=sprintf(":%s:44:\\%03.3o\\%03.3o", hostname, $6, $7)
for(i=1; i<length($8); i+=2) {
rr=sprintf("%s\\%03.3o", rr, strtonum("0x" substr($8, i, 2)))
}
print "# " $0
print rr ":::"
}
}
}
Пример вызова:
%# ssh_host_key_to_sshfp $(hostname --fqdn) </etc/ssh/ssh_host_rsa_key.pub
Полученная запись должна быть добавлена в файл соответствующей зоны DNS.
Игорь Чубин. Актуальную версию статьи можно найти по адресу http://xgu.ru/wiki/ssh/hostkeydns.
Описываемый способ повышения безопасности SSH является спорным. Если кому-то удалось выполнить MITM-атаку и внедриться внутрь SSH-сеанса, он точно также сможет выполнить и DNS-spoofing. Он будет намного более ценным, когда будет доступна поддержка DNSSEC.
При подключении к очередному новому SSH-серверу вам на экран выдается приглашение с информацией об открытом ключе сервера. Тем самым сервер пытается доказать вам свою подлинность. Как вы проверяете, что этот сервер действительно тот, за кого себя выдает? В идеале, вы должны знать отпечаток ключа сервера, который можно получить с помощью команды ssh-keygen, находясь на самом сервере.
igor@chub:in$ ssh xgu.ru
The authenticity of host 'xgu.ru (194.150.93.78)' can't be established.
RSA key fingerprint is fb:a6:01:55:48:7d:2b:2c:23:ff:37:99:c8:0e:65:36.
Are you sure you want to continue connecting (yes/no)? no
Host key verification failed.
igor@chub:in$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
1024 fb:a6:01:55:48:7d:2b:2c:23:ff:37:99:c8:0e:65:36 /etc/ssh/ssh_host_rsa_key.pub
Вы должны знать отпечатки ключей (key fingerprint) - записать их или сохранить на каком-то носителе, который всегда с вами.
После первого подключения ключ сохраняется в файле ~/.ssh/known_hosts (либо вместе с именем/адресов хоста, которому соответствует ключ, либо, в более новых версиях, с хэшем этого адреса; если нужно хранить адрес не в хэшированном виде, установите HashKnownHosts no в /etc/ssh/ssh_config или в ~/.ssh/config). При последующих подключениях сравнение происходит с этим ключом. Если замечены отличия, ssh сообщит вам о них, и подключиться, в общем случае, уже не получится.
Наиболее небезопасным является именно момент первого подключения и первого набора слова yes. Некоторые организации размещают свои ключи на доступных по сети ресурсах, например, в вебе, другие полагаются на то, что пользователь/администратор запомнит эти ключи сам. Как правило, в последнем случае yes просто набирается вслепую.
построение списка ключей
Клиент ssh помимо традиционно используемого пользовательского файла ~/.ssh/known_hosts в поисках отпечатков ключей может читать и глобальный файл /etc/ssh/ssh_known_hosts, если он существует.
Создать такой файл, который будет содержать, например, ключи хостов в локальной сети, можно с помощью программы ssh-keyscan.
ssh-keyscan -t rsa,dsa cfmaster.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa cfmaster >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa mine.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa mine >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa yours.my.flat >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,dsa yours >> /etc/ssh/ssh_known_hosts
или еще проще:
for host in {cfmaster,mine,yours}{,.my.flat}
do
ssh-keyscan -t rsa,dsa $host
done
Обратите внимание, что для каждого хоста команда выполняется дважды: с его коротким и длинным именем. Ключ ищется по имени, которое точно соответствует имени, указанному при вызове ssh. При доступе по IP-адресам в данном случае приглашение будет по-прежнему выводиться.
хранение открытых ключей SSH в DNS
В современных версиях SSH-клиентов есть возможность проверить ключ на соответствие ключу, хранящемуся в DNS. Эта возможность включается при помощи опции VerifyHostKeyDNS в конфигурационном файле программы ssh.
Если ключ найден в DNS, сообщение будет выглядеть так:
%$ ssh localhost -o "VerifyHostKeyDNS=yes"
yes authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
В противном слуае сообщение будет выглядеть иначе:
RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
Создание записей DNS о ключах выполняется так:
%$ ssh-keygen -r $(hostname --fqdn) -f /etc/ssh/ssh_host_rsa_key.pub
xgu.ru. IN SSHFP 1 1 4db0d50059205a85dc890b6ce430e1af96ac0f74
Будет создана SSHFP-запись на основе существующего файла.
Также можно использовать скрипт:
#!/usr/bin/gawk -f
BEGIN {
hostname=ARGV[1]
keygen="ssh-keygen -gr " hostname " -f /dev/stdin"
while(keygen | getline) {
if($8) {
rr=sprintf(":%s:44:\\%03.3o\\%03.3o", hostname, $6, $7)
for(i=1; i<length($8); i+=2) {
rr=sprintf("%s\\%03.3o", rr, strtonum("0x" substr($8, i, 2)))
}
print "# " $0
print rr ":::"
}
}
}
Пример вызова:
%# ssh_host_key_to_sshfp $(hostname --fqdn) </etc/ssh/ssh_host_rsa_key.pub
Полученная запись должна быть добавлена в файл соответствующей зоны DNS.
Игорь Чубин. Актуальную версию статьи можно найти по адресу http://xgu.ru/wiki/ssh/hostkeydns.
Сетевые решения. Статья была опубликована в номере 11 за 2007 год в рубрике sysadmin