クローズドに運用したいWebサイトの構築

レンタルサーバ上に家族向けのWebサイトを作っていて、外部の人間からアクセスできないようにしたいと思ったのでメモ。

【環境】
CentOS Linux release 7.9.2009 (Core)

検索エンジンに引っかからないようにする

まずは、Googleなどの検索エンジンで、検索結果に出てこないようにします。これで、基本的にはURLを知っている人間しかアクセスできなくなるはず。

自作ページ

各WebページにmetaタグをくっつければOK。

<!DOCTYPE html>
<html lang="ja">
<head>
...
  <meta name="robots" content="noindex">
...
</head>

WordPress

WordPressの設定で実装可能。

[設定]->[表示設定]を選択。

「検索エンジンがサイトをインデックスしないようにする」にチェックを入れて保存します。これで固定ページ・記事いずれも自動的に検索対象外になる。

一応ディベロッパーツールで確認してみたが、やってることは一緒のよう。ついでにnofollowも付与されている。

ユーザ認証(Basic認証)

次に、ユーザID/パスワードによる認証機能をBasicで実装する。

Apacheのルートディレクトリへ移動し、①.htpasswd(アカウント情報を管理するファイル)と②.htaccess(コンフィグファイルみたいなもの)をそれぞれ作成、Apacheを再起動。

.htpasswdの「user1」「password1」はそれぞれユーザIDとパスワードになるので、適切な値を設定。

.htaccessのRewriteEngine~はHTTPSを強制するための定義。せっかくなので入れておく。

# cd /var/www/html
# vim .htpasswd

user1: password1
user2: password2
 
# vim .htaccess

AuthType Basic
AuthName "Login Password Required"
AuthUserFile /var/www/html/.htpasswd
require valid-user

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
 
# systemctl restart httpd

ちなみに、パスワードにランダムな文字列を使いたい場合、以下のコマンドで生成可能。紛らわしい文字は適当な記号に置換。桁数を変える際は、fold -w 10の”10″を変更。

# openssl rand -base64 12 | fold -w 10 | head -1 | tr '1Il0O' '^@<>-'
njhL/AKK8h

動作確認してみる。ブラウザから該当のページへアクセスすると、Basic認証の画面が表示された。これで、アカウント情報を知らない人間はアクセス不可となる。

端末認証(クライアント証明書)

最後に、端末認証の仕組みを導入する。これにより、万一アカウント情報が流出したり、極論総当たりで突破されたとしても、証明書がインストールされていない限り、アクセス不可となるはず。

プライベート認証局の構築

認証機能を準備する。

$ vim /etc/pki/tls/openssl.cnf

[ usr_cert ]
basicConstraints=CA:FALSE
 ↓
basicConstraints=CA:TRUE

[ v3_ca ]
# nsCertType = sslCA, emailCA
 ↓
nsCertType = sslCA, emailCA

$ vim /etc/pki/tls/misc/CA

CADAYS="-days 1095" # 3 years
 ↓
CADAYS="-days 10950" # 30 years

$ vim /etc/pki/CA/serial

00

$ /etc/pki/tls/misc/CA -newca

※記載を省いている箇所は空エンターでOK

(略)
Enter PEM pass phrase:ss phrase:1234
Verifying - Enter PEM pass phrase:1234
(略)
Country Name (2 letter code) [XX]: JP
State or Province Name (full name) []: Tokyo
(略)
Common Name (eg, your name or your server's hostname) []: private-ca
(略)
Enter pass phrase for /etc/pki/CA/private/./cakey.pem:1234
(略)
Write out database with 1 new entries
Data Base Updated

$ openssl rsa -in /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/private/cakey.pem

Enter pass phrase for cakey.pem: 1234 ←表示されません

$ vim /etc/pki/tls/openssl.cnf

[ CA_default ]
default_days = 365
 ↓
default_days = 36500

[ usr_cert ]
basicConstraints=CA:TRUE
 ↓
basicConstraints=CA:FALSE

# nsCertType = client, email, objsign
 ↓
nsCertType = client, email, objsign

[ v3_ca ]
nsCertType = sslCA, emailCA
 ↓
# nsCertType = sslCA, emailCA

クライアント証明書の発行

実際にクライアントへインストールする証明書を作成する。

$ mkdir /etc/pki/tls/client
$ cd /etc/pki/tls/client/
$ openssl genrsa -out client.key 2048
$ openssl req -new -key client.key -out client.csr

※記載を省いている箇所は空エンターでOK

Country Name (2 letter code) [XX]: JP
State or Province Name (full name) []: Tokyo
(略)
Common Name (eg, your name or your server's hostname) []: client
(略)

$ openssl ca -in client.csr -out client.crt
Certificate is to be certified until Apr 15 21:26:01 2120 GMT (36500 days)
Sign the certificate? [y/n]: y
 
1 out of 1 certificate requests certified, commit? [y/n] y
Write out database with 1 new entries
Data Base Updated

$ openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12

※ここで入力したパスワードがクライアントへのインストール時に必要になるため注意

Enter Export Password:<パスワード>
Verifying - Enter Export <パスワード>

生成されたクライアント証明書(/etc/pki/tls/client/client.p12)をFTP等で手元のPCへ持ってきておく。スマホからもアクセスできるように、Googleドライブとかに入れてシェアするとよさそう。

クライアント証明書認証設定

クライアント証明書がないとアクセスできないように設定する。

SSL化の設定が入っているファイルを編集する。手元の環境では、/etc/httpd/conf/httpd-le-ssl.confに設定が入っていたので、網掛けの箇所を追記。

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin root@example.com
DocumentRoot /var/www/html
ServerName hogehoge
ServerAlias example.com
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

# Client Certification ---
SSLCACertificateFile /etc/pki/CA/cacert.pem
SSLVerifyDepth 1

<Directory "/var/www/html">
    SSLVerifyClient require
    Require expr %{SSL_CLIENT_S_DN_CN} == 'client'
</Directory>
# Client Certification ---

</VirtualHost>
</IfModule>

最後にApacheを再起動。

$ systemctl restart httpd

これでサーバ側の設定は完了。試しにアクセスしてみると、見事に拒否された。

クライアント証明書のインストール

ブラウザによって手順が異なる。以下Chromeの手順。

PC

設定を開く。

[プライバシーとセキュリティ]->[セキュリティ]

[証明書の管理]

[インポート]

[次へ]

先ほど作成した証明書を選択して[次へ]

証明書作成時に設定したパスワードを入力し[次へ]

証明書ストア:個人を選択し[次へ]

[完了]

再度サイトにアクセスしてみると、証明書を選択する画面が表示されるので[OK]

ちなみに、Basic認証はこの後に表示された。

Android

ダウンロードした証明書ファイルを開けばインストールが走る。

以下はGoogleドライブからダウンロードする例。ファイルをタップ。

インストーラが起動された。パスワードは、証明書作成時のもの。

証明書の種類の選択では、[VPNとアプリユーザー証明書]を選択。

以上でインストール完了。サイトにアクセスすると、Androidの場合は以下のような画面が表示された。

コメント

タイトルとURLをコピーしました