パスワード無しでSSH
www.ssh.com の ssh (有料) は対象外
2001-07-10 作成 福島
2001-08-11 更新 福島
2001-08-16 更新 福島
2001-10-21 更新 福島
2002-03-18 更新 福島
2002-07-20 更新 福島
TOP > tips > ssh-shosts
OpenSSH 2.9p1 で .shosts を使用するときの注意点
・.shosts は ssh protocol 1 のみ有効 (ssh protocol 2 では取り扱わないので注意)
  指定方法は以下のいずれか
  1. sshd_config (サーバ側設定ファイル) に
     Protocol 1
     あるいは
     Protocol 1,2
     と記述する
     ssh, scp コマンドに有効
  2. ssh (クライアントプログラム) に -1 オプションをつける
     ssh コマンドに有効
 3. ssh_config (クライアント側設定ファイル) に
    Protocol 1
    と記述する
     ssh コマンドに有効
・クライアント側のポート番号は 512 <= X < 1024 の範囲であること
 限定しなくても良いような気がするが…。
 理由は良く分からないが、接続元の root しか使えないポートからアクセスしないと接続先で弾かれる。
 (コメントには、「侵入者に root を取られた時にはこのポートも使われてしまう」云々が書いてあった)
 これを回避するためにはオプション
 UsePrivilegedPort yes
 を ssh_config (クライアント側コンフィグ) に指定する。
 コマンドラインからの指定は
 ssh -o 'UsePrivilegedPort yes'
 ssh protocol 1 を指定した場合、大きなポート番号でも接続できます。
