まず、http before sshなんていう機能はありません。
私が勝手につけました。ようは、pop before smtpみたいなものを
sshの接続のために構築します。
つまり、sshでアクセスするためにはhttpに一度アクセスして許可を取らなければいけないとします。
どうして、こんなことをしようと思ったかといえば、
ちょっと、昨日設定したiptableの設定が考慮不足で自分で自分のサーバにemobileを使ってアクセスができなくなってしまった。
まあ、結構いい加減に許可をしていたので、もうちょっと厳しくしようかなと思ったものの、
それで失敗してしまった。
ということで、どうせやるならもうちょっときちんとやろうと思った次第です。
さて、この
http before ssh
ですが、ここでは2つの方法を紹介します。
1つは、httpでアクセスしたIPから数秒以内だけsshの接続を許可する。
2つは、httpであるページに接続しそこで認証したら、そのIPからのみ数十分間だけsshの接続を許可する。
というものです。
どちらも、iptablesを使うので、まずは安全のための準備をします。
iptablesを安全につかうための準備
iptablesで設定している最中がもっとも、間違いやすく、
ましてや、リモートからiptablesの設定をするとなると多少は勇気がいるものです。
しかし、ここでは私なりの間違いが起きにくい方法を紹介します。
1)ゼロからiptablesの設定をするのも面倒ですし、
間違いがあってもいけないのでCUIベースの設定ツールがあればそれを使って簡単な設定を行います。
たとえば、CentOS等であれば
” system-config-securitylevel-tui”
などのツールを使って概要をつくってから、
/etc/sysconfig/iptables
のファイルをいじっていきます。
まずはここで必ず、sshを有効にしましょう。
この前提で記述してあるので、-RH-Firewall-1-INPUTと記述してあります。
2)自分がアクセスするIPからsshを無条件で許可するようにします。
私は、e-mobileからだったので、ある程度のレンジで指定します。
-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -m iprange --src-range 117.55.65.0-117.55.65.255 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
ここでポイントは、既存の22ポートも許しておくことです。
設定が終わったら、iptablesを再起動します。
そして、sshでアクセスをしてみます。
(当然、接続はできます。)
ここで、どちらのルールに適用されて許可されたのかを調べる為に、
#iptables -nvxL
と打てば、
Chain RH-Firewall-1-INPUT (2 references)
pkts bytes target prot opt in out source destination
1 52 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 source IP range 117.55.65.0-117.55.65.255
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
とこんな感じに表示されます。
ここで、pktsが接続毎に増えていれば、そこが使われているということです。
それで、IPのレンジ指定で許可されているのがわかります。
これで多少は安心して、接続元の指定がない22番ポートへの接続を切ることができます。
httpでアクセスしたIPから数秒以内だけsshの接続を許可する
この方法のネタ元はhttp://blog.onoh.info/linux-sshiptablesです。
多少ちがいますが、ほとんど同じです。
こちらはiptablesさえあれば実現可能です。
http(ポートを変えた方がいいかも)にアクセスしてから、数秒(5秒)以内だけsshの接続を受け付けるようにします。
ここで、この方法を知っている人と、httpのポート番号を知っているひとがsshできる対象というわけです。
それ以外はsshのポートすらあいていることすら知りません。
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 8888 -m recent --set --name check --rsource -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 5 --name check --rsource -j ACCEPT
と設定します。
こちらも、設定が終了したら再起動します。
また、
#iptables -nvxL
も忘れず実行し、実際に思い通り動いているか確認しましょう。
httpであるページに接続しそこで認証したら、そのIPからのみ数十分間だけsshの接続を許可する。
こちらはもうちょっと複雑です。
WEBの画面を使って認証(ログイン)すると、その接続元IPから接続できるように動的にiptablesに設定を追加し、
atコマンドを使って一定の時間経過後に、その設定を削除するというものです。
ちなみに、使う環境として
iptables
syslog-ng
at (/usr/bin/at )
php (やcgiなど)
です。
syslog-ngを使うのは、syslogのメッセージによりコマンドを発行するためであり、
また、root権限にてiptablesへの追加ができるようにするためです。
ここでは、syslog-ngを含めてインストールは説明しません。
まずは、PHPにて
< ?php
if($_POST['auth'] == "1"){
$ip = $_SERVER['REMOTE_ADDR'];
openlog("ipconn",LOG_INFO,LOG_LOCAL1);
syslog(LOG_INFO,"@$ip");
}
?>
<html>
<body>
<form method="POST">
<b>Your IP Address: < ?php print $_SERVER['REMOTE_ADDR']; ?></b>
<input type="hidden" name="auth" value="1" />
<input type="submit" value="CONNECT" />
</form>
</body>
</html>
のようなプログラムをつくりWEBでアクセスできるようにします。
実際には、何らかの認証もつけるのですが、私は面倒なのでhttpsとBASIC認証で代用してしまいます。
ここでは、重要な点はログに
“@IP_ADDRESS”
のような形式を出力することです。
このあと設定するsyslog-ngはこのメッセージを受けたら、IP_ADDRESSを許可するというようにします。
次に、syslog-ngから起動されるプログラム(shell)を記述します。
(もちろん、実行権限を忘れずに・・・)
#!/bin/sh
IPTABLES=/sbin/iptables
ATCMD=/usr/bin/at
NAME=RH-Firewall-1-INPUT
while read line;
do
IP=`echo $line | cut -d@ -f2`
ADD_IP="$IPTABLES -I $NAME 7 -p tcp -s $IP -m multiport --dport ssh,smtp,imap,pop3,svn -j ACCEPT"
DEL_IP="$IPTABLES -D $NAME -p tcp -s $IP -m multiport --dport ssh,smtp,imap,pop3,svn -j ACCEPT"
$ADD_IP
echo $DEL_IP | $ATCMD now +60minutes
done
ここで、”@”以降をIPアドレスと見なしてそれをもとに設定を追加します。
ADD_IP="$IPTABLES -I $NAME 7 -p tcp -s $IP -m multiport --dport ssh,smtp,imap,pop3,svn -j ACCEPT"
で”7″とありますが、$NAMEで指定したルールの7行目に追加するという意味なので、
実際に何行目に設定するかをかえてください。
また、同時に、atコマンドを使って削除する指定もしておきます。
(atdが動いていないと実行されないので、そこはご確認を)
これで、60分だけ接続ができるようになります。
ちなみに私はsshだけではなく、それ以外のサービスも同時に設定しているのでmultiport指定を使いました。
ここまで、準備ができたら、これらをsyslog-ngの指定でつなげていきます。
destination d_ipconn_at { program("/usr/local/bin/ipconn.sh"); };
filter f_ipconn { program("ipconn"); };
log { source(s_sys); filter(f_ipconn); destination(d_ipconn_at); };
の指定をsyslog-ngに追加してください。
これで、syslog-ngを再起動したら終了です。
これの応用で無人サーバ運用も広がっていくことと思います。


