TORIPIYO DIARY

recent events, IoT, programming, security topics

WEBサイトの脆弱性学習に使えるOWASP Mutillidae IIのローカル環境での構築と簡単な使い方の紹介

【追記】
vagrantを立ち上げてすぐにphpmyadmin操作できるように、mutillidae_deploy.shにphpmyadmin/config.inc.php設定ファイルの書き換え処理を追加しました。

===========================================

最近WEBアプリのセキュリティについて勉強しているのですが、今回は実際に手元のローカル環境で手を動かしながら脆弱性を学ぶことができるOWASP Mutillidae IIというWEBアプリを紹介します。WEBアプリのソースは下記のサイトから配布されています。
https://sourceforge.net/projects/mutillidae/sourceforge.net

OWASP Mutillidae IIのローカル環境への構築方法

vagrant仮想マシンを立ち上げる

OWASP Mutillidae IIアプリは、LAMP環境で動作するのですが、ゼロからLAMP環境を構築するのは少し面倒なのでVagrantfileを作りました。

上記2個のファイルを配置したディレクトリ上で、

vagrant up

を実行すれば、OWASP Mutillidae IIアプリのインストールされたvirtual machineがローカル環境上に立ち上がります。vagrantのインストール方法はWEB上にたくさん掲載されているので別サイトで確認してください。

Mutillidae用のデータベースを設定する

vagrant upで仮想マシンが立ち上がった後は、
http://192.168.33.10/mutillidae/ で仮想マシンにブラウザからアクセスします。

下記の画面が表示されるので、"setup/reset the DB"のリンクをクリックすると、
f:id:ha107chan:20170816123804p:plain

また下記の画面が表示されるので、OKをクリックすれば、Mutillidae用のデータベースが仮想マシンMySQL上に構築されます。
f:id:ha107chan:20170816124134p:plain

HTTPS接続の有効化

デフォルトではMutillidaeとはHTTPで通信を行います。ただ、HTTPS通信に関する脆弱性などの勉強をしたいときにはHTTPSを有効化する必要があります。上記のVagrantfileでは、仮想マシン側でHTTPS通信が出来るようになる設定をしているので、MutillidaeアプリでもHTTPS通信をするように設定させます。

下記URLにアクセスして、
http://192.168.33.10/mutillidae/

下記画面のEnforce SSLをクリック。
f:id:ha107chan:20170816124506p:plain

自己証明書なので、下記のような警告画面が出ると思いますが、無視して先に進めます。(Chromeであれば、Proceed to 192.168.33.10 (unsafe)をクリック)
f:id:ha107chan:20170816124700p:plain

そうすると、HTTPSが有効になります。
f:id:ha107chan:20170816125144p:plain

OWASP Mutillidae IIの簡単な使い方

OWASP Top 10とは、ウェブサイトでよく見られる脆弱性のTop10を世界中のセキュリティの専門家がまとめて公表したものです。
Category:OWASP Top Ten Project - OWASP
数年ごとに内容を見直しているようで、OWASP Top 10(2010), OWASP Top 10(2013)などがあります。

例えば、OWASP Top 10(2017)のA1 - Injection(SQL)の内容を確認したい場合は、左側のメニューから順番に階層構造をたどって目的の脆弱性のデモ画面のリンクをクリックします。
f:id:ha107chan:20170816134022p:plain

このような感じで各機能の脆弱性を実際に自分の目で確かめながら確認することが出来ます。下記は、入力したHTMLタグ(br)がそのまま出力の際に処理されてしまっている例です。
f:id:ha107chan:20170816134445p:plain

How to Implement Nginx Client Certificate Authentication

When we need to collaborate with outside companies to manage web site's content, admin tool site is sometimes used. So admin tool has to be exposed on the Internet network. In this case password authentication function is often used to restrict other client's access. But Nginx can also use client certificate authentication function. So I would like to introduce client certificate implementation in this article.

client certificate authentication benefits
1. Nginx can deny irrelevant user's access.
2. Nginx can revoke issued client certificate at any time.

About 1, even if username and password is not leaked, hackers try to do a brute force attack indiscriminately. So password authentication might be broken someday. Client certificate authentication doesn't allow user access who doesn't have a client certificate. This feature makes the site more secure that is exposed to the Internet Network.
About 2, Nginx administrator can revoke the client certificate to deny admin tool access from unauthorized user when outside company's contract finishes.

How to implement client certificate authentication by Nginx

Nginx server side settings

Off course root user is used when configure Nginx settings. In this example Nginx is installed under "/usr/local/nginx" directory. Please adopt below instructions to your environment properly.

1. generate CA certificate and Key

