LoginSignup
20
20

More than 5 years have passed since last update.

EC2のsshホスト鍵を得て手元のknown_hostsと比較

Posted at

EC2インスタンスにsshで接続する際、もやもやした思いを抱きながらssh -oStrictHostKeyChecking=noしている人も多いのではないかと思います。理想はStrictHostKeyCheckingの際に不一致の場合はTTYでaskするのではなく、コマンドを呼び出してくれるといいのですが、手元の環境に降りてくるのがいつになるかもわからないし、今できることを考えていきます。

実際に何が必要か考えると、1.正しいホスト鍵を得る 2.known_hostsと比較する、になります。

前者はaws ec2 get-console-outputで得ることができます。インスタンスが再起動された場合(init.dとかで毎回表示するか、起動ごとにホスト鍵を作り直すか)や、起動後にコンソールに64KBの出力がある場合(こちらは対策が厄介なので、別の場所に保存するという戦略の方がいいかもしれない)の対策が必要かもしれません。

後者は特に悩む必要も無いので淡々とやります。

以下のスクリプトによって、正しいホスト鍵との比較が出来るようになります。ここではエラーにしていますが、ssh-keygen -Rで既存の鍵を消した上でknown_hostsにあたらしい鍵を登録するようにすると、sshコマンドを実行する前に叩いておくとそこそこ便利なヘルパースクリプトがつくれるでしょう。

#!/usr/bin/env ruby
require 'open3'

def hostname2instance_id(hostname)
  case hostname
  when /\.amazonaws.com\z/
    key = 'dns-name'
  when /\.internal\z/
    key = 'private-dns-name'
  when /\A10\./
    key = 'private-ip-address'
  when /\A\d+\.\d+.\d+.\d+\z/
    key = 'ip-address'
  else
    abort "unknown hostname type '#{hostname}'"
  end
  o, s = Open3.capture2('aws', 'ec2', 'describe-instances', '--filters', "Name=#{key},Values=#{host<
  res = o[/"InstanceId"\s*:\s*"([^"]+)"/, 1]
  unless res
    puts "cannot get InstanceId for '#{hostname}' #{s.inspect}"
    puts o
    abort
  end
  res
end
hostname = ARGV.shift
puts "hostname: #{hostname}"
instance_id = hostname2instance_id(hostname)
puts "InstanceId: #{instance_id}"

o, s = Open3.capture2('aws', 'ec2', 'get-console-output', '--instance-id', instance_id)
server_keys = o[/-----BEGIN SSH HOST KEY KEYS-----(.*)-----END SSH HOST KEY KEYS-----/, 1]
server_keys.gsub!(/\\r\\n/, "\n")
server_keys.strip!
puts server_keys

o, s = Open3.capture2('ssh-keygen', '-qF', hostname)
puts "known host key: #{o}"
unless o.scan(/^\S+\s+([a-zA-Z0-9=+\/]+)/).any?{ server_keys.include?($1) }
  abort "server key doesn't match"
end
20
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20