SSH: Почему мне нужно повторно проверять отпечаток пальца при подключении к тому же серверу из другого домена?

Далее я говорю о клиенте OpenSSH, установленном по умолчанию на debian.

Я хотел бы иметь несколько (под) доменов, указывающих на мой сервер (а) (то есть несколько на сервер), то есть database.example.com, webserver.example.com и т. д. Я хочу этого, потому что у меня несколько серверов, и иногда я не знаю наизусть, какая служба на каком сервере работает. Я хочу управлять этим с помощью DNS, имея субдомен для каждой службы, а затем я могу использовать этот субдомен для SSH на правильном сервере, не запоминая, на каком сервере работает служба.

Проблема: кажется, что отпечаток пальца включить доменное имя. Итак, если database.example.com и webserver.example.com указывают на один и тот же IP-адрес, и я использовал database.example.com и проверил отпечаток пальца (поэтому он добавлен в known_hosts), тогда мне нужно снова выполнить проверку, если я подключусь к SSH сервер через webserver.example.com позже.

Я не понимаю, почему здесь используется домен, а не IP-адрес, на который разрешается домен. Есть ли способ использовать IP вместо домена в отпечатке пальца? (может быть, какой-то вариант конфигурации).

И если это так, может ли это вызвать проблемы с безопасностью?

И почему это вообще реализовано таким образом? Кроме того, насколько я понимаю, отпечаток получен из открытого ключа сервера, для которого только сервер имеет соответствующий закрытый ключ. Так зачем вообще нужно включать что-то вроде домена или IP? Разве это не мешает мне случайно подключиться к одному из моих других серверов, которые я сохранил в known_hosts?

Добавление ключей для каждого субдомена, который я использую для подключения к серверу на known_hosts, - мой наименее предпочтительный вариант, так как это намного больше работы и предлагает игнорировать проверку ключа, так как каждый привык к тому факту, что несколько раз спрашивает, верен ли ключ для одного и того же сервера.

Я думаю этот пост имеет отношение, но он просто говорит, что он обработан таким образом, а не почему и есть ли способ изменить это поведение.

Заранее спасибо

Изменить: Я также нашел этот пост , в котором теперь предлагается отключить StrictHostKeyChecking , но, насколько я понимаю, это позволяет добавлять все отпечатки пальцев по ssh, что, насколько я понимаю, является проблемой с точки зрения безопасности. Я хочу, чтобы, даже если я использую домен для подключения к серверу, IP-адрес использовался для проверки отпечатков пальцев (ssh все равно разрешает IP, что вы можете увидеть при использовании флага -vvv )

1
задан 21 March 2020 в 19:46
2 ответа

Вы можете разделить запятыми записи в ~ / .ssh / known_hosts

. Вы можете сделать это:

database.example.com,webserver.example.com,database,webserver,10.1.2.3 ssh-rsa …

Вы можете добавить альтернативные имена и IP-адреса для хоста в эту запятую -delimited формат.

Здесь используются настоящие имена хостов, а не псевдонимы Host , которые вы можете создать в файле ~ / .ssh / config .

Найдите повторяющиеся записи в known_hosts

Я создал крошечный скрипт под названием ssh-hosthashes , который может находить повторяющиеся записи в файле known_hosts . Используйте его и вышеупомянутые знания, чтобы свернуть их.

Вот его результат для ключа Github (который, как вы могли заметить, я немного свернул, но недостаточно). Коллизии перечислены по номеру строки:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTt
...JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
    72: github.com,gist.github.com,192.30.252.128,192.30.252.129,192.30.252.130,192.30.252.131,192.30.252.140,192.30.252.141,192.30.252.142,192.30.252.143
    93: 192.30.253.113
    95: 192.30.253.118
    96: 192.30.253.119
    97: 192.30.253.112
    109: 192.30.255.113
    110: 192.30.255.112
    155: 140.82.113.3
    158: 140.82.114.4
    161: 140.82.113.4

Подтверждение с помощью ssh localhost

Еще одна вещь, которую я часто делаю, - это проверяю, что я не сохранил отпечаток пальца для localhost. Таким образом, я могу подключиться по ssh к серверу с хоста, на котором сохранен и доверять отпечаток пальца, запустить ssh localhost с этого сервера и сопоставить этот отпечаток с отпечатком, предложенным клиентом, у которого он не сохранен. уже. Однако следите за различными типами ключей (или форматами отпечатков пальцев). (Это полезно только потому, что дайджест, предоставленный клиентом ssh , отличается от формата, хранящегося в файлах known_hosts .)

0
ответ дан 30 March 2020 в 00:20

Чтение ответа @AdamKatz заставило меня захотеть отсортировать мой файл known_hosts, поэтому я написал скрипт, который делает это, найдите его ниже (я тщательно написал его, но я только минимальное тестирование, так что используйте на свой страх и риск).

Что касается первоначального вопроса, я бы рекомендовал использовать запись конфигурации HostKeyAlias ​​в .ssh/config, как объяснено в этом ответе ServerFault: «SSH в ящик с часто меняющимся IP».

SSH: настройте ssh_config для использования определенного файла ключа для определенного отпечатка сервера


# (python3)
# `organize_known_hosts.py`

# For all known hosts, sort them by algo+hashed value, grouping the known IPs and domain names into one comma-separted list

# Usage:
# Generated the sorted file:
#     cat ~/.ssh/known_hosts | python organize_known_hosts.py > /tmp/known_hosts
# Print it for visual check
#     cat /tmp/known_hosts
#     mv /tmp/known_hosts ~/.ssh/

import sys
from collections import namedtuple

class Entry(namedtuple("Entry", ["domainString", "algorithm", "hash"])):
    def __str__(self):
        return f"{self.domainString} {self.algorithm} {self.hash}"
    
    def rightHandSide(self):
        """algorithm+hash"""
        return f"{self.algorithm}.{self.hash}"

entryMap = {}

for lineNumber, line in enumerate(sys.stdin, start=1):
    content = line.strip().split()
    if len(content) == 0:
        continue # empty line -> skip
    elif line[0].startswith("#") or len(content) != 3:
        if not line[0].startswith("#"):
            sys.stderr.write(f"could not parse a line; line moved to top|{lineNumber}: '{line}'\n")
        sys.stdout.write(line)
        continue # comment or erroneous line -> skip
    entry = Entry(*content)
    entryMap.setdefault(entry.rightHandSide(), []).append(entry)

compactEntryList = []

for k, entryList in sorted(entryMap.items()):
    domainList = []
    ipList = []
    for entry in entryList:
        for domainOrIp in entry.domainString.split(","):
            if 'a' <= domainOrIp[0].lower() <= 'z':
                domainList.append(domainOrIp)
            else:
                ipList.append(domainOrIp)
    domainString = ",".join(sorted(domainList) + sorted(ipList))
    compactEntryList.append(Entry(domainString, *k.split(".")))

sys.stdout.write("\n".join(map(str, compactEntryList)))
0
ответ дан 28 March 2021 в 16:54

Теги

Похожие вопросы