mkdir -pv /usr/local/nginx/conf/client-certificates
cd /usr/local/nginx/conf/client-certificates

openssl genrsa -out ca.key 2048

# set proper certificate expiration date, in this example 2 years
# set site's domain name on "CN" field
openssl req -new -x509 -days 730 -key ca.key -out ca.crt -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=tool.toripiyo.com/emailAddress=admin@toripiyo.com"

2. generate CRL

# configure CRL for revocation settings
touch /etc/pki/CA/index.txt  && echo '01' > /etc/pki/CA/crlnumber
openssl ca -name CA_default -gencrl -keyfile ca.key -cert ca.crt -out ca.crl -crldays 730

diff -U0 <(openssl x509 -noout -modulus -in ca.crt) <(openssl rsa -noout -modulus -in ca.key)


3. generate client certificate for each user

# In this example "toripiyo" user's client certificate is generated
# Please iterate this process as you require
_CLIENTNAME='toripiyo'

mkdir /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
cd /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
openssl genrsa -out ${_CLIENTNAME}.key 2048
openssl req -new -key ${_CLIENTNAME}.key -out ${_CLIENTNAME}.csr -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=${_CLIENTNAME}/emailAddress=admin@toripiyo.com"

openssl x509 -req -days 365 -in ${_CLIENTNAME}.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -CAserial ../ca.seq -out ${_CLIENTNAME}.crt

# this command execution prompts the password input. don't forget the password. the password is used for client certificate registration
openssl pkcs12 -export -clcerts -in ${_CLIENTNAME}.crt -inkey ${_CLIENTNAME}.key -out ${_CLIENTNAME}.p12

# set file permission to 640
chmod 640 ${_CLIENTNAME}.*
ls -lta

4. configure Nginx settings

cd /usr/local/nginx/conf
cp -ivp nginx.conf{,.$(date +%Y%m%d)}
vi nginx.conf
# add the following directives that are related to client authentication
# - set clientcert log format
# - ssl_verify_client on: enable client certificate authenticate. if client certificate is not shown, access is defied.
----------------------------------------------------------------------------------------------
log_format clientcert '$remote_addr - $remote_user [$time_local] "$request" '
                   '$status $body_bytes_sent "$http_referer" '
                   '"$http_user_agent" "$http_x_forwarded_for" '
                   '$request_time $upstream_response_time '
                   '"$ssl_client_s_dn($ssl_client_serial)"';

ssl_client_certificate client-certificates/ca.crt;
ssl_crl client-certificates/ca.crl;
ssl_verify_client on;

access_log  logs/host.access.log  clientcert;
----------------------------------------------------------------------------------------------

5. restart Nginx

# stop Nginx daemon
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

# start Nginx daemon
/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

Client side settings

Client certificate file name will be ${_CLIENTNAME}.p12. On the way to client side settings requires the password that is set on above procedure.

macOS safari browser's client certificate settings

Adding a client certificate | Cybozu manual site

iOS safari browser's client certificate settings

Adding a client certificate | Cybozu manual site

typical regular operations for Nginx client certificate management

issue new client certificate for new user

If new client(tama) joins our team, issue the new client certificate by following below procedure.

1. issue client certificate
_CLIENTNAME='tama'

mkdir /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
cd /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
openssl genrsa -out ${_CLIENTNAME}.key 2048
openssl req -new -key ${_CLIENTNAME}.key -out ${_CLIENTNAME}.csr -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=${_CLIENTNAME}/emailAddress=admin@toripiyo.com"

openssl x509 -req -days 365 -in ${_CLIENTNAME}.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -CAserial ../ca.seq -out ${_CLIENTNAME}.crt

# password can be put on as a openssl option directly. "doraemon" is used as a password in this case
openssl pkcs12 -password doraemon -export -clcerts -in ${_CLIENTNAME}.crt -inkey ${_CLIENTNAME}.key -out ${_CLIENTNAME}.p12

# set file permission to 640
chmod 640 ${_CLIENTNAME}.*
ls -lta

2.Nginx restart is not required

3. Share new client certificate with new user

revoke specific client certificate

When tama leaves our team, following procedure makes the certificate to be revoked.

1. update index.txt
_CLIENTNAME='tama'
cd /usr/local/nginx/conf/client-certificates
openssl ca -name CA_default \
    -revoke ${_CLIENTNAME}/${_CLIENTNAME}.crt \
    -keyfile ca.key \
    -cert ca.crt

2. update ca.crl
openssl ca -name CA_default -gencrl \
    -keyfile ca.key \
    -cert ca.crt \
    -out ca.crl \
    -crldays 730

3. restart nginx
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

