余白の書きなぐり

aueweのブログ

apache2でcgiがダウンロードされる時のチェック項目一覧

自鯖http://hogehoge/piyo.cgi にアクセスしたとき、piyo.cgi が実行されず、なぜかダウンロードが始まる時のチェック項目一覧

AddHandlerしたか ?

# httpd.conf
AddHandler cgi-script .cgi

AddTypeしたか?

# httpd.conf
AddType applications/x-httpd-cgi .cgi

OptionでExecCGIしたか?

# httpd.conf
Options Indexes FollowSymLinks ExecCGI

a2enmodを有効化したか?

$ sudo a2enmod cgi # Ubuntu14.04LTSの場合

設定終えた後restartしたか?

$ sudo service apache2 restart

cgiのパーミションは大丈夫か?

$ cd /.../cgi-dir/
$ chmod 755 hoge.cgi

cgiを設置したディレクトリのパーミションは?

$ 755 /.../cgi-dir

cgiスクリプトの表示内容は正しいか?

#!/usr/bin/perl
print "Content-typo: text/html\n\n";    # タイポしてる!!
print "Hello, World.";

他なんかあるかな。 a2enmodの有効化はググってもあんまり出ないし盲点な気がする。

さくらVPSのUbuntu LTS 14.04にSoftether-VPNをインストール

あちこちにインストール方法が書かれてるけど、少しハマったのでメモ。 まずsoftetherのウェブサイトからソースをダウンロードする

$ uname -a   # x86_64を確認。64bit用のインストーラーをダウンロードする
$ mkdir vpninstall
$ cd vpninstall
$ wget http://jp.softether-download.com/files/softether/v4.19-9605-beta-2016.03.06-tree/Linux/SoftEther_VPN_Server/64bit_-_Intel_x64_or_AMD64/softether-vpnserver-v4.19-9605-beta-2016.03.06-linux-x64-64bit.tar.gz
$ tar xvfz softether-vpnserver-v4.19-9605-beta-2016.03.06-linux-x64-64bit.tar.gz

コンパイルしてインストールする

