2017 年度 OSS リテラシー 3 : 第 6 回 セキュリティ対策

不要なポートを閉じる

まず, 開いているポートを確認するには, netstat コマンドや nmap コマンドを用いる. なお, nmap コマンドはクラッキングの前段階として行われることが多いので, 無用の誤解を与えないために localhost 以外のホストに対して実行しないこと.

netstat -ntl コマンドを実行する. 以下の例では, 22 番ポート (SSH) が全ての IP アドレス (0.0.0.0) に対して開いており, 25 番ポート (SMTP) が自分 (127.0.0.1) に対してのみ 開かれていることがわかる. また IPv6 で 22 番ポート (SSH) が全ての IP アドレス (0.0.0.0) に対して開かれていることがわかる.

$ netstat -ntl

  稼働中のインターネット接続 (サーバのみ)
  Proto 受信-Q 送信-Q 内部アドレス            外部アドレス            状態       
  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
  tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
  tcp6       0      0 :::22                   :::*                    LISTEN     

次に nmap をインストールして, 開いているポートを確認する.

$ sudo -s

# apt-get update

  ... (略) ...

# apt-get install nmap

  パッケージリストを読み込んでいます... 完了
  依存関係ツリーを作成しています                
  状態情報を読み取っています... 完了
  以下の追加パッケージがインストールされます:
    liblinear3 liblua5.3-0 libpcap0.8 ndiff python-bs4 python-html5lib python-lxml
  ...(中略)...
  続行しますか? [Y/n] 
  取得:1 http://moon.epi.it.matsue-ct.jp/raspbian stretch/main armhf liblinear3 armhf 2.1.0+dfsg-2 [34.9 kB] 
  ...(後略)...

# exit   

インストールしたら, localhost (127.0.0.1) と有線もしくは無線 LAN の IP アドレスに対して nmap を実行せよ. 前述の netstat コマンドと同様に, localhost では 22, 25 番ポート (SSH, SMTP) が, 有線もしくは無線 LAN の IP アドレス (ローカルホスト以外) に対しては 22 番ポート (SSH) のみが 公開されていることが確認できる.

$ nmap localhost  (localhost (127.0.0.1) を指定)

  ...(中略)...
  PORT   STATE SERVICE
  22/tcp open  ssh
  25/tcp open  smtp

  Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds

$ hostname -I       (有線もしくは無線の IP アドレスを確認)

  XX.XX.XX.XX

$ nmap XX.XX.XX.XX  (有線もしくは無線の IP アドレスを指定)

  ...(中略)...
  PORT   STATE SERVICE
  22/tcp open  ssh

  Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds

もしも 25 番ポートが全てのホスト (0.0.0.0) に対して開いている場合は, 前回のメールサーバ設定が間違っている可能性が高い. 前回の資料を確認し, 設定内容を修正すること.

もしも 22, 25 番以外のポート番号が表示された場合は教員に相談すること. 誤って余計なパッケージをインストールしてしまった可能性が高い. 誤ってインストールしたパッケージを削除すればポートを閉めることができる.

ssh の設定の修正

前節で確認した通り, ラズパイでは外部に対して 22 番ポート (SSH) しか 開いていないが, さらにセキュリティを高める方法として, 以下の 2 つがある.

  1. パスワード認証を無効化し公開鍵認証のみにする
  2. SSH 接続が可能なホストを限定する

パスワード認証の無効化.

ssh でパスワードによる認証を無効にし, 公開鍵認証のみをサポートする.

$ sudo -s

# vi /etc/ssh/sshd_config

  # To disable tunneled clear text passwords, change to no here!
  #PasswordAuthentication yes  (変更前)
  PasswordAuthentication no    (変更後)

設定を変更したら ssh サーバを再起動する.

# /etc/init.d/ssh restart        

  [ ok ] Restarting ssh (via systemctl): ssh.service.

# exit
$

確認を行う. サーバにログインしてからラズパイに対して ssh コマンドを実行する.

$ ssh -l jxxxx sky.epi.it.matsue-ct.jp

  ...(略)...

sky$ ssh -l pi XX.XX.XX.XX (自分のラズパイの IP)

   Permission denied (publickey).    (公開鍵を作っていないユーザ pi はログインできない)

sky:~$ ssh -l hogehoge  XX.XX.XX.XX (自分のラズパイのユーザ名と IP を使うこと)

   Enter passphrase for key '/home/jxxxx/.ssh/id_rsa':   (パスフレーズ入力) 

   ...(略)...

$          (ラズパイに再度ログイン) 

$ exit     (ラズパイからサーバへ)

sky$ exit  (サーバからラズパイへ)

$ 

TCP Wrapper によるアクセス制限

TCP Wrapper を用いて ssh 接続を許可するホストを限定する. 設定ファイルは /etc/hosts.allow と /etc/hosts.deny の 2 つである. 動作としては /etc/hosts.allow に書かれたアクセスルールが最初に適用され, 次に /etc/hosts.deny に書かれたアクセスルールが適用される.

まず, /etc/hosts.allow において, サーバ sky.epi.it.matsue-ct.jp (10.164.1.197) のみに SSH アクセスの許可を出すことにする.

$ sudo -s

# vi /etc/hosts.allow

  sshd: 10.164.1.197   (末尾に追記)