reactivate the revoked certificate

If tama withdraws team leaving, following procedure makes the certificate to be reactivated.

1. modify index.txt
vi /etc/pki/CA/index.txt
====================
1. change "R" => "V" on first column of corresponding certificate row
2. delete third column characters of corresponding certificate row (important: tabs between second and fourth colomn not to be deleted!! If not, openssl outputs error message.)
====================

2. update ca.crl
cd /usr/local/nginx/conf/client-certificates
openssl ca -name CA_default -gencrl \
    -keyfile ca.key \
    -cert ca.crt \
    -out ca.crl \
    -crldays 730

3. restart nginx
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

友達に会いにマレーシアまで旅行に行ってきた

ちょっと前、7月の上旬にマレーシアで働いている友達に会いに行ってきました。
f:id:ha107chan:20170708124704j:plain

訪れた場所は、クアラルンプールとペナン島です。いままで東南アジアはタイとカンボジアに行ったことがあるのですが、マレーシアは一番治安が良いように感じました。ただ、ボルネオ島の東側は海賊が出るそうなので、東側の島に行くときは注意が必要です。マレーシアにはマレー系と中国系とインド系の人がいて、日本に比べれば多民族国家です。ごはんもマレー料理、中華料理、インド料理のレストランがあります。(マレー料理のレストランではアルコールは飲めないそうです。間違えてマレー料理の店にアルコールを持ち込まないように気をつけましょう。)物価は日本の3分の1ぐらいだそうで、大変住みやすそうな国でした。Gacktが住むのも納得です。

気候

気候は年中夏の天気で、天気予報を見るといつも晴れときどき雷雨となっています。ただ気温は30度前後で、自分が滞在していたときは40度近い気温にはなりませんでした。友達はいつも夏なので服をあまり買わなくなったそうです。
f:id:ha107chan:20170812144711p:plain

シムフリー

いつも海外旅行ではシムフリーを利用しているのですが、マレーシアが一番手続きが簡単でした。KLIA2の空港に着いて入り口を出るとプリペイドシムフリーを販売している販売店がいくつもあります。自分はdigiという会社のシムフリーを買いました。値段はたしか500~800円で3GBぐらいあったと思います。旅行中ずっと使いましたが、ペナン島でも問題なくLTEを利用できました。ただ、マレーシアの通過のリンギットでないとシムフリーを購入できなかったので、まず空港内の両替所で日本円からリンギットに両替しましょう。マレーシアで両替したほうが日本よりも交換レートは良いそうです。

街中の移動方法

マレーシアにもUberはあるのですが、Grabというアプリがマレーシアでは一番はやっているそうです。友達は空港に行くときによく利用すると言っていました。運転手は様々で、普通のおじさんからものすごい若い見た目(中学生?に見えた)の人まで様々な人が運転手をしていました。現金払いもできるようで、友達はクレジットカード登録は怖いのでいつも現金払いをしていると言っていました。
f:id:ha107chan:20170812151357j:plain

クアラルンプールからペナン島への行き方

マレーシアで働く友達が事前にエアアジアの国内便を予約してくれていたので飛行機で行きました。KLIA2とペナン空港を往復でチケット代は5000円ほどです。飛行機に乗る時間自体は1時間弱なのですが、空港までの移動や空港での待ち時間を入れると合計5時間ぐらいはかかっている気がします。

マレーシアのたべもの

中国料理

  • チャーシュー

初日の朝ごはんで行った中国料理店で食べたチャーシュー(?)はとても美味しかった。
一応、屋内だけど外と屋内を仕切る壁が全くなく、地元の人も朝から通っているようだった。
f:id:ha107chan:20170708090043j:plain

マレー料理

  • ホテルの朝ごはん

マレー系の人が経営しているホテルにペナン島では泊まったので朝食のメインはマレー系料理です。ココナッツの汁でといたごはんは甘いのかと思っていたのですが、食べてみるとそんなに甘さは感じませんでした。
f:id:ha107chan:20170709082335j:plain

  • ラクサ

マレーシアの麺料理ラクサ。ペナンの空港で食べました。麺が柔らかくて、酸っぱいスープは日本ではなかなか味わえないので、食べれば記憶に残ります。
【マレーシアソウルフード ヌードル編】 | マレーシアマガジン
f:id:ha107chan:20170709131357j:plain


インド料理
食べていない。。。。つぎ来たときは食べよう!

その他

  • あんぱん

見た目はそれほど美味しそうに見えないけれど、個人的にはものすごくお薦めしたいあんぱん。30~40円ぐらいでスーパーで売られていて、日本のコンビニで売られているアンパンよりもちもちして柔らかくて美味しかった。
f:id:ha107chan:20170709154436j:plain

