ssh certificados de chave de host, localize o período de validade remotamente?

7

Eu tenho um ambiente onde eu uso certificados ssh para autenticar chaves de host ssh. Eu estou falando sobre o tipo de certificados criados executando ssh-keygen -s /path/to/ca -h ... . Esses certificados também são criados com um intervalo de validade, informando quando eles expirarão. Esses certificados agora estão em uso agora o tempo suficiente para que eu precise começar a monitorá-los, para obter um alerta quando eles começarem a ficar próximos de expirar.

De qualquer forma, posso fazer uma conexão remota, sem efetuar login e, de alguma forma, obter o intervalo de validade exibido alt. obter o certificado baixado? A execução de ssh -vvv não parece exibir as informações de que preciso. O ssh-keyscan não parece ser certificado. Talvez alguma biblioteca que eu não tenha olhado de perto o suficiente?

No pior caso, posso sempre escrever um plug-in de monitoração que é executado localmente e analisa a saída de ssh-keygen -L -f . Ainda assim, um rastreamento remoto realmente parece a abordagem preferencial.

    
por andol 12.08.2014 / 23:16

3 respostas

6

Isso é possível, mas falta suporte a ferramentas. Eu encontrei uma biblioteca que fala o protocolo SSH bem o suficiente para me deixar escrever uma ferramenta para extrair o certificado de host valid_before tempo sem um login ssh completo. Aqui está, na linguagem Go. Espero que ajude.

package main

import "golang.org/x/crypto/ssh"
import "fmt"
import "os"
import "time"

func ignoreCertChain(auth ssh.PublicKey, address string) bool {
    return true // Pretend all certificates are trusted.
}

var sawACert bool

func examineCert(cert *ssh.Certificate) bool {
  expires := cert.ValidBefore
  var humanReadable string
  if expires >= ssh.CertTimeInfinity {
    humanReadable = "infinity"
  } else if expires < (1 << 63) {
    humanReadable = time.Unix(int64(expires), 0).Format(time.RFC3339)
  } else {
    humanReadable = "the distant future"
  }
  fmt.Println("Cert expires at time", expires, "(" + humanReadable + ")")
  sawACert = true
  return true  // Reject the cert, to force early connection close.
}

func main() {
  serverHostPort := os.Args[1]
  checker := &ssh.CertChecker{
    IsHostAuthority: ignoreCertChain,
    IsRevoked: examineCert,
  }
  config := &ssh.ClientConfig{
    User: "test-sshcertscan-not-a-real-login-attempt",
    Auth: []ssh.AuthMethod{
      ssh.Password(""),
    },
    HostKeyCallback: checker.CheckHostKey,
  }
  sawACert = false
  client, err := ssh.Dial("tcp", serverHostPort, config);
  if err != nil && !sawACert {
    panic(fmt.Sprint("Cannot connect to ", serverHostPort, ", error: ",
                     err.Error()))
  } else if client != nil {
    defer client.Close()
  }
}

(Instruções de uso rápido: instale , salve o código visto acima em sshcertscan.go, execute go build sshcertscan.go e aponte em um servidor ssh na porta 22 do examplehost com ./sshcertscan examplehost:22 .)

    
por 17.08.2014 / 19:29
1

Infelizmente, não conheço nenhuma ferramenta de código aberto. Parece que o nmap seria capaz de recuperá-lo de alguma forma com scripts NSE (mas precisa de alguns ajustes - verifique / usr / share / nmap / scripts).

O servidor SSH do Tectia do SSH inclui uma ferramenta chamada ssh-fetchkey que recupera o certificado e, em seguida, você pode usar ssh-certview para ver os detalhes.

    
por 15.08.2014 / 22:45
0

Eu tenho medo que a resposta seja "isso não é possível". Pelo menos não de qualquer maneira que eu encontrei, usando o cliente openssh ou a biblioteca SSH paramiko para python. Eu sugeriria uma verificação local como você descreveu, combinada com uma verificação remota mais simples que verifica se a chave usada pelo SSHD é a chave que você acabou de verificar a validade do certificado.

    
por 15.08.2014 / 15:52