LoginSignup
5
2

More than 1 year has passed since last update.

LAN上にhttps対応のwebサーバを建て、Androidスマホのchromeから警告が表示されない状態でアクセスした手順

Last updated at Posted at 2020-10-11

初めに

プログレッシブwebアプリ(PWA)を展開するには、HTTPS通信でつながる環境が必要になります。
レンタルサーバを借りることなく、LAN上でPWAを展開、動作確認できる手段はないかと、調査した結果です。

環境

  • Windows10 Home
  • Node.js(v12.13.0)
  • Androidスマホ (KYOCERA TORQUE® G03 Androidバージョン 6.0.1)
  • Visual Studio Code
  • wifi環境

Windows Subsystem for Linux(WSL)のインストール

https通信を行うにあたり、DNSサーバの構築、サーバ証明書の作成が必要です。
当方が調査したところ、DNSサーバの構築にはUnbound、サーバ証明書の作成にはOpenSSLが見つかりました。Unbound、OpenSSLはともに、Windwos版もありますが、仮想Ubuntuを用いたほうが、壁にぶつかることが少なく進めることができました。のちに、下記参考記事を見つけ、仮想UbuntuではなくWSLを用いたほうがよりスムーズでした。そのWSLをインストールします。
(参考)【連載】WSL2、Visual Studio Code、DockerでグッとよくなるWindows開発環境 〜 その1:まずは概要 〜 | SIOS Tech. Lab

1. Windows PowerShellを管理者権限で起動
2. コマンドを実行する
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

再起動確認が現れるので、再起動します。

3. Ubuntu 20.04LTSをインストールする

MicroSoftStoreを起動し、Ubuntu 20.04LTSを検索し、インストールします。

Unboundを用いて、LAN上にDNSサーバを建てる

(参考)Ubuntu Serverで内向きDNSをUnboundを使ってやってみたのでメモ - Qiita
当手順は、Ubuntuでの作業になります。
当手順にて、Windows10をDNSサーバとして機能するようにします。

1. Windowsのスタートボタンより、「Ubuntu 20.04LTS」を起動する
2. Unboundをインストールする

下記コマンドを実行します。

sudo apt install unbound
3. 設定ファイルのサンプルをコピーする

下記コマンドを実行します。

sudo cp /usr/share/doc/unbound/examples/unbound.conf /etc/unbound/unbound.conf.d
4. 設定ファイルを編集する

下記コマンドを実行し設定ファイルを開きます。

sudo nano /etc/unbound/unbound.conf.d/unbound.conf

開いた設定ファイルを編集します。

unboud.conf
server: 
  verbosity: 1

  interface: 0.0.0.0

  access-control: 127.0.0.0/23 allow
  #以下は環境に応じて変更する
  #当方の環境が192.168.0.xxx系統であったので、192.168.0.0/23 allowとしています。
  #各々の環境に合わせて設定してください。
  access-control: 192.168.0.0/23 allow

  #ドメイン名とIPアドレスを紐づける
  #この例では、192.168.0.100にexample.comというドメイン名を紐づけています。
  local-data: "example.com. IN A 192.168.0.100"

python: 
remote-control:
forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 1.1.1.1
  forward-addr: 1.0.0.1
5. Unboudを開始する
sudo service unbound start

エラーが発生した場合、設定ファイルの記述に誤りがあると思われます。
以下は、設定ファイルにエラーがないか確認するコマンドです。

sudo unbound-checkconf

※サービス開始前に上記チェックコマンドを実行しても、正しく動作しませんでした。一度サービス開始コマンドを実行すれば、チェックコマンドも正しく動作しました。

他 当ステップで随時使用するコマンド

  • Unboudの停止
sudo service unbound stop
  • Unboundの再起動
sudo service unbound restart
  • Ubuntu上にインストールされているサービスの状態確認
sudo service --status-ll

OPENSSLをインストールし、自己証明書を作成する

当手順は、Ubuntuでの作業になります。
(参考)
SAN(Subject Alternative Name) のオレオレ証明書 - Qiita
Android端末にインストール可能なDER形式の自己証明書作成 - Qiita

1. Windowsのスタートボタンより、「Ubuntu 20.04LTS」を起動する
2. OpenSSLをインストールする

下記コマンドを実行します。

sudo apt install openssl
3. keyファイルを作成する
openssl genrsa -des3 -out server.key 2048

設定するパスワードを要求されるので入力します。
ここで設定するパスワードは後に必要なので控えておきます。

