レンタルサーバ上に家族向けの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の場合は以下のような画面が表示された。
コメント