SSH接続ユーザの強制ログアウト方法

ずっとログインしたままのユーザが居ると聞いてwコマンドで確認。
fオプションは接続元IPを非表示にします。これは最初から接続元が分かっているのであれば不要なのと実行中のコマンド内容が右端で切れてしまうのでそれを防ぐためにつけています。
実験的にVMのCentOS6.4で試してみました。

[root@CentOS64 ~]# w -f
08:40:57 up 15 min, 3 users, load average: 0.00, 0.03, 0.08
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 08:40 0.00s 0.05s 0.03s w -f
user1 pts/1 26Nov13 21days 0.01s 0.01s -bash
user2 pts/2 26Nov13 21days 0.01s 0.01s -bash

2人のユーザがログインしたまま放置されていました。全くけしからん。
次にpsコマンドの結果からsshdを抽出し対象のプロセスIDを調べます。

[root@CentOS64 ~]# ps ax | grep sshd
1093 ? Ss 0:00 /usr/sbin/sshd
1252 ? Ss 0:00 sshd: user1 [priv]
1256 ? S 0:00 sshd: user1@pts/1
1272 ? Ss 0:00 sshd: user2 [priv]
1276 ? S 0:00 sshd: user2@pts/2
1349 ? Ss 0:00 sshd: root@pts/0
1368 pts/0 S+ 0:00 grep sshd

ここで見るのはptsとついた行になります。
もっと絞り込めば、こんな感じでしょうか。

[root@CentOS64 ~]# ps ax | grep "sshd: .*@pts/"
1256 ? S 0:00 sshd: user1@pts/1
1276 ? S 0:00 sshd: user2@pts/2
1349 ? Ss 0:00 sshd: root@pts/0
1393 pts/0 S+ 0:00 grep sshd: .*@pts/

こうすれば対象のプロセスIDが1256と1276であることが分かります。

それでは殺しましょうw

[root@CentOS64 ~]# kill 1256
[root@CentOS64 ~]# kill 1276

これでログインしたままのユーザを強制排除できました。さっそく確認しましょう。

[root@CentOS64 ~]# ps ax | grep "sshd: .*@pts/"
1349 ? Ss 0:00 sshd: root@pts/0
1395 pts/0 S+ 0:00 grep sshd: .*@pts/

ね、生きていないですねw

用法は
・メンテしたいのでユーザに出て行って欲しい時
・不審な接続の排除
・通信切れ等で残ったゴミ接続の掃除
となります。

因みにユーザ権限では他のユーザを追い出すことは出来ませんのでご心配なく。

ポートフォワードを使って踏み台先のサーバにFileZillaでファイル送受信する

WinSCPはトンネルの設定があり単体で踏み台経由の接続ができますが、残念な事にこのツールがWindows版しか無い為、他のOSでは別の方法をとる必要があります。

その一例としてsshコマンドによるポートフォワードを使った接続を紹介します。

1.ターミナルを立ちあげてポートフォワードを行う

ssh -L <ローカルポート>:<転送先ホスト>:<転送先ポート> <踏み台ホスト>

ローカルポート:FileZillaに設定したいポート番号
転送先ホスト:踏み台からアクセスするサーバー
転送先ポート:踏み台からアクセス先のサーバーへ接続するポート

例えば普段SSHで以下のように接続する場合

ssh user1@172.16.33.43 (踏み台)
ssh user2@192.168.1.6 (転送先)

割り当てるローカルポート番号を10022とすると
ssh -L 10022:192.168.1.6:22 user1@172.16.33.43 -p 22

この状態でlocalhost:10022は172.16.33.43経由で192.168.1.6:22に接続される。
注意点としては上記コマンドを実行して172.16.33.43にログインした後は、FileZillaの作業が終わるまで閉じないこと。

2.FileZilla で接続する。
ホスト名に localhost、ポートに 設定したポート番号、ユーザ名はuser2
(上記の例で行くと 10022 を設定する)

expectでssh自動接続

実はMacのネタですがLinux枠でw