日本では売られていない不思議な味がした。ポカリスエットに炭酸。これはこれで、ありかもしれない。
f:id:ha107chan:20170708194844j:plain

  • ドリアン

噂どおり、においが強烈!!結局、現地で生のものを食べる勇気は持てなかった。
f:id:ha107chan:20170708202510j:plain

行った場所
  • バトゥ洞窟

洞窟の中にあるお寺で、ヒンドゥー教の聖地だそうです。自分が訪れたときには洞窟内で工事が行われていました。洞窟内にある像の配色がとてもカラフルで、京都などのお寺にある仏像とは全然異なっていました。お土産物屋さんの商品もとてもカラフルです。
f:id:ha107chan:20170708101654j:plainf:id:ha107chan:20170708102334j:plain

  • バードパーク

クアラルンプールにある様々な種類の鳥を見ることができる施設です。入場料は1000円を超えてマレーシアにしてはちょっと高いですが、入ればいろんな種類の鳥を見ることが出来るので元は取ることが出来ると思います。この施設の中にはドクターフィッシュの出来る場所があって、日陰で休みながら魚に古い角質を食べてもらいました。ドクターフィッシュ自体の料金はそんな高くなかったと思います。
f:id:ha107chan:20170708111849j:plainf:id:ha107chan:20170708112646j:plain

ちょうどペナン島に行ったときには夜にお祭りがやっていたようで、夜の街はたくさんの人で賑わっていました。人が多いので荷物には気をつけていたのですが、置き引きなどがいるようには感じませんでした。ストリートパフォーマンスをしている人や、いろんな露店があるので、食べながら夜の街並みを探検するのも楽しいです。
f:id:ha107chan:20170708194148j:plainf:id:ha107chan:20170708195253j:plain

  • ペナンプラナカンマンション

ペナン島にある昔の中国系の富豪の家を博物館として公開している場所です。華やかな暮らしを数々の装飾品から感じることが出来ます。自分もこんな家に住みたい。。。
f:id:ha107chan:20170709094803j:plainf:id:ha107chan:20170709095828j:plain

おみやげ
  • ドリアンチョコ

現地で生のドリアンを食べる機会はなかったので、空港の売店でベリーズのドリアンチョコを買いました。チョコになっているので少しドリアンの風味がするぐらいかなと思っていたのですが、強烈な匂いはチョコになっても健在ですw 自分は結局1個しか食べることが出来なくて、会社に持っていっても日本人はほとんど食べず中国人や台湾人の方が食べていました。次は普通のチョコを買おうと思います。



まだまだいろいろと食べてない料理や行ってない場所など、マレーシアにはたくさんあるので、友達が働いている間にまた行こうと思います。

nginxでクライアント証明書認証の設定と運用時に失効させる方法

WEBサイトの管理者ツールサイトを、例えば協力会社など外部の人にも操作してもらう必要があるときには、どうしてもインターネットに公開しないといけなくなることがあると思います。こういったとき、一般のユーザからのアクセスを拒否するためにユーザ名とパスワードで認証するように実装することが多いのですが、nginxではクライアント認証機能も利用できるのでその方法を紹介します。

クライアント認証にすると以下のメリットがあります
1. クライアント証明書を持っていないユーザに対してはログインを拒否できる
2. 証明書を失効できる

1について、ユーザ名・パスワードがたとえ漏洩していなくても、インターネット上からは絶えずブルートフォースアタックなどの攻撃を受けることになるので認証を突破される可能性があります。クライアント証明書認証ではクライアント証明書を持っている人しかログイン出来ないのでよりセキュアにインターネット上に管理ツールサイトを公開できます。
2について、協力会社との契約が終わった後に、証明書を失効することでクライアント証明書を持っていてもログインを拒否できるようになります。

nginxでのクライアント証明書認証の設定方法

サーバ側の設定

nginxのインストールされているサーバでrootユーザで実行します。nginxは/usr/local/nginxディレクトリの配下にインストールされている想定で進めます。自分の環境に合わせて適時修正してください。

1. CA証明書と鍵の作成

mkdir -pv /usr/local/nginx/conf/client-certificates
cd /usr/local/nginx/conf/client-certificates

openssl genrsa -out ca.key 2048
# 証明書の期限は適切に設定する、ここでは2年(730日)に設定している
# CNには管理ツールサイトのドメイン名を記載する
openssl req -new -x509 -days 730 -key ca.key -out ca.crt -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=tool.toripiyo.com/emailAddress=admin@toripiyo.com"

2. CRLの作成