sshd_conf, ssh_conf のありか
/etc/ssh/*
/usr/local/etc/*
のどちらか。
sshd -f /etc/ssh/sshd_conf 等としての起動も可。
sshd_config を更新した後は sshd デーモンのリスタートが必要。
/usr/local/etc/sshd_config の注意点
| 
PidFile /var/run/sshd.pid       PID ファイル名 (/var/run/sshd.pid がデフォルト)
Port 22                         ポート番号 (22 がデフォルト)
PermitRootLogin no              root のログインは禁止 (no を指定)
IgnoreRhosts no                 ~/.rhosts ~/.shosts を無視しない (no を指定)
RhostsAuthentication no         ~/.rhosts を有効にしない (no を指定)
RhostsRSAAuthentication yes     ~/.shosts を有効にする (yes を指定)
#AllowHosts host.trust.com      SSH 2.9 には存在しない
AllowUsers TargetUserID         特定のユーザ ID を有効にする
 | 
AllowUsers を指定すると、他のユーザが自動的に DenyUsers になるので注意!!
.shosts が指定してあっても、DenyUsers であれば無視される(ログインできない)
~/.ssh/authorized_key 0644
・~/.shosts の使い方 (誰を自分とみなすかを記述する)
TargetUserID@target.servers.com <- Visitor1@host.trust1.com     ---(a)
TargetUserID@target.servers.com <- Visitor2@host.trust2.com     ---(b)
を許可する場合
target.servers.com:/home/TargetUserID/.shosts 0600
| 
host.trust1.com Visitor1     ---(a)
host.trust2.com Visitor2     ---(b)
 | 
ログインコマンドは
host.trust1.com:Visitor1$ ssh -1 -o 'UsePrivilegedPort yes' -l TargetUserID target.servers.com
とする。(青字はプロンプトです)
相手の公開鍵 (互いのサーバ鍵、ユーザ鍵) がそれぞれ必要
1.ローカル、リモート共に相手サーバの公開鍵が必要。(.ssh/known_hosts 0644)
 ssh や slogin でログインしたときに公開鍵を登録するかを聞いてくるので、
 これを互いに行うことで登録できる。
 それが出来ないときは、/usr/local/etc/ssh_host_key.pub をコピーし、適宜修正して .ssh/known_hosts に加える
 xxxxx...xSPrrr@hostnameLF
 というフォーマットなので、(xxxxx...x は公開鍵、rrr@hostname は管理者アドレス)
 FQDN,IPSPxxxxx...xLF
 というフォーマットに変更して格納すれば良い。 (FQDN はコピー元のホスト名、IP はコピー元の IP アドレス)
 SP は空白 1 文字
 LF は改行 1 文字
 ※ログイン時には、パスワードを入力する前に公開鍵の登録を聞いてくる。
  つまり、ログインは出来なくても良い。(→ パスワードが設定されてなくても可)
 ※ protocol 1 を使用するため、コマンドは ssh -1 を使用します。
  そうしないと .ssh/known_hosts に登録できません。
 ※ .ssh/known_hosts2 は protocol 2 のファイルです。混同し易いので注意。
2.ローカル、リモート共に相手ユーザの公開鍵が必要。(.ssh/authorized_keys 0644)
 互いに相手の .ssh/identity.pub を自分の .ssh/authorized_keys に追加する。
 相手が .ssh/identity.pub を持っていなければ、ssh-keygen で作成する。
 $ ssh-keygen                ~/.ssh/identity と ~/.ssh/identity.pub を作る (それぞれ、バイナリとテキスト)
 $ ssh-keygen -t rsa         ~/.ssh/id_rsa と ~/.ssh/id_rsa.pub を作る (新バージョンはこちらを使う)
 $ ssh-keygen -f file        file と file.pub を作る (それぞれ、バイナリとテキスト)
 ssh-keygen を実行すると pass phrase (パスフレーズ) の入力を行うが、ここでは空を指定する。
 空を指定しないと、ログイン時にパスフレーズを聞かれてしまう。
運用時の弱点
弱点1..shosts の許可を限定出来ない。
弱点2.scp コマンドが接続先の shell を介してして動作する。
説明と対処1..shosts の許可を限定出来ない。
  .shosts を許可してしまうと、全ユーザに許可することになる。
  例えば、
   ・UserA に .shosts を許可
   ・UserB に .shosts を禁止
   という条件を同時に満たすことが出来ない。
   UserA は MachineA から接続 (MachineA は信頼性が高い)
   UserB は MachineB から接続 (MachineB は管理者がタコ)
   という状況でも UserB に .shosts を認める事になってしまう。
   (UserB には パスワードログインだけを認めたいのに…)
  対処 (別ポートで sshd を立ち上げる)
   通常 sshd は Port 22 で動作するが、これとは別のポートで複数動作させ、AllowUsers での制御を行う。
   方法は幾つかあるが、変更した設定ファイル (sshd_config_another) が別途必要 (当然自分で作ること)。
   1. inetd の場合 (root 権限が必要)
     /etc/services
     sshd-another PortNumber/tcp
     /etc/inetd.conf
     sshd-another stream tcp nowait root /usr/local/sbin/sshd sshd-another -i -f sshd_config_another
   2. standalone の場合 (root 権限が必要)
     /etc/rc.d/init.d/sshd-another として、
     /etc/rc.d/init.d/sshd を変更したスクリプトを登録する
     /usr/local/sbin/sshd -p PortNumber -f sshd_config_another       変更個所はこの行
   3.ユーザ権限で起動する場合 (root 権限は不要)
     /usr/local/bin/ssh-keygen -q -b 1024 -f hostkey_another -C '' -N ''       ホストキーの作成
     /usr/local/sbin/sshd -p PortNumber -f sshd_config_another -h hostkey_another
     クライアントは
     /usr/local/bin/ssh -p PortNumber -1 -o 'UsePrivilegedPort yes' -l TargetUserID ServerName
     等として接続する。
     ※注意1:sshd が libwrap.a 付きでコンパイルされている場合、
          /etc/hosts.allow /etc/hosts.deny が有効になる。
          この制限を越えるには管理者の協力が必要。
          (対策: libwrap.a 無しでコンパイル (--without-tcp-wrappers) すれば考えなくて良い)
     ※注意2:PAM を使用している環境でパスワードログインをするとき、
          /etc/pam.d/sshd が可読である必要がある。
          この制限を越えるには管理者の協力が必要。
          (.shosts だけを使うので、ログインは行わないため考えなくて良い)
     ※注意3:他ユーザのログインは不能。
          sshd を起動したユーザ以外の権限は無い。
     ※注意4:nohup コマンドは不要。
          常駐させたくないときは -d オプションを使用する。
     ※注意5:上記のようにホストキーを自前で用意する (本物は root しか読めないため) ので、
          クライアント機の .ssh/known_hosts で矛盾が起きてしまう。
          (対策1. UserKnownHostFile を指定して回避する)
          (対策2. ssh protocol 2 で接続すれば known_hosts は使用しない)
説明と対処2.scp コマンドが接続先の shell を介して動作する。
  scp でファイル転送するためだけのアカウントを用意したい時、ログインもできてしまう。
  パスワードを知っている人間が公開鍵を登録することにより、他のサーバからもアクセス出来てしまう。
  対処 (パスワードを無効にし、shell を入れかえる)
   .shosts はパスワードを必要としないので、当該ユーザの
   パスワードをロックしてしまえば、とりあえず他人のログインは出来なくなる。
   (.shosts の有無に関わらずパスワードを知っていれば ssh ログインが出来てしまうため、これを抑止)
   ※通常の shell を禁止すれば接続元の公開鍵を登録できなくなる。
    接続先ユーザの .ssh/known_hosts と .ssh/authorized_keys に接続元ユーザの情報が必要なため、
    これを変更しない限り接続元ユーザは限定される。
   scp だけを実行する shell を作ってみた。
   これを接続先ユーザの shell として登録しておくことにより、動作を制限させる。
   scp を実行すると、相手シェルに
   -c scp -f FilePath     … 受信時
   または
   -c scp -t FilePath     … 送信時
   が渡ることを利用したもの。
/usr/bin/scponly
| 
#!/usr/local/bin/perl
# /usr/bin/scponly 755
#
# SHELL -c "scp ..." がリクエストされたときだけ動作するシェル
#
use strict ;
my $log  = './scponly.log' ;     # 実行ログ。適宜変更すること
exit if ($ARGV[0] =~ /\`/) ;     # バッククォートは駄目
exit if ($ARGV[1] =~ /\`/) ;
if ($ARGV[0] eq '-c' and $ARGV[1] =~ /^scp +/
&&  $ARGV[1] !~ /-f\s+.*(known_hosts|authorized_keys)/) # 鍵ファイルは書き込み不能にする
	{
	my $command = $ARGV[1] ;
	system($command) ;
	open LOG,">> $log" ;
	print LOG "$command\n" ;
	close LOG ;
	}
 | 
  .shosts の書き換えを禁止 (オーナでさえも禁止) したいときは、
  chattr (見るときは lsattr) で i フラグを立てれば良い。
  ※ i フラグを変更できるのは root のみ。