Enter pass phrase for server.key:
#キーボードで入力しても画面には表示されませんが、入力は受け付けられています。

#再入力を求められるので、再度パスワードを入力します。
Verifing - Enter pass phrase for server.key:
4. CSRファイルを作成する (CSR:キー発行依頼ファイル)
openssl req -new -key server.key -out server.csr

途中に国名、会社名等聞かれます。適当に入力します。
ただし、FQDN名は、設定したいドメイン名で設定する必要があります。
前述のUnboundの設定ファイル(unbound.conf)で設定したドメイン名と同じである必要があります。

5. keyファイルからパスワードを除去する
元のファイルをコピーし、バックアップserver.key.orgを作成します。
cp -p server.key server.key.org

パスワードを除去します。

openssl rsa -in server.key -out server.key
6. SANに設定するFQDNを書く

san.txtを作成します。

sudo touch san.txt

san.txtを編集します。

sudo nano san.txt
san.txt
#example.comの部分は任意に変更する。
subjectAltName = DNS:example.com

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:TRUE
keyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
7. 証明書ファイルを生成する
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt -extfile san.txt

上記コマンドの"-days 365"の部分は、証明書の有効期間と思われます。

8. 確認

下記コマンドを実行し、エラーがないか確認します。

openssl x509 -text -in server.crt -noout
9. DER形式に変換(Android端末にインストールする際に必要)
openssl x509 -in server.crt -out server.der.crt -outform der

上記手順でWSL上に生成したserver.key、server.crt、server.der.crtは、Windowsのエクスプローラより"\\wsl$\Ubuntu-20.04\home\ユーザ名"にアクセスすることで参照可能です。

Node.jsにてhttpsサーバを建てる

当例では、httpsというプロジェクトフォルダを作成し、作業するものとします。
当手順は、Windowsでの作業になります。
プロジェクトフォルダをVisual Studio Code(以下VSCode)で起動します。

1. プロジェクトの初期化

VSCodeのターミナル画面で下記コマンドを実行します。

npm init -y
2. 必要なパッケージのインストール

VSCodeのターミナル画面で下記コマンドを順次実行します。
プロジェクトフォルダにnode_modulesフォルダが作成され、必要なファイルがダウンロードされます。

npm install --save express

npm install --save-dev @types/express
npm install --save-dev typescript
npm install --save-dev ts-loader 
npm install --save-dev webpack
npm install --save-dev webpack-cli
npm install --save-dev webpack-node-externals
3. 各種設定ファイルの作成
- tsconfig.json
  typescriptのトランスパイルの設定ファイルです。
tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true, 
    "noImplicitAny": true, 
    "module": "es2015", 
    "target": "es2017", 
    "jsx": "react", 
    "lib": ["es2018", "dom"], 
    "moduleResolution": "node", 
    "removeComments": true, 
    "strict": true, 
    "noUnusedLocals": false, 
    "noUnusedParameters": false, 
    "noImplicitReturns": true, 
    "noFallthroughCasesInSwitch": true, 
    "strictFunctionTypes": false 
  }
}
  • webpack.config.js

webpackの設定ファイルwebpack.config.jsを作成します。

webpack.config.js
const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  mode: 'development', 
  target: 'node', 
  externals: [ nodeExternals() ], 
  devtool: 'eval-source-map', 
  module: {
    rules: [
      {
        loader: 'ts-loader', 
        test: /\.ts$/, 
        exclude: [/node_modules/], 
        options: { configFile: 'tsconfig.json'}
      }
    ]
  }, 
  resolve: {
    extensions: ['.ts', '.js', '.json']
  }, 
  entry: './src/server.ts', 
  output: {
    filename: 'server.js', 
    path: path.resolve(__dirname, 'dist')
  }, 
  node: {
    __dirname: false
  }
};
  • packckage.jsonにコマンドの登録

package.jsonにコマンドを登録しておきます。

package.json
{
  ...略...
  "scripts": {
    ...
    "start": "node ./dist/server.js", 
    "build": "webpack --config webpack.config.js"
  },
  ...略...
}      
4. コーディング

プロジェクトフォルダにsrcフォルダを作成し、そこにserver.tsファイルを作成し以下のようにコーディングします。

src/server.ts
import * as Express from 'express';
import * as path from 'path';
import * as HTTPS from 'https';
import * as fs from 'fs';

const app = Express();

//スマホからexample.comにアクセスした際、文字列"Hello World"を返します。
app.get('/', (req: Express.Request, res: Express.Response) => {
  return res.send('Hello World');
});