# クライアント証明書の失効に利用するのでCRLの設定をする
touch /etc/pki/CA/index.txt  && echo '01' > /etc/pki/CA/crlnumber
openssl ca -name CA_default -gencrl -keyfile ca.key -cert ca.crt -out ca.crl -crldays 730

diff -U0 <(openssl x509 -noout -modulus -in ca.crt) <(openssl rsa -noout -modulus -in ca.key)


3. クライアント証明書をユーザ数分作成

# ここではtoripiyoというユーザのクライアント証明書を作成している
_CLIENTNAME='toripiyo'

mkdir /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
cd /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
openssl genrsa -out ${_CLIENTNAME}.key 2048
openssl req -new -key ${_CLIENTNAME}.key -out ${_CLIENTNAME}.csr -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=${_CLIENTNAME}/emailAddress=admin@toripiyo.com"

openssl x509 -req -days 365 -in ${_CLIENTNAME}.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -CAserial ../ca.seq -out ${_CLIENTNAME}.crt

# 実行するとパスワードの入力を求められるので入力したパスワードを忘れないように注意!
openssl pkcs12 -export -clcerts -in ${_CLIENTNAME}.crt -inkey ${_CLIENTNAME}.key -out ${_CLIENTNAME}.p12

# set file permission to 640
chmod 640 ${_CLIENTNAME}.*
ls -lta

4. nginxの設定を変更

cd /usr/local/nginx/conf
cp -ivp nginx.conf{,.$(date +%Y%m%d)}
vi nginx.conf
# client証明に関連した以下のdirectiveを追加する
# - clientcertというログフォーマットを追加
# - ssl_verify_client on: クライアント認証する、証明書の提示がないとアクセス拒否
----------------------------------------------------------------------------------------------
log_format clientcert '$remote_addr - $remote_user [$time_local] "$request" '
                   '$status $body_bytes_sent "$http_referer" '
                   '"$http_user_agent" "$http_x_forwarded_for" '
                   '$request_time $upstream_response_time '
                   '"$ssl_client_s_dn($ssl_client_serial)"';

ssl_client_certificate client-certificates/ca.crt;
ssl_crl client-certificates/ca.crl;
ssl_verify_client on;

access_log  logs/host.access.log  clientcert;
----------------------------------------------------------------------------------------------

5. nginxを再起動

# nginxを止める
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

# nginxを開始する
/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

クライアント側の設定

クライアント証明書のファイルは、サーバ側の設定で作成した${_CLIENTNAME}.p12 となります。設定の際には、クライアント証明書作成時に設定したパスワードが必要になります。

macOSsafariブラウザ環境でのクライアント証明書の設定方法

Safari(Mac版) - cybozu.com ヘルプ

iOSsafariブラウザ環境でのクライアント証明書の設定方法

iPhone/iPad版 - cybozu.com ヘルプ

nginxでのクライアント証明書認証の運用で定常的に発生しそうな設定変更

新しいユーザ向けのクライアント証明書の新規発行方法

新しく管理ツールサイトを操作するtamaさんが入ってきたときは、以下のようにしてクライアント証明書を新規に発行します。

1. クライアント証明書を発行
_CLIENTNAME='tama'

mkdir /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
cd /usr/local/nginx/conf/client-certificates/${_CLIENTNAME}
openssl genrsa -out ${_CLIENTNAME}.key 2048
openssl req -new -key ${_CLIENTNAME}.key -out ${_CLIENTNAME}.csr -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Cat Inc./OU=Development/CN=${_CLIENTNAME}/emailAddress=admin@toripiyo.com"

openssl x509 -req -days 365 -in ${_CLIENTNAME}.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -CAserial ../ca.seq -out ${_CLIENTNAME}.crt

# パスワードを直接引数に指定することも可能。doraemonというパスワードを今回は指定している
openssl pkcs12 -password doraemon -export -clcerts -in ${_CLIENTNAME}.crt -inkey ${_CLIENTNAME}.key -out ${_CLIENTNAME}.p12

# set file permission to 640
chmod 640 ${_CLIENTNAME}.*
ls -lta

2. nginxの再起動は不要

3. クライアント証明書を配布するためにローカルPCに取得

特定のクライアント証明書の無効化方法

tamaさんが、管理ツールサイトを利用しなくなった場合は、以下のようにしてクライアント証明書を無効にさせます。

1. index.txt を更新する
_CLIENTNAME='tama'
cd /usr/local/nginx/conf/client-certificates
openssl ca -name CA_default \
    -revoke ${_CLIENTNAME}/${_CLIENTNAME}.crt \
    -keyfile ca.key \
    -cert ca.crt