書式としては, コロンの前にデーモン名 (SSH ならば sshd (ssh daemon)), コロンの後ろにホスト名である. ホスト名には .matsue-ct.jp のように, matsue-ct.jp のドメインを持つ全てのホスト, という書き方もできる.
[注: 書式的にはドメインで書いても良いはずだが, IP で指定しないとうまく動かなかった]

次に, /etc/hosts.deny において, 全てのホストからの接続を禁止する 設定を行う. ALL: ALL とすると, 外部の全てのホストから, 全てのデーモン (ポート) へのアクセスを拒否することとなる.

# vi /etc/hosts.deny

  ALL: ALL     (末尾に追記)

TCP wrapper は再起動は必要なく, 編集したファイルの内容は直ちに適用される.

以上の設定で, sky.epi.it.matsue-ct.jp 以外はラズパイのどのポートにも アクセスできなくなったはずである. 動作確認として, 友人のラズパイに SSH 接続してみよ. 正しく設定されていれば, 以下のように Connection がリセットされ, SSH 接続できないことがわかる.

$ ssh -l pi XX.XX.XX.XX (友人のラズパイの IP)

  ssh_exchange_identification: read: Connection reset by peer

さらに確認として, サーバからはラズパイに対して ssh 接続できることを確かめる.

$ ssh -l jxxxx sky.epi.it.matsue-ct.jp

  ...(略)...

sky:~$ ssh -l hogehoge  XX.XX.XX.XX (自分のラズパイの IP)

   Enter passphrase for key '/home/jxxxx/.ssh/id_rsa':   (パスフレーズ入力) 

   ...(略)...

$          (ラズパイに再度ログイン) 

$ exit     (ラズパイからサーバへ)

sky$ exit  (サーバからラズパイへ)

$ 

フィルタリング : fail2ban (iptables)

本演習では iptables のフロントエンドとして実装されたソフトウェア fail2ban を用いる. iptables を直接設定するのは初心者には難しいためである.

fail2ban はログを監視し, 特定のパターンに引っかかる動作が記録されたらファイヤウォールに動的にルールを追加して, 通信をブロックする. 例えば ssh のブルトフォース攻撃 (パスワード総当たり攻撃) のように, 頻繁にアクセス & ログイン失敗を繰り返すホストからのアクセスを切断する.

まず, iptables の現在の設定を確認する.

$ sudo -s    

# 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      

次に fail2ban をインストールする.

# apt-get update

  ... (略) ...

# apt-get install fail2ban

# iptables -L  (fail2ban の設定が追加されていることを確認)

  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         

  Chain f2b-sshd (0 references)
  target     prot opt source               destination         
  RETURN     all  --  anywhere             anywhere           

fail2ban の設定ファイルは /etc/fail2ban/jail.conf および /etc/fail2ban/jail.d/defaults-debian.conf である. 各ポートに対して /etc/fail2ban/filter.d/ 以下にフィルタが用意されている. デフォルトの設定では ssh のみ監視が有効にされている. 本演習のラズパイでは ssh 以外に外部からアクセス可能なポートを開けていないので, ssh 以外のフィルタを有効にする必要はない.

sshd が監視対象となっていることは, 以下のコマンドを実行すれば確かめられる.

# fail2ban-client status 

  Status
  |- Number of jail:   1
  `- Jail list: sshd

[参考] ban された時の動作

fail2ban をインストールしたので, ssh で何度もパスワード入力を誤ると ban される (以下のように ssh コネクションが切られる). デフォルトでは 10 分間接続不可となる.

sky$ ssh XX.XX.XX.XX

  ssh: connect to host 10.138.64.109 port 22: Connection refused

ラズパイで ssh アクセスで ban された IP を確認するためには以下のようにする.

# fail2ban-client status sshd

    Status for the jail: sshd
     |- filter
     |  |- File list:	/var/log/auth.log 
     |  |- Currently failed:	0
     |  `- Total failed:	6
     `- action
        |- Currently banned:	1
        |  `- IP list:	10.164.1.197
        `- Total banned:	1

不要なユーザのアカウントのロック

ユーザーアカウントをロックすると, そのアカウントは使用不可の状態になりログインすらできなくなる. ユーザ pi はもはや必要ないので, このアカウントをロックする.

$ sudo -s 
# passwd -l pi

  passwd: パスワード期限切れ情報を変更しました

# exit

$ su pi          (ユーザ pi にスイッチ)

  パスワード:
  su: 認証失敗

なお, パスワードロックを外す場合は, $ passwd -u pi とすればよい.

課題

  • 不要なユーザ pi をロックする前とロックした後で何が変わるか調べなさい. wbt のオンラインテキストで提出しなさい. (ヒント: パスワードが保管されているファイルは?)
  • サーバ (sky.epi.it.matsue-ct.jp) において以下のコマンドを実行して, 設定をチェックせよ. jxxxx は適宜自分のユーザ名に変更すること. wbt に提出する必要はない.

    sky$ sudo -u sugiymki /usr/local/bin/check_2017.rb jxxxx
  • (発展, 提出任意) 以下の 1,2 を行い, その証拠を何らかの形で提出せよ.

    1. 5 棟 3 階の演習室の PC からラズパイにアクセスできるようにするために TCP Wrapper の設定を編集せよ. 
    2. Windows の putty から自分のラズパイに公開鍵認証でリモートアクセスできるようにせよ. 
       (公開鍵をコピーするためには, パスワードログインできるように SSH の設定を一時的に直すのが簡単. 
       コピー後に SSH の設定を戻すこと)