BLOG.tass.io

さくらVPS

2014-03-22

下記の記事に影響をモロに受けて、さくらVPS(石狩2G)を契約しちゃいました(;・∀・)

エンジニアならウェブサーバーのひとつでも自腹で立てて運用すべき理由と、サーバー環境の選び方 http://www.akiyan.com/blog/archives/2013/08/software-engineers-should-operate-a-web-server.html

「技術的なレイヤーは掘り下げて習得していくべきなので、ソフトウェア・エンジニアだってサーバー運用は経験すべき」
いや全くそーですよねー。いつも通り逃げてました。ごめんなさい。

わたしはサーバの立ち上げもメンテの経験もありません。底辺エンジニアとしてどうにか就職して、前職ではSH2とかARMとかの組み込み系からAndroid/iOSアプリ開発までやって、今の会社でWebフロントエンドに流れ着いた感じです。それなのに、ソフトウェアエンジニアとか名乗っちゃったのです。もう恥ずかしくて、おそと歩けないレヴェル。ほんとうにすみませんした…

以下、参考にさせて頂いたサイトの皆様です

さくらVPSでインスタンスを起動させてから、やるべきことをまとめてみました

1. rootユーザから作業用ユーザへの移行

さくらVPSだと、インスタンスを立ちあげた直後はrootユーザしかいません。
というか、rootユーザでログインできてしまいます。
つまり、rootユーザのパスワードを突破するだけで何でもありの状態です。これは非常に危険。
クラッキング対策したいならば、何重にも障壁を作っておく必要があります。
まずはrootをやめて、作業用ユーザに移行します。

# (1-1) 作業用ユーザ(tron)を作る
$ useradd -m -G wheel tron
$ passwd tron


# (1-2) rootになれるユーザを管理者グループだけに限定する
$ vi /etc/pam.d/su
> (修正)下記のコメントアウトを外す
> #auth required pam_wheel.so use_uid
> ↓
> auth required pam_wheel.so use_uid

# (1-3) rootとして実行できるユーザを管理者グループだけに限定する
$ visudo
$ (修正)下記を追記もしくはコメントアウトを外す
> #%wheel ALL=(ALL) ALL
> ↓
> %wheel ALL=(ALL) ALL

もうrootを直接使うことはないので、rootユーザをロックしてしまいます。

$ sudo passwd -l root

2. 公開鍵認証でのログインに限定する

今のままだと結局、作業ユーザのIDとパスワードが判明すれば侵入して何でもできてしまいます。
今度は、特定のPCからしかログインできないように、公開鍵認証以外でのログインをさせないようガードを固めます。

まずはクライアントになる自分のPC上で、ssh鍵を作っておきます。

# (2-1) 公開鍵と秘密鍵を生成
& ssh-keygen -t rsa -N "<任意のパスフレーズ>" -f ~/.ssh/id_rsa_sakura_vps
Generating public/private rsa key pair.
Your identification has been saved in /Users/xxx/.ssh/id_rsa_sakura_vps.
Your public key has been saved in /Users/xxx/.ssh/id_rsa_sakura_vps.pub.
The key fingerprint is:
83:cc:e3:0e:bc:51:82:f2:74:f1:c4:c1:ec:41:a1:9e xxx@localpc.local
The key's randomart image is:
+--[ RSA 2048]----+
|     ++.         |
|     o+.         |
|    ..o.         |
|.  o *.          |
|o.+.F o S        |
|.+++   .         |
| ..              |
| ...             |
|ooo              |
+-----------------+

# (2-2) 作った公開鍵ファイルをサーバに送る
& scp ~/.ssh/id_rsa_sakura_vps.pub tron@remote.host:~

クライアント側の作業はここで一旦中断して、これからはサーバ側のコンソールに切り替えて作業します。
先ほど送った公開鍵ファイルを登録します

# (2-3) サーバ側で鍵を登録
$ mkdir -p ~/.ssh
$ chmod 700 ~/.ssh
$ touch ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ cat ~/id_rsa_sakura_vps.pub >> ~/.ssh/authorized_keys
$ rm ~/id_rsa_sakura_vps.pub

さらにsshdの設定を変更して、パスワード認証から公開鍵認証に切り替えます

# (2-4) sshdの設定ファイルを修正
$ sudo vi /etc/ssh/sshd_config
>
> (修正1)ついでに、デフォルトのポート番号では攻撃を受けやすいので変更
> Port 22
> ↓
> Port 25822
>
> (修正2)rootでのログインを許可しないよう「no」に変更
> PermitRootLogin no
>
> (修正3)パスワード認証はもうやめるので「no」に変更
> PasswordAuthentication no
>
> (修正4)チャレンジレスポンス認証も使わないので「no」に設定
> # ChallengeResponseAuthentication no たぶんsakuraだとデフォルトでnoなので編集しなくていい
>
> (修正5)修正3をしていれば大丈夫と思うけど、念のためPAMも使わないよう「no」に設定
> UsePAM no
$
# 設定を反映させるために、sshdを再起動"
$ sudo service sshd restart
Stopping sshd: [  OK  ]
Starting sshd: [  OK  ]

以降はssh tron@remote.host -p 25822でアクセスできます。