2. ca.crl を更新する
openssl ca -name CA_default -gencrl \
    -keyfile ca.key \
    -cert ca.crt \
    -out ca.crl \
    -crldays 730

3. nginxを再起動する
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

無効化してしまった証明書を再び有効化する方法

tamaさんのクライアント証明書を無効にしたけれど、やっぱり管理ツールサイトを利用する必要がありクライアント証明書の再配布をしたくない場合は以下のようにします。

1. index.txtのファイルを編集
vi /etc/pki/CA/index.txt
====================
- 該当する行の最初の列の"R" と記載のある項目を "V" に変更
- 該当する行の3番目の列を削除 (2列目と4列目にあるカラムを残しておかないと次のopensslコマンドでエラーを出すので文字だけを消すようにすること。3番目の列は""となる。)
====================

2. ca.crlを更新
cd /usr/local/nginx/conf/client-certificates
openssl ca -name CA_default -gencrl \
    -keyfile ca.key \
    -cert ca.crt \
    -out ca.crl \
    -crldays 730

3. nginxを再起動する
ps aux | grep -i nginx
/etc/init.d/nginx stop
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

/etc/init.d/nginx start
ps aux | grep -i nginx
less /usr/local/nginx/logs/error.log

openvpnを使ってaws環境にVPNサーバを比較的低コストで構築する方法

追記

Amazon Linux 2 向けに新しく記事を書き直しました!
toripiyo.hatenablog.com
=============================================================

家のネットワークとAWS環境をVPNで繋ぎたくて、openvpnVPN環境を構築してみました。いろんなサイトを参考にしながら構築しているので、その手順をまとめたいと思います。中小企業であれば、専用のVPN機器を購入しなくてもこれで十分ではないかと思います。VPNにかかるコストはt2.nanoの稼働コストのみなので、比較的安い費用でvpnを構築できます。

f:id:ha107chan:20170723204801p:plain

上図の構成の通り、VPNサーバをAWS環境上に構築します。この構成を取ることで、

  • ユーザはVPNサーバを通してSSHやHTTP通信を行えるようになり、サービスを不必要に外部に公開しなくても良くなります。例えば、データベースサーバをMacなどから直接いじりたいときも、データベースサーバをインターネット環境に公開する必要はありません。
  • ユーザ個別に証明書と鍵を発行することでプロジェクトから抜けたユーザがAWS環境にアクセス出来ないように個別にアクセス制御が出来ます。


このVPNサーバは、1個のVPCに1個構築するイメージで構築しています。ですので、複数のVPCVPNサーバを利用したい場合は、VPNサーバを各VPCごとに構築する必要がありますのでお気をつけください。

VPN 環境の構築

VPNサーバの構築

VPNサーバ用のEC2インスタンスを起動

そんなに高いスペックでなくても、数人のユーザで利用するのであれば負荷はほとんどなく利用できます。
spec

  • AMI:amzn-ami-hvm-2017.03.1.20170623-x86_64-gp2, SSD Volume Type
  • Subnet: subnet1 (subnet1は、インターネットと通信できるようにInternet Gatewayがルーティングテーブルに設定されている必要がある。)
  • instance type: t2.nano
  • root volume: ebs

security groupを設定
以下のInbound設定をする

# vpn接続で利用するポート
TCP/1194
# vpnサーバにsshログインして作業するために開ける、作業が終わったら閉じても構わない
SSH/TCP/22

elastic IPを設定
VPNサーバのグローバルIPアドレスを固定するために、AWSのコンソールから設定する

日本時間に修正

clockファイルの修正

vi /etc/sysconfig/clock

# ZONE="UTC"
ZONE="Japan"
UTC=true

シンボリックリンクの修正

ln -sf /usr/share/zoneinfo/Japan /etc/localtime
OS内のネットワーク設定の修正

ip forwardingの有効化

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -w net.ipv4.ip_forward=1
cat /proc/sys/net/ipv4/ip_forward # 1となっていることを確認

ip masqueradeの有効化

echo "iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE" >> /etc/rc.local (ip masqueradeの起動時の有効化)
openvpnのインストール

パッケージのアップデート

yum update -y

openvpnパッケージのインストール

yum install -y openvpn

easy-rsaパッケージのインストール

yum install easy-rsa -y --enablerepo=epel
証明書の作成

CA証明書と鍵の作成

cd /usr/share/easy-rsa/2.0
vi vars

# 組織情報とあうように適切な値を入力する
export KEY_COUNTRY="JP"
export KEY_PROVINCE="Tokyo"
export KEY_CITY="Ota-ku"
export KEY_ORG="Cat Inc."
export KEY_EMAIL="admin@toripiyo.com"
export KEY_OU="Development Unit"