$ cd vpnserver
$ make # 1を三回選んだ
$ cd ..
$ sudo mv vpnserver /usr/local  # make installコマンドは無いようなので、愚直にmvする
$ cd /usr/local/vpnserver
$ chmod 600 *
$ chmod 700 vpncmd vpnserver
$ chown root:root *
$ chown root:root **/*
$ /usr/local/vpnserver/vpncmd   # 正しくインストールされてるかチェック

サーバーの電源ON時にvpnserverが自動起動するよう設定

$ sudo vi /etc/init.d/vpnserver
$ sudo apt-get install sysv-rc-conf   # sys-rc-confはchkconfigのUbuntu版
$ sysv-rc-conf --add vpnserver

/etc/init.d/vpnserverの中身

#!/bin/sh
# chkconfig: 2345 99 01
# description: SoftEther VPN Server
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/subsys/vpnserver
test -x $DAEMON || exit 0
case "$1" in
    start)
        $DAEMON start
        touch $LOCK
        ;;
    stop)
        $DAEMON stop
        rm $LOCK
        ;;
    restart)
        $DAEMON stop
        sleep 3
        $DAEMON start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac
exit 0

管理権限のあるアクセス元IPアドレスadmini.tmpに指定。 「管理権限のあるアクセス元のIPアドレス」であり、「クライアントのIPアドレス」ではない。 通常はVPNサーバをインストールしたサーバー自身のIPアドレスを書く。

$ sudo vi /usr/local/vpnserver/adminip.tmp
# ファイルには以下のように書く。
192.168.1.2
127.0.0.1

vpnサーバを立ちあげてパスワードを設定

$ sudo /usr/local/vpnserver/vpnserver start # この操作を忘れてハマった
$ sudo /usr/local/vpnserver/vpncmd # 何も入力せずエンターを二回押した後、パスワード設定

参考サイト SoftEther VPN Server を CentOS にインストールする 3.5 仮想 HUB のセキュリティ - SoftEther VPN プロジェクト

Haskellの型推論でハマった話

久しぶりにHaskellで遊んでたらハマったのでメモ。 100の階乗 100!=1*2*...*100 の桁数を求めるプログラムを書いた。

main = print $ kaijo 100
kaijo n = length $ show $ product [1..n]
-- 158が表示される。

上記のプログラムは正しい値(158)を返すが、下記のように型を明示すると、誤った値(0)を返す。

main = print $ kaijo 100
kaijo :: Int -> Int
kaijo n = length $ show $ product [1..n]
-- 0が表示される。なんでや!!

ちなみに100ではなく10の階乗なら、どちらのプログラムも正しい結果を返す。 この不条理の原因は、Intを明示するとproduct関数の計算がIntで実行されて、 100の階乗という大きな値が桁溢れを起こすせいだと思われる。 Intを明示しなければ、自動で多倍長計算してくれる。

「100を158にする関数」なのに、Int -> Intとするとバグっちゃう。こわいこわい。

zshのプロンプトを256色にする方法

zshから256色を使う詳細については、以下のサイトの情熱がものすごい。 http://misc.flogisoft.com/bash/tip_colors_and_formatting

しかし肝心のプロンプトの設定方法が載ってなかったので、ここにメモしておこう。 ~/.zshrcで以下のように記述する。

# 例1
# 注意! ^[ は特殊文字。Vim上で Ctrl+Vした後にESCを押せば入力できる。
# 赤(001番)文字+デフォルト背景
PROMPT="%{^[[38;5;001m%}RED%{^[[0m%}"
# 例2
# デフォルト文字色+緑(082番)背景
PROMPT="%{^[[30;48;5;082m%}Green Background%{^[[0m%}"
# 例3
# 赤(001番)文字+緑(082番)背景
PROMPT="%{^[[30;48;5;082m%}%{^[[38;5;001m%}Red on Green Background%{^[[0m%}"
# 例4
# 以下のように文字色を定義しておくと便利
COLOR_FG="%{^[[38;5;001m%}"      # 表を赤に
COLOR_BG="%{^[[30;48;5;082m%}"   # 背景を緑に
COLOR_END="%{^[[0m%}"            # 色を元に戻す
PROMPT="${COLOR_BG}${COLOR_FG}Red on Green Backgroun${COLOR_END}"

ちなみに zshのプロンプトカラーを設定を変更してみた - HAM MEDIA MEMO に書いてある形式

PROMPT=$'%{\e[38;5;46m%}%m%(!.#.$)%{\e[m%} '

ではうまくいかなかった。

シェルスクリプトの平文パスワードをセキュアにする方法(続き)

この記事は、一年前に書いた シェルスクリプトの平文パスワードをセキュアにする方法 という記事の続きです。 なぜか今頃になって大量のはてブが付き、戦慄している次第です。 ブックマーカーのコメントには

  • chmod 700 の平文パスワードファイルを読み込むのと大差なくね。
  • 秘密鍵を使う方法は環境固定なのがイヤ。
  • GitHubシェルスクリプト共有するときに便利そう。

といった指摘が並んでいました。せっかくなので、少し補足します。

chmod 700 の平文パスワードファイルを読み込むのと大差なくね。

確かにその通りですね。 暗号化したパスワードファイルが盗まれる状況では、ssh秘密鍵も一緒に盗まれそうです。 そう考えると、平文のパスワードを外部ファイルに保存してパーミションを700に設定するのと、本質的に同程度のセキュリティしか担保されていません。

この問題を解決するのは簡単です。 ssh-keygen秘密鍵を作成する際にパスワードを設定すればよろしい*1 こうしておけば、もし秘密鍵と暗号化したパスワードファイルの両方が盗まれたとしても、秘密鍵のパスワードが破られない限り複合できません。 もう少し具体的に書くと、まず

$ ssh-keygen -f pasu_tuki_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): # パスワードを入力
Enter same passphrase again: # パスワードを再入力
Your identification has been saved in pasu_tuki_rsa.
Your public key has been saved in pasu_tuki_rsa.pub.
The key fingerprint is:
...

としてpasu_tuki_rsaというパスワード付きの秘密鍵を作成します。 後は前回の記事に書いたのと同じ手順で暗号化や複合が可能ですが、その時にpasu_tuki_rsaのパスワードを問われます*2

秘密鍵を使う方法は環境固定なのがイヤ。

この問題については、パスワードファイル専用のssh秘密鍵を作ることで解決します。 パスワードファイルと(パスワード付きの)ssh秘密鍵をペアで管理する訳ですが、このペアは環境に依存しないので、各環境に配布することが可能です。 便利な使い方としては、例えばcronrsyncでパスワードファイルを各環境に同期すれば、Dropbox + KeePassのコマンドライン版を手軽に実装できます*3

GitHubシェルスクリプト共有するときに便利そう。

まさにそういう目的で前回の記事を執筆しました。 他人とシェルスクリプトを共有する際、スクリプトに自分専用の平文パスワードをべた書きするのは論外です。 対策として、パスワードを外部に保存してスクリプトから読みこめば、スクリプトを共有できると考えました。 しかし外部に平文のパスワードファイルを置くのも気持ち悪いと思い至り、前回記事の着想を得ました。

まとめ

要点は以下に集約されます。

  • opensslを使うことで、パスワードファイルのセキュリティコストをssh秘密鍵に負わせることが可能。
  • ssh秘密鍵にはパスワードが設定できる。
  • opensslは大抵の環境に入っているので、ソフトのインストールが制限されている環境でも使用可能。

こういう特性をうまく使って、各人にあった運用方法を探してね~

*1:そもそもsshログイン用の秘密鍵にパスワードを設定しないのは、かなり危険だと思う。もし秘密鍵が漏れた場合、その公開鍵が登録されてる全環境にログインされるので、二次被害が半端ない

*2:パスワードを保存したファイルを開くために、また別のパスワードが必要なのはナンセンスでは?という質問については、「パスワード管理ソフト」でググるのが教育的だと思う

*3:こういう秘密鍵の使い方は、公開鍵暗号システムの本質から外れていると思う。もっと良い方法がないものか

UNIXの設定ファイル中の平文パスワードを暗号化してセキュアにする方法

UNIX系の設定ファイルの中にパスワードを書くのは、あまりにインセキュアで躊躇われる。 たとえばCUIメーラーの雄 muttGmail を使う場合、~/.muttrc

# ~/.muttrc for Gmail
set imap_user = "YOUR.EMAIL@gmail.com"
set imap_pass = "パスワード"
set smtp_url = "smtp://YOUR.EMAIL@smtp.gmail.com:587/"
set smtp_pass = "パスワード"

といった具合にパスワードを書く必要がある。
参考:
brew - mutt + Gmailを使ってCUIでのメール環境を作る - Qiita

いくらなんでもセキュリティ的にアレすぎるので、平文のパスワードを暗号化してセキュアにしよう。 大抵のUNIXの設定ファイルには、外部ファイルを読み込む source コマンドが実装されている (source できない設定ファイルはクソすぎる)。従って

  1. 設定ファイルのパスワード部分を、外部ファイルの plain.txt に分離
  2. plain.txt を暗号化して pass.rsa にする
  3. アプリケーションの起動時に pass.rsa を復号化しつつ、元の設定ファイルにsourceする

という手続きを踏むことになる。 .muttrc を例に順番に説明しよう。

1. パスワード部分を plain.txt に分離

set imap_pass = "パスワード"
set smtp_pass = "パスワード"

を外部のplain.txtに保存する。

2. plain.txt を暗号化して pass.rsa にする

次に plain.txt を暗号化する。 こういう場合には opensslを使うのが便利だ。 その辺の詳しい事情は以前の記事にまとめてある。

暗号化のやり方だけを抜粋すると、コマンドラインで以下のコマンドを叩けばよい。

# plain.txt というテキストファイルを暗号化して pass.rsa に書き込むコマンド
$ openssl rsautl -encrypt -inkey ~/.ssh/id_rsa -in plain.txt > pass.rsa

これでpass.rsaが作成されるはずだ。 もしエラーが出た場合には、ssh-keygenすれば多分解決する。 詳しい話はシェルスクリプトの平文パスワードをセキュアにする方法 - 余白の書きなぐりを参照。

3 pass.rsa を復号化しつつ、元の設定ファイルにsourceする

最後に pass.rsa を復号化して、.muttrcに読み込む作業が残っている。 これは .muttrc を以下のように書き換えることで実現できる。

# ~/.muttrc for Gmail
set imap_user = "YOUR.EMAIL@gmail.com"
set smtp_url = "smtp://YOUR.EMAIL@smtp.gmail.com:587/"
source "openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in pass.rsa |"

sourceの使用は設定ファイルによってマチマチなので個別に対応せねばならないが、 多くの場合は上記のように source "openssl ... |" で正しく動くと思う。