普段使うノートがMacになったので急に障害連絡が来た時にメンテ可能な端末はMacしかない。でもBSDベースなので親和性が高く楽にできると何もせず構えてたら結構面倒だったw
これまではTeratermのマクロを準備していて例えば10台のサーバに一気にログインする必要があったりするときマクロファイルをダブルクリックでガンガンログインしていたのだが、MacにはTeratermないし同様の機能をどうするかなっと検索。
#!/usr/bin/expect
set timeout 1
spawn ssh root@192.168.56.101
expect “password: “
send “111111n”
expect “[.*]$ “
send “ls -ln”
expect “[.*]$ “
interact
結論としてexpectを利用してsshと対話してしまえば良い事が分かった。これならLinux上でもそのまま使える。但し二段階ログインした上でその先での操作が出来るかどうかについては確認していないが無理そうな気がする。
これはシェルスクリプトな感覚で作成します。違いは一行目にshではなくexpectを定義している点とその後のコマンド送信がteratermマクロっぽい感じになっていること(多分expectの方が先だと思いますがw)
spawnの行でsshコマンドを書き秘密鍵を利用するならここにオプションも一緒に書けば良いと思う(秘密鍵を使う場合はパスワード暗記しているケースが多いのでexpectの世話にはなり難いと思うが)
expectは待ち受ける文字列、ここではpassword: とプロンプトを待っている記述がある。
そしてsendがターミナルに送信するコマンドです。
最後のinteractはログインしたままの状態で終了するおまじない。これが無いとSSH接続を終了するので用途によって付けたり付けなかったりします。

サーバのIPアドレス入れ換えた時のSSH再接続

 サーバーのIPアドレスを入れ換えるなんて普段は無いのですが、ハードウェア障害によるサーバ交換を行った時に気をつけなければならないのはSSHが弾かれてしまうこと。
Windowsクライアントならサーバが代わろうが警告が出ようが新しいキーを上書きして続行できるのですがLinux同士だと、一旦known_hostsの情報を削除する必要がありました。
で、これだけknown_hosts自体を削除しそうですが、SSHの接続先が複数あるときは後でknown_hostsを再生成する手間が掛かるので、該当行だけを削除します。
viでdd打てばそれで終わりですが、もっと安全な方法が無いかと探したらありました。
参考:
OpenSSH : WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

http://futuremix.org/2007/08/openssh-warning

ssh-keygen -F [IPアドレス]
で検索して
ssh-keygen -R [IPアドレス]
で削除
これは簡単。

さくらのVPS ファイアーウォールを設定してみる

SSHの設定が済んだら次はファイアーウォールですよね。不要なサービスを止める作業も必要ですがそれだけでは新しくインストールした未設定のサービスが標的にされることもあるのでとりあえずアクセスを弾く機能は必要だと思います。

前回のSSHでも同じですが、この辺の設定を誤るとリモートログイン自体が出来なくなる可能性がありますので設定内容と手順には十分気をつけましょう。さくらのVPSの場合はブラウザ上でシリアル接続できるので最悪そこから設定を戻す事になります。(実は手順ミスって接続切られたorz)
参考:
にわかSEの独り言 CentOS 5.2 x64でiptablesを設定
基本参考サイトの通りなのですが若干気をつける点がありましたのでこちらで試した手順は以下の通り。
今までは/etc/sysconfig/iptablesを編集していたのですが、さくらのVPSにはそのファイルが初期状態でありません。それでコマンドラインで設定することにしました。念のためiptablesがストップしている事を確認し自動起動も外しておいたほうが良いと思います。それは万が一設定を間違って接続できなくなっても再起動すれば良いので、接続手段が無くなってしまったときにリモートか若しくはデーターセンター側のサポートで再起動してもらえば良いからです。
設定の初期化
# iptables -F
受信を全て破棄
# iptables -P INPUT DROP
送信を全て許可
# iptables -P OUTPUT ACCEPT
通過は全て破棄
# iptables -P FORWARD DROP
# サーバから外部に接続したコネクションのレスポンスを許可(2010/10/08追加)
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
PINGの許可
# iptables -A INPUT -p icmp -j ACCEPT
ローカルの許可
# iptables -A INPUT -i lo -j ACCEPT
ブロードキャストアドレス、マルチキャストアドレス宛のパケットを破棄
# iptables -A INPUT -d 255.255.255.255 -j DROP
# iptables -A INPUT -d 224.0.0.1 -j DROP
SSHの許可
# iptables -A INPUT -p tcp –dport 22 -j ACCEPT
SMTPの許可(submissionも追加) 2010/10/08修正
# iptables -A INPUT -p tcp –dport 25 -j ACCEPT
# iptables -A INPUT -p tcp –dport 587 -j ACCEPT
# iptables -A INPUT -p tcp –sport 25 -j ACCEPT
# iptables -A INPUT -p tcp –sport 587 -j ACCEPT
DNSの許可(source port 53 のルールも追加して下さい) 2010/10/08修正
# iptables -A INPUT -p udp –dport 53 -j ACCEPT
# iptables -A INPUT -p udp –sport 53 -j ACCEPT
HTTPの許可
# iptables -A INPUT -p tcp –dport 80 -j ACCEPT
POP3の許可
# iptables -A INPUT -p tcp –dport 110 -j ACCEPT
NTPの許可
# iptables -A INPUT -p udp –dport 123 -j ACCEPT
SNMPの許可
# iptables -A INPUT -p tcp –dport 161 -j ACCEPT
# iptables -A INPUT -p udp –dport 161 -j ACCEPT
SSLの許可
# iptables -A INPUT -p tcp –dport 443 -j ACCEPT
DROP対象をロギング
# iptables -A INPUT -m limit –limit 1/s -j LOG –log-prefix “[IPTABLES INPUT] : “
# iptables -A INPUT -j DROP
# iptables -A FORWARD -m limit –limit 1/s -j LOG –log-prefix “[IPTABLES FORWARD] : “
# iptables -A FORWARD -j DROP
設定の保存
# service iptables save
iptables起動
# service iptables start
ざっとこんな感じですが、FreeBSDのファイアーウォールと違ってハマったところは、私の調査不足なだけかも知れませんがレスポンスについてのルールを設定していないこと。サーバーから外部へのアクセスについては全許可してますが、そのアクセスのレスポンスについては何も設定していないので応答がDROPされてしまいました。今回の場合DNSの応答がDROPされた為、iptablesを起動してからSSH接続の応答が非常に遅くなって焦りました。
ちなみにSSH接続の応答が遅い時は経験上、接続元のIPを逆引きしようとして失敗している場合が多いので/etc/resolv.confで指定しているDNSサーバはアクセス可能なのか、今回のように53番が塞がっていないか確認します。そもそもSSH接続でDNS使うなよって思っているのですが、どうも逆引き→正引きを行ってIPアドレスが正しいものか認証しているようですね。理由が分かるとUseDNSをnoに変えるのもマズイかなっと思った。
追記:2010/10/08
探したらありました。絶対あるはずだと思ってた。
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
最初のACCEPT行の上に書いておけば良いかな。これでsource port 53のルールは不要になりました。多分SMTP関係のsource portのルールも不要になっているはずなので外してメールサーバを構築した時に確認してみます。
参考:
Kozupon.com – 解りにくいiptablesのアルゴリズム!

