Como posso escrever um programa (script) para remover as teclas de host obsoletas de ~/.ssh/conhecido_hosts?

StackOverflow https://stackoverflow.com/questions/1933871

  •  20-09-2019
  •  | 
  •  

Pergunta

Eu uso um cluster de cerca de 30 máquinas que foram reconfiguradas recentemente com novas teclas de host OpenSSH. Quando tento fazer login em um, recebo esta mensagem de erro (muitas linhas removidas para a brevidade):

@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
The fingerprint for the RSA key sent by the remote host is
52:bb:71:83:7e:d0:e2:66:92:0e:10:78:cf:a6:41:49.
Add correct host key in /home/nr/.ssh/known_hosts to get rid of this message.
Offending key in /home/nr/.ssh/known_hosts:50

Eu posso remover a linha ofensiva manualmente, nesse caso, recebo uma reclamação diferente sobre os endereços IP, o que requer remover outro Linha manualmente, e não tenho vontade de repetir este exercício 29 vezes. Eu gostaria de escrever um programa para fazer isso. Infelizmente, a linha no arquivo .ssh não contém mais o nome do host e o endereço IP no texto claro, como fez nas versões anteriores.

Então aqui está minha pergunta:

  • Dado um nome de host e um endereço IP, como posso escrever um programa para descobrir quais linhas do meu ~/.ssh/known_hosts Armazene uma chave host SSH para esse host ou endereço IP?

Se eu puder recuperar essas informações, acho que posso fazer o resto.


Nota de rodapé: eu preferiria codificar em bash/ksh/sh ou c ou lua; Meu Perl e Python estão muito enferrujados.


Esclarecimentos:

  • Não quero remover o arquivo inteiro e repovoar -o; Ele contém mais de cem teclas validadas que eu prefiro não validar novamente.

  • Se eu mantenho uma única cópia mestre ou várias réplicas, o problema de esfregar um grande grupo de chaves obsoletas do host permanece.

Responda

Aqui está o script da Lua que escrevi usando ssh-keygen -F:

#!/usr/bin/env lua

require 'osutil'
require 'ioutil'

local known = os.getenv 'HOME' .. '/.ssh/known_hosts'

local function lines(name)
  local lines = { }
  for l in io.lines(name) do
    table.insert(lines, l)
  end
  return lines
end

local function remove_line(host)
  local f = io.popen('ssh-keygen -F ' .. os.quote(host))
  for l in f:lines() do
    local line = l:match '^# Host %S+ found: line (%d+) type %u+$'
    if line then
      local thelines = lines(known)
      table.remove(thelines, assert(tonumber(line)))
      table.insert(thelines, '')
      io.set_contents(known, table.concat(thelines, '\n'))
      return
    end
  end
  io.stderr:write('Host ', host, ' not found in ', known, '\n')
end

for _, host in ipairs(arg) do
  local ip = os.capture('ipaddress ' .. host)
  remove_line(host)
  remove_line(ip)
end
Foi útil?

Solução 2

Se eu quiser descobrir em que linha a entrada de um host vive,

ssh-keygen -F hostname

O mesmo truque funciona com endereços IP.

Outras dicas

ssh-keygen -R hostname
ssh-keygen -R ipaddress

Pessoalmente, esfrego os endereços IP com um loop e Perl e removo os conflitos manualmente.

$!/usr/bin/perl
for (1..30){
     `ssh keygen -R 192.168.0.$_`; #note: backticks arent apostrophies
}

Toque e edite "ClearKey.sh" ou o que sempre o faz feliz.

#! /bin/bash
# $1 is the first argument supplied after calling the script

sed -i "$1d" ~/.ssh/known_hosts
echo "Deleted line $1 from known_hosts file"

Deve ser capaz de fazer "ClearKey.sh 3" e ele excluirá a linha ofensiva!

Eu costumo fazer o seguinte no script bash checkssh Para remover automaticamente a linha:

#!/bin/bash

# Path to "known_hosts" file
KH=~/.ssh/known_hosts
# Find the host in the file, showing line number
L=`grep -i -n $1 $KH`
# If line is not found, exit
[[ $? -ne 0 ]] && exit
# Isolate line number
L=`echo $L | cut -f 1 -d :`
sed -i "${L}d" $KH

Você pode adicionar ssh $1 exit No final de recriar automaticamente uma entrada no arquivo, se o seu SSH estiver configurado para fazê-lo.

Chame como checkssh <hostname>.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top