//スマホにサーバ証明書をダウンロードできるように、ルーティングを設定します。
app.get('/download-cert', (req: Express.Request, res: Express.Response) => {
  res.download(path.join(__dirname, 'ssl/server.der.crt'));
});
const portNo = process.env.portNo || 443;

const serverOptions: HTTPS.ServerOptions = {
  key: fs.readFileSync(path.join(__dirname, 'ssl/server.key')),  
  cert: fs.readFileSync(path.join(__dirname, 'ssl/server.crt')), 
};

HTTPS.createServer(serverOptions, app).listen(portNo as number, () => {
  console.log(`Server runging on PortNo:${portNo}`);
}); 

export default app;

VSCodeのターミナル画面で、以下のコマンドを実行し、ビルドします。プロジェクトフォルダにdistフォルダが生成され、server.jsファイルが生成されます。

npm run build
5. server.key、server.crt、server.der.crtの配置

プロジェクトフォルダのdistフォルダに、sslというフォルダを作成し、server.key、server.crt、server.der.crtを配置します。

Androidスマホにサーバ証明書をインストールし、https通信でアクセスする

当手順はAndroidスマホにおける操作手順になります。
私のスマホ KYOCERA TORQUE® G03にて検証しました。
Windows10端末と、Androidスマホが同一wifi上に接続されているものとします。

1. スマホのIPアドレスを控える
  • ホーム画面より"設定"をタップ。Wi-Fiをタップ
    Wi-Fiの設定画面が開きます。

  • 画面右上の設定ボタン(右上の・が縦に3つ並んでいるボタン)をタップし、"詳細設定"をタップ
    "Wi-Fiの詳細設定"画面が起動します。
    画面下部にスクロールすると、割り当てられているIPアドレスが表示されているので控えます。

2. DNSサーバのアドレスを設定する
  • ホーム画面より"設定"をタップ。Wi-Fiをタップ
    Wi-Fiの設定画面が開きます。

  • 一覧より、接続しているWi-Fiを長押しする

    "ネットワークを削除"、"ネットワークを変更"の選択肢が表示されるので"ネットワークを変更"をタップします。

  • "詳細設定項目"を設定する

    • IP設定で"静的"を選択する
    • IPアドレスを設定する

      上記手順で控えたIPアドレスを設定します。

    • DNS1を設定する
      UnboundでDNSサーバを建てたWindows端末のIPアドレスを指定します。

    • DNS2を設定する
      元のDNSサーバのIPアドレスを指定します。

3. サーバ証明書をインストールする
  • chromeを立ち上げ"https://example.com/download-cert"にアクセスする
    この接続ではプライバシーが保護されませんというセキュリティ警告画面が表示されます。
    画面下部の"詳細設定"をタップ、"example.comにアクセスする(安全ではありません)"をタップします。
    インストールできませんでした。証明書ファイルが読み取れませんでしたというメッセージが表示されます。以下の手順に進みます。

  • ホーム画面より"設定"をタップ、設定画面で"セキュリティ"をタップ

  • セキュリティ画面で"ストレージからインストール"をタップ
    一覧の中に、"server.der.crt"があるのでタップします。
    "証明書の名前を指定する"画面が開くので、適当な証明書名を入力し、OKをタップします。

4. chormeからhttps://example.comにアクセスする

警告が表示されず、"Hello World"が表示されれば、成功です。

最後に

長い手順を踏んだ割には最終的にスマホの画面に"Hello World"が表示されるだけですが、これによりLAN内限定のPWAを展開することが可能になります。
余談ですが、当記事、私の初投稿となります。今後も少しずつ自分なりに身についた事柄をまとめて投稿していこうと思います。

参考資料

当記事は下記記事を参考にさせていただきました。
- 【図解】よく分かるデジタル証明書(SSL証明書)の仕組み 〜https通信フロー,発行手順,CSR,自己署名(オレオレ)証明書,ルート証明書,中間証明書の必要性や扱いについて〜 | SEの道標
- 【連載】WSL2、Visual Studio Code、DockerでグッとよくなるWindows開発環境 〜 その1:まずは概要 〜 | SIOS Tech. Lab
- SAN(Subject Alternative Name) のオレオレ証明書 - Qiita
- Android端末にインストール可能なDER形式の自己証明書作成 - Qiita
- Ubuntu Serverで内向きDNSをUnboundを使ってやってみたのでメモ - Qiita

ありがとうございました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2