さくらのVPSを借りて最初にSSH設定

サーバーコストの節約という事で専用サーバ+共用レンタルの構成をVPS2台にしようとお試しで1台借りてみました。

さくらのVPS|VPS(仮想専用サーバ)はさくらインターネット
早速ですが最初はrootユーザしか無いためセキュリティ関連の設定を行います。ちょっと変則的かも知れないかもしれませんが一例として。
まずはroot権限に昇格できる作業ユーザを作成します。俺ルールとしてはこのユーザでメールやウェブは使わないようにしています。ここでは名称をworkuserとして書きますが、実際に作業ユーザを作成する場合は辞書にヒットするような名称は避けましょう。
作業ユーザの作成
# useradd workuser
パスワードの設定
# passwd workuser
ユーザグループの変更(wheelグループに所属させる)
# usermod -g wheel workuser
# usermod -G wheel,workuser workuser
SSHのログイン方法ですがVPSなら運用上SSHログインするユーザは狭い範囲で限定されることが多いと思いますのでクライアント認証の方式にします。
ユーザ用のキーペアを作成しておく
※今回はteratermの機能で作成
メニュー[設定]-[SSHキー作成]
作成した公開鍵をログインするユーザの~/.ssh/authorized_keysに保存
workuserに切り替え
# su – workuser
.sshディレクトリの作成とパーミッションの設定
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
authorized_keysを新規編集
$ vi ~/.ssh/authorized_keys
クライアントからSCP等で公開鍵をアップロードしても良いのですが、ターミナル上でコピペでも行けるので最初のユーザの場合等はそうしています。あと面倒だからってサーバーでキーペアを作成して秘密鍵をダウンロードするというのはセキュリティ運用上悪いので避けてください。
authorized_keysもパーミッションを適正値に修正します。グループやその他に権限があるとログインできなくなりますので後で慌てる事のないよう必ずチェックしてください。
$ chmod 600 ~/.ssh/authorized_keys
workuserから脱出
$ logout
ここでrootユーザに戻っているはず
次にsshdのログイン方法の設定変更をします。
まずは/etc/ssh/sshd_configの編集
# vi /etc/ssh/sshd_config
以下3行をnoに変更
PermitRootLogin no
PasswordAuthentication no
UsePAM no
1行目はrootでのSSHログインを無効、2行目はパスワード認証を無効、3行目はPAMを無効(多分パスワード認証で使っているものだから不要ということで無効なのかな?)
設定修正が終わったらsshdを再起動します。serviceコマンドでもOK。
# /etc/init.d/sshd restart
次にsuコマンドでrootに成れるユーザの制限をします。
suコマンドの制限
/etc/pam.d/suの下記のコメントを外す
auth sufficient pam_wheel.so trust use_uid
auth required pam_wheel.so use_uid
サーバー再起動
shutdown -r now
作業ユーザでクライアント認証ログインし、さらに
su – でrootに成れるところまで確認する。
一応作業ユーザ以外にもユーザを作ってみてwheelグループに属していない場合はsuコマンドでのユーザ切り替えができないことを確認する。
さくらのVPSの場合は管理画面にシリアル接続のターミナルがあるのでログインできなくなったらそこから設定の見直しをする。
鍵の管理は厳重に取り扱う
root自体のパスワードを無効化した時やroot権限を使う場合でもrootのパスワードを利用したくない場合はsudoの利用設定をします。sudoもwheelグループだけ使えるように制限します。
visudo コマンドでsudoの許可制限
# visudo
以下1行のコメントを外します
%wheel  ALL=(ALL)       ALL
続きは次回に
参考:
yukotan hour: CentOSで特定のユーザがsuでrootに昇格できるよう設定する
myfinder’s blog: さくらのVPSを借りたら真っ先にやるべきssh設定

 