. ./vars
./clean-all # "NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/share/easy-rsa/2.0/keys" message will be shown.
./build-ca # use default value

サーバ証明書と鍵の作成

./build-key-server server  # set "common name" => vpn host name

クライアント証明書と鍵の作成

  • プロンプトが表示されたときは、基本的にそのままEnterを押していけば大丈夫
  • 下記では、tamaというユーザ向けのクライアント証明書と鍵を作成する例
./build-key tama

Diffie Hellmanパラメータの生成

# 少し生成に時間がかかる
./build-dh
証明書失効のための設定
  • ダミー証明書を作成して失効する、一度実施しないと証明書失効リストファイルが作成されない
cd /usr/share/easy-rsa/2.0
. ./vars
./build-key dummy # use default value
./revoke-full dummy (keys/crl.pem ファイルが作成される)
openvpnサーバの設定

server.confファイルの編集
protoをudpにしているサイトが多いけれど、tcpに変更したほうが接続が安定したのでtcpにしている

sudo cp /usr/share/doc/openvpn-*/sample/sample-config-files/server.conf /etc/openvpn/

vi /etc/openvpn/server.conf

# 以下の設定で上書きする
port 1194
proto tcp
dev tun
ca /usr/share/easy-rsa/2.0/keys/ca.crt
cert /usr/share/easy-rsa/2.0/keys/server.crt
key /usr/share/easy-rsa/2.0/keys/server.key  # This file should be kept a secret
dh /usr/share/easy-rsa/2.0/keys/dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 10.1.0.0 255.255.0.0" #VPC内部のプライベートIPレンジが10.1.0.0/16の場合
keepalive 10 120
comp-lzo
max-clients 20
persist-key
persist-tun
status openvpn-status.log
log-append  /var/log/openvpn.log
verb 3
crl-verify /usr/share/easy-rsa/2.0/keys/crl.pem

openvpn自動起動の有効化

chkconfig openvpn on

openvpnサーバの起動

openvpn /etc/openvpn/server.conf

サーバ再起動

  • サーバを再起動してもopenvpnは正常に稼働するか確認するためにサーバを再起動
reboot

VPNクライアントの設定

VPNサーバを構築できたらVPNに繋げるようにクライアント側の設定をする

tunnelbrickのインストール

homebrewのcaskを利用してインストール

brew cask install tunnelblick
証明書と鍵を入手

(ユーザ名).key, (ユーザ名).crt, ca.crtの3ファイルが必要になるのでVPNサーバからscpなどで取得しておく

client.confファイルの作成
  • Macのhomeディレクトリの下に、.vpnというディレクトリを作成して、 (ユーザ名).key, (ユーザ名).crt, ca.crtの3ファイルを置く
  • .vpnディレクトリの配下などで、client.confファイルを作成する(ファイル名は好きな名前に変更しても大丈夫)
  • client.conf
client
dev tun
proto tcp
remote (vpnサーバのグローバルIPアドレス) 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca (ca.crtのファイルパス)
cert ((ユーザ名).crtのファイルパス)
key ((ユーザ名).keyのファイルパス)
remote-cert-tls server
comp-lzo
verb 3
tunnelbrickによる接続
  • tunnelbrickを起動する
  • client.confのファイルを画面右上のtunnelbrickのアイコンにドラッグアンドドロップする
  • 表示されてきたプロンプト画面でOnly Meをクリックする
  • Macのパスワード入力を求められるので入力する。これでVPNサーバとクライアントでコネクションを貼れるようになる。

VPNの運用

新しいクライアントの追加作業

新しくvpnを使うユーザが増えた場合は以下のように作業します。
生成された(新しいユーザ名) .crt, (新しいユーザ名) .key と ca.crtのファイルを新しいユーザに共有してあげてください。

cd /usr/share/easy-rsa/2.0
. ./vars
./build-key (新しいユーザ名) # use default value
* openvpnの再起動は不要

既存のクライアントの削除作業

退職したなどの理由で、特定のユーザがvpnを使えないようにするには以下のように作業します。

cd /usr/share/easy-rsa/2.0
. ./vars
./revoke-full (削除するユーザ 名) (keys/crl.pem ファイルが作成される)
* openvpnの再起動は不要

raspberry pi 3にclamavを導入する

最近、raspberry piのセキュリティが気になって色々と設定しているのですが、今回はclamavの設定を書きます。ドキュメントなど読むと、clamavには2種類の動かし方があるようです。

1. scanのときにプロセスを立ち上げる方法
2. デーモンを立ち上げておく方法