ちょっと面倒なので、下記のようにしておくと便利です。
クライアント側のコンソールに戻って、sshの設定ファイルに下記を追記します。

# (2-5) SSHの設定を保存
$ vi ~/.ssh/config
> 下記を追記する
> Host sakura
>   HostName remote.host
>   User tron
>   Port 25822
>   IdentityFile ~/.ssh/id_rsa_sakura_vps

これでクライアントからssh sakuraで接続できるようになります。

3. ファイアウォールを設定してパケットフィルタする

これでだいぶセキュリティは高まりましたが、意外な脆弱性をつかれて侵入されてしまうかもしれません。
下手なパケットは受け取らないように、ファイアウォールを設定してポートを閉じちゃいましょう。
当然ながら接続用のSSHポート(22→25822に変更済み)と、これから使うであろうWebサーバのポート(http=80,https=443)、そしてpingに応答はできるようにします。

手順としては、ファイアウォールの設定を変更するスクリプトを作成して、実行して、設定を保存するというイメージになります。
まずはファイルを作成します。

$ sudo iptables -L
(現在の設定は、たぶん↓の感じになっているはず)
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
$ touch ~/init-iptables.sh
$ chmod +x ~/init-iptables.sh
$ vi ~/init-iptables.sh

viで下記の内容をファイルに書き込みます。

#!/bin/bash
# sudoでしか実行できないスクリプト
if [ `id -u` -ne "0" ];then
      echo "Sorry, Not Permit User!" >&2
      exit 1
fi
# テーブル初期化
iptables -F

# 基本ポリシー(どのルールにもマッチしなかった場合)の設定
#   INPUT(受信パケット)             => 'DROP(破棄)'
#   OUTPUT(送信パケット)            => 'ACCEPT(許可)'
#   FORWARD(フォワードするパケット) => 'DROP(破棄)'
iptables --policy INPUT   DROP
iptables --policy OUTPUT  ACCEPT
iptables --policy FORWARD DROP
#
# 自分自身に対する全てのアクセス(loインターフェースの送受信パケット)は全て許可
iptables --append INPUT  -i lo -j ACCEPT
iptables --append OUTPUT -o lo -j ACCEPT
#
# ブロード/マルチキャスト宛の受信パケットは記録せずに破棄(不要ログ)
iptables --append INPUT --destination 255.255.255.255 -j DROP
iptables --append INPUT --destination 224.0.0.1       -j DROP
#
# ローカルネットワーク内と思われるIPアドレスからの受信パケットは拒否
iptables --append INPUT -s 10.0.0.0/8     -j DROP
iptables --append INPUT -s 172.16.0.0/12  -j DROP
iptables --append INPUT -s 192.168.0.0/16 -j DROP
#
# SSHの接続ポート(25822)、Webサーバの接続ポート(80,443)の受信パケットは許可
iptables --append INPUT -p tcp --dport 25822 -j ACCEPT
iptables --append INPUT -p tcp --dport 80    -j ACCEPT
iptables --append INPUT -p tcp --dport 443   -j ACCEPT
#
# ping(icmp echo-request)の受信パケットは許可

iptables –append INPUT -p icmp –icmp-type echo-request -j ACCEPT # # セッション確立後のパケット疎通は許可 iptables –append INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT # # 設定内容の保存 /etc/rc.d/init.d/iptables save # # 再起動 service iptables restart

保存したら、スクリプト実行して反映させます。 実行した後は必要ないのでファイルを削除しても大丈夫です。

$ sudo ~/init-iptables.sh
$ rm ~/init-iptables.sh
$ sudo iptables -L
(実行した後は、下記のように変わっているはず)
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
DROP       all  --  anywhere             255.255.255.255
DROP       all  --  anywhere             all-systems.mcast.net
DROP       all  --  10.0.0.0/8           anywhere
DROP       all  --  172.16.0.0/12        anywhere
DROP       all  --  192.168.0.0/16       anywhere
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:25822
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

4. その他の設定

root宛てのメールを普段のメールアドレスへ転送します。 your-mailaddress@example.comの部分は、自分のメールアドレスにしましょう。

$ sudo sed -i '/^root:/d' /etc/aliases
$ sudo sh -c "echo 'root: your-mailaddress@example.com' >> /etc/aliases"
$ sudo newaliases

ちゃんと届くかテストしてみます

$ echo test | mail root

ちゃんと届いていたらOKです。|\○ヒャッ ε=\_○ノ ホーウ!!

TODO

  • パフォーマンス向上のため、不要なデーモンを停止
  • パフォーマンス向上のため、要らないコンソールを停止
  • ハッキング対策のために、sudoのログを取る
  • システムのログイン認証ログを監視
    • /var/log/secure
    • 不正アクセスがあった場合は弾かれたログが大量に残る
  • HTTPサーバアクセスログを監視
    • /var/log/httpd/access_log
    • phpadminフォルダを狙ってアクセスされていたりする(404が残る)
    • Nginxを使っている場合はこちら
      • /var/log/nginx/access.log
      • /var/log/nginx/error.log

Michael Kuroneko

Written by Michael Kuroneko. Follow me on twitter, github.