バージョン違いMySQLの同居

同じバージョンのMySQLを2台同じサーバーに入れたりというのは開発環境でやったことがあるのですが、双方とも自動起動してバージョン違いかつ文字コード違いという環境は初めて入れた。結論としては自動起動スクリプトがまるで複数導入を想定していないというのが分かったくらいかな。

やってみた構成はこんな感じ。
  • rpm版同士での複数インストール
    これは普通に競合するのでNG
  • 既存のMySQLクライアントとPHP-MySQLコネクタを残して、MySQL公式サイトのrpm最新版(Serverのみ)をインストール
    これも競合。MySQL公式サイトのものはServerとClientで2つに分けているが、RedHat公式のMySQLはServerとClientとその両方で使う無印パッケージの3つ分かれ、無印とMySQL公式のパッケージで競合を起こす。
  • 既存はrpm版で別途ソース版を入れる
    これは問題なし、自動起動スクリプトは改造が必要
  • 既存がソース版で別途インストールもソース版
    問題は無いがソース版同士なので全ての設定を別に分ける必要が出てくる。自動起動スクリプトは改造が必要。
自動起動スクリプトの改造が必要なのは、configureの設定内容を無視しているのでそのまま使えばデフォルトの構造でmy.cnfやpidファイル、sockファイルを探しに行くという恐ろしいワナがある。結局自動起動スクリプト上のmysql_safeコマンドの行に–defaults-file=[my.cnfのパス]で設定が必要。ちなみにこのオプションは最初に記述しないとエラーになります。他にはDBの初期化(mysql_install_db)をするときに既存のDBを破壊しないように念のためバックアップを取った上でオプションでdatadirやdefaults-fileを設定し回避すること。これは理由がわからないのですがスレーブ用に構築する予定のDBで初期化するときに最初からmy.cnfよりbin-logを抜いていたらエラーになった。これは初期化にはバイナリログが必要だったのか、中途半端なコメントがまずかったのかは不明。別に初期化の時にバイナリログが出されてもたいしたこと無いので別に良いのですけどね。
参考
またレプリケーションも本格的に負荷分散しようとしたら参照系で不要なDBやテーブルを持ってきたくないという事がありました。こちらの設定はスレーブ側のmy.cnfの[mysqld]内に
replicate-do-table=dbname.table
replicate-do-db=dbname
といった感じで追記するだけ。
また文字コードの設定で[mysqld]内に
default-character-set = utf8
だけでなく
skip-character-set-client-handshake
を設定するとPHPから接続したときにいちいち「SET NAMES」を設定しなくても良くなるし、他のセクションにdefault-character-setを入れなくても文字コードが統一される(status;やshow variablesで確認)。
[MySQL] 特定データベース、特定テーブルを指定したレプリケーション設定 | 半袖野郎 blog.hansode.org
あと大きなバッチを使うときに気になるのがメモリ使用量なのですが、折角1行ずつ取り出すのに一斉に配列に入れようとするのはセンス無さ過ぎで見つけ次第指導するレベルなのですが、また全件必要でないのにどうせ詮索スピード変わらないからという理由でLIMITを使わないのもメモリの事を考えてない証拠なのでこれもダメ、でもまさかmysql_query関数の結果が一旦全部メモリにキャッシュされるとは思わなかった。PHP上ではどう見てもメモリが溜まるような処理を書いてないのにメモリ不足になるのはこれのせいだった。そのときはmysql_unbuffered_queryを使いましょう。mysql_unbuffered_queryの制約としてはmysql_data_seekが使えないことや全ての行をフェッチする必要があるという事なので件数の絞込みはしっかりLIMITで設定しましょう。スピードは多分遅くなると思いますがバッチ等では消費メモリの上限を抑えられない方が問題なので。
PHP:SQLクエリのメモリ消費量を抑える:mysql_unbuffered_query