1の方法でファイルをscanするときは、clamscanコマンド。2の方法でファイルをscanするときは、clamdscanコマンドを利用します。この2種類のコマンドを比較すると、scanの速度に違いがありました。
(ちなみに、自分が見つけた中では公式のサイトのpdfドキュメントが一番詳しく記載されていました。https://github.com/vrtadmin/clamav-faq/raw/master/manual/clamdoc.pdf


raspberry pi 3上で732個のファイル(ファイルの合計の大きさは2.4GB)のscanを比較した場合

clamscan: 3min19sec
clamdscan: 2min9sec


デーモンを立ち上げていると、一定のメモリ量が常に消費されてしまいますが、scan時のパフォーマンスはデーモンモードのほうが良さそうです。一番避けたい設定はclamdをデーモンで立ち上げているのに、scanはclamscanで実行している場合です。こうすると、scan時にメモリを追加で消費することになってしまい、scanのスピードも遅くなります。
www.riscascape.net


clamavは、指定されたファイルをscanして、データベースに登録されたウイルス署名と一致したファイルがないかどうか確認します。ですので、ウイルス署名のデータベース情報は定期的に更新される必要があります。freshclamコマンドはインターネットから最新のウイルス署名情報を取得してくれます。freshclamにもデーモンモードがあり、デーモンで起動していると、定期的にウイルス署名情報を取得するようです。

以上を踏まえて、自分の場合は、以下のようにraspberry piclamavを設定しました。これで、webコンテンツ以下のファイルに対して毎日深夜の時間帯にスキャンをかけ、virusが検知されたらslackに通知されるようになります。

1. install clamav

apt-get update
apt-get install clamav clamav-daemon

2. update virus definition database

freshclam

3. create script file (hooks.slack.com のURLは適宜変更)

cd /root
vi virusscan.sh
------------------------------------------------
#!/bin/bash
PATH=/usr/bin:/bin

# virus scan
CLAMSCANTMP=`mktemp`
TIME=`date`
MESSAGE="Virus is detected!!: ${TIME}"
clamdscan /var/www/html/data > $CLAMSCANTMP 2>&1

# report slack
grep FOUND$ $CLAMSCANTMP && \
curl -X POST --data-urlencode 'payload={"channel": "#alerts", "username": "alerts", "text": "'"${MESSAGE}"'", "icon_emoji": ":dog:"}' https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXX
rm -f $CLAMSCANTMP
------------------------------------------------
chmod 700 virusscan.sh

4. set cron job

crontab -e
------------------------------------------------
00 04 * * * sh /root/virusscan.sh
------------------------------------------------


ドキュメントを読むと、以下のコマンドがあったのでメモも兼ねて記載しておきます。

clamconf

  • clamavの設定情報を表示する
root@raspberrypi:~# clamconf | head
Checking configuration files in /etc/clamav

Config file: clamd.conf
-----------------------
LogFile = "/var/log/clamav/clamav.log"
StatsHostID = "auto"
StatsEnabled disabled
StatsPEDisabled = "yes"
StatsTimeout = "10"
LogFileUnlock disabled

clamtop

  ClamdTOP version 0.99.2   Mon Jul 17 23:41:19 2017
NO CONNTIME LIV IDL QUEUE  MAXQ   MEM HOST           ENGINE DBVER DBTIME
 1 00:00:14   1   0     0     0  471M local          0.99.2 23571 2017-07-17 17h
Details for Clamd version:  ClamAV 0.99.2/23571/Mon Jul 17 17:08:59 2017
Primary threads: live   1 idle   0 max  12                                                                                                  ┌───────────────────────────────────────┐
 [|||                                 ]                                                                                                     │Mem:  heap    1M mmap    0M unused   0M│
Queue:     0 items      0 max                                                                                                               │Libc: used    1M free    0M total    1M│
 [                                    ]                                                                                                     │Pool: count    1 used  470M total  470M│
                                                                                                                                            │[||||||||||||||||||||||||||||||||||||] │
                                                                                                                                            └───────────────────────────────────────

dockerコンテナのrailsコンソールで日本語入力をコンテナ再ビルドなしで出来るようにする方法

日本語がdockerコンテナのrailsコンソール上で入力できないので調べてみると、
以下のようにbuildし直すと出来るようになると記事がありました。
http://qiita.com/suin/items/856bf782d0d295352e51

ただ、再ビルドするのも面倒なので、
以下のようにrailsコンソールの実行時にenvで環境変数を指定することで日本語入力出来るようになりました。

root@b2de32d57cf1:/app# env LANG=C.UTF-8 rails c
Running via Spring preloader in process 104
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> a = "日本語が入力できる!!"
=> "日本語が入力できる!!"