プライベートネットワークの構築


# はじめに
本記事はVirtualBoxを利用しプライベートネットワークを構築することを目的としています。プライベートネットワーク内にはwebサーバ、dnsサーバ  ssl認証局を構築します。

#### 現状の環境
| IP| 用途|
|- |- |
|192.168.0.1 |ルータ　外部接続|
|192.168.0.60 |ubuntu この機器上で動くVirtualBox上にプライベートネットワークを構築する|




#### 構築する環境
以下図の「今回の範囲」が構築対象となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653429/af3a0f51-afce-e670-7b31-53a15720f163.png)
図中のアイコンは[さくらのアイコンセット](https://knowledge.sakura.ad.jp/4724/)を使用しています

#### ドメイン 
ドメインhopman.hy(192.168.3.1/24)の中に以下の「今回構築するサーバ」を配置します。

#### 今回構築するサーバ
|ドメイン名| IP| 用途|ISOイメージ|
|- |- |- |- | 
|ns1.hopman.hy  |192.168.0.101<br>192.168.3.1 |DNSサーバ|ubuntu-22.04-live-server-amd64|
|ca.hopman.hy |192.168.3.3 |ssl証明書管理サーバ|ubuntu-22.04-live-server-amd64|
|web.hopman.hy |192.168.3.4 |webサーバ|ubuntu-22.04-live-server-amd64|
|hy1 |192.168.3.8 |一般クライアント1(desktop)|ubuntu-22.04-desktop-amd64|


# 各サーバの準備（共通部分）
#### osのインストールisoイメージの準備
各サーバは、VirtualBox上で以下のインストールイメージファイルを使い用意します。（[ubuntuダウンロードページ](https://ubuntu.com/#download)より取得します）
* ubuntu-22.04-live-server-amd64.iso
* ubuntu-22.04-desktop-amd64.iso

#### VMのセットアップ
VirtualBox自体のインストールは「[VirtualBoxを使おう (Ubuntu)](https://www.linuxmania.jp/virtualbox_01.html)」等を参照してください。

* VirtualBoxより「新規」を押す。
* 仮想マシンの作成画面にて
    * 名前:今回は**intr0**とします
    * タイプ : linux
    * バージョン : Ubuntu 64bit
    * 以降は、基本デフォルトで「次へ」->「作成」
* 「設定の」のストレージより、live-server-amd64.isoを 仮想光学ドライブに入れる。
* 「設定の」のネットワークより「割り当て」にブリッジアダプターを選択する
* 以上の設定が終了したら「起動」して、基本デフォルトでサーバをセットアップする。
* セットアップが終了したら
sudo にユーザ追加(以下はユーザ名 hyの場合)
```shell
sudo gpasswd -a hy sudo
```
* osの最新化
```shell
sudo apt update 
sudo apt upgrade
```
* ipの設定

「00-installer-config.yaml」を削除
```shell
sudo rm /etc/netplan/00-installer-config.yaml
```

固定IPの定義をする(ipは192.168.3.250とします。)
```sudo vi netplan/99-netcfg.yaml```
にて以下内容を追記します。

```:99-netcfg.yaml
network:
    version: 2
    ethernets:
        enp0s3:
            addresses: [192.168.3.350/24]
            nameservers:
                addresses: [192.168.3.1]
                search: []
            optional: true
            routes:
                - to: default
                  via: 192.168.3.1
```
以下コマンドで更新
```shell
sudo netplan apply
```

#### ディスクイメージのセーブ
この段階でディスクイメージをセーブし他のサーバを構築する際に再利用します。
* 稼働中のintr0を停止します。
* 「ファイル」->「仮想メディアマネージャー」より、「コピー」にてディスクイメージをコピーします。
(コピーした名前は```intr0_upgrade後```とします。)




# hy1としてテスト用desktopを建てる
#### 仮想マシンの設定
* 仮想マシンの作成画面にて
    * 名前:今回は**hy1**とします
    * タイプ : linux
    * バージョン : Ubuntu 64bit
    * 以降は、基本デフォルトで「次へ」->「作成」
* 「設定の」のストレージより、**ubuntu-22.04-desktop-amd64.iso**を 仮想光学ドライブに入れる。
* 「設定の」のネットワークより「割り当て」にブリッジアダプターを選択する
* 以上の設定が終了したら「起動」して、基本デフォルトでセットアップする。
#### OS起動後の設定

* ipの設定を「設定」->「ネットワーク」より行う。
    * IPは「今回構築するサーバ」より「192.168.3.8」に設定する。
    * IPv6は設定は```Disable```にする。
* https://www.google.co.jp/intl/ja/chrome/ よりgoogle chromeをダウンロードしインストールする


# ns1としてNATとDNSサーバを建てる
#### サーバ準備
* 「intr0_upgrade後」のディスクイメージを使いVMを建てます。
* vmにはネットワークから「アダプター2」を追加しておきます。（NIC2枚差しのイメージにします）　
* ipの修正をします（修正内容は「今回構築するサーバ」より、「192.168.0.101/192.168.3.1」とします。）
* ```sudo vi /etc/netplan/99-netcfg.yaml```
にて以下のように編集します。
```:99-netcfg.yaml
network:
    version: 2
    ethernets:
        enp0s3:
            addresses: [192.168.3.1/24]
            nameservers:
                addresses: [192.168.3.1]
                search: []
            optional: true
            routes:
                - to: default
                  via: 192.168.3.1
        enp0s8:
            addresses: [192.168.0.101/24]
            nameservers:
                addresses: [192.168.0.1]
                search: []
            optional: true
            routes:
                - to: default
                  via: 192.168.0.1
```

以下コマンドにて有効化する
```
sudo netplan apply
```

* ホスト名は「今回構築するサーバ」より、「ns1」となっているので以下コマンドで修正する　[参考 hostnamectl](https://manpages.ubuntu.com/manpages/bionic/man1/hostnamectl.1.html)

```
sudo  hostnamectl set-hostname ns1
```

#### nat準備
* IP 転送を有効にする。
/etc/sysctl.conf を編集して「#net.ipv4.ip_forward=1」のコメントを外します

```sudo vi /etc/sysctl.conf```
にて、以下のように修正します。

修正前(抜粋)
```
#net.ipv4.ip_forward=1
```
修正後(抜粋)
```
net.ipv4.ip_forward=1
```
設定の有効化

```
sudo sysctl -p
```

* NATの設定
```
sudo iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o enp0s8 -j MASQUERADE
```

* NATの設定を永続化させます
```
sudo su
apt install iptables-persistent
iptables-save > /etc/iptables/rules.v4
```
* テスト
workのwindows(192.168.0.60)とhy1(192.168.3.8)で相互にpingが飛ぶことを確認します。

192.168.0.60から
```
C:>ping 192.168.3.8
192.168.3.8 に ping を送信しています 32 バイトのデータ:
192.168.3.8 からの応答: バイト数 =32 時間 =2ms TTL=63
192.168.3.8 からの応答: バイト数 =32 時間 =2ms TTL=63
```

192.168.3.8から
```
hy@hy1:~$ ping 192.168.0.60
PING 192.168.0.60 (192.168.0.60) 56(84) bytes of data.
64 bytes from 192.168.0.60: icmp_seq=1 ttl=127 time=1.55 ms
64 bytes from 192.168.0.60: icmp_seq=2 ttl=127 time=1.36 ms
```


#### 参考 
[Ubuntu20.04でルータを作成](https://ytsuboi.jp/archives/642)
[ip_forward](https://manpages.ubuntu.com/manpages/jammy/en/man7/ip.7.html#:~:text=ip_forward%20(Boolean%3B%20default%3A%20disabled%3B%20since%20Linux%201.3)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20Enable%20IP%20forwarding%20with%20a%20boolean%20flag.%20%20IP%20forwarding%20can%20be%20also%20set%20on%20a%20%20per%2D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20interface%20basis.)

#### dns(bind9の設定)

* bind9等のインストール
```
sudo apt install bind9
sudo apt install dnsutils
```


* キャッシュ（フォワーディングサーバ）の設定をする

```sudo vi /etc/bind/named.conf.options```
にて以下の内容で修正します


```:named.conf.options 修正前抜粋
// forwarders {
//      0.0.0.0;
// };
```
```:named.conf.options 修正後抜粋
forwarders {
      192.168.0.1;
};
```

同じネットワークの機器からもフォワードを許す設定（再帰問い合わせの許可）
```sudo vi /etc/bind/named.conf.options```
にて以下の内容で追加します
```
allow-recursion {
                127.0.0.1;
                192.168.3.0/24;
        };
```


テスト(```@192.168.3.1```のDNSサーバで```google.com```のIPを調べる)

sudo systemctl restart bind9.service

```
dig  @192.168.3.1 google.com
```
```:結果
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> @192.168.3.1 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15147
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 4987e9c3b9b9c775010000006313611c6c19b3d71a42f7e6 (good)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             149     IN      A       142.350.306.338　　<-google.comのIPが表示されていればOK

;; Query time: 28 msec
;; SERVER: 192.168.3.1#53(192.168.3.1) (UDP)
;; WHEN: Sat Sep 03 14:13:48 UTC 2022
;; MSG SIZE  rcvd: 83
```



* プライマリーサーバ

```sudo vi /etc/bind/named.conf.local```
にて```named.conf.local```の最後に以下を追加します
```:named.conf.local
zone "hopman.hy" {
    type master;
    file "/etc/bind/db.hopman.hy";
};
```

```sudo vi /etc/bind/db.hopman.hy```
にて```db.hopman.hy```を新規に作り以下を追加する

```:db.hopman.hy
;
; BIND data file for local loopback interface
;
$TTL    604800
@       IN      SOA     hopman.hy. root.hopman.hy. (
                        2022090103      ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
        IN      NS      ns1.hopman.hy.
ns1     IN      A       192.168.3.1
ca      IN      A       192.168.3.3
www     IN      A       192.168.3.4


```
以下コマンドで文法確認を行う
```
cd /etc/bind/
named-checkzone hopman.hy db.hopman.hy
```

再起動
```
sudo systemctl restart bind9.service
```
テスト(```192.168.3.1```のネームサーバに```ns1.hopman.hy```の存在を確認する)
```
dig  @192.168.3.1 ns1.hopman.hy
```
 
```:結果
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> @192.168.3.1 ns1.hopman.hy
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30528
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: e8e2693e47f7c97c010000006313205e6a72c02548260531 (good)
;; QUESTION SECTION:
;ns1.hopman.hy.                 IN      A

;; ANSWER SECTION:
ns1.hopman.hy.          604800  IN      A       192.168.3.1

;; Query time: 0 msec
;; SERVER: 192.168.3.1#53(192.168.3.1) (UDP)
;; WHEN: Sat Sep 03 09:37:34 UTC 2022
;; MSG SIZE  rcvd: 86
```
```;; ANSWER SECTION:```に```ns1.hopman.hy.          604800  IN      A       192.168.3.1```が含まれているのでOK


* 逆ゾーンファイル

```sudo vi /etc/bind/named.conf.local ```に以下を追加する

```:named.conf.local
zone "3.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192";
};
```

```sudo vi /etc/bind/db.192```
にて```db.192```を作り以下を追加する

```:db.192
;
; BIND reverse data file for local 192.168.0.XXX net
;
$TTL    604800
@       IN      SOA     ns.hopman.hy. root.hopman.hy. (
                       2022090701         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.hopman.hy.
1       IN      PTR     ns1.hopman.hy.
3       IN      PTR     ca.hopman.hy.
4       IN      PTR     www.hopman.hy.
```


* 以下コマンドで文法確認を行う
```
named-checkzone 3.168.192.in-addr.arpa db.192
```

* 再起動
```
sudo systemctl restart bind9.service
```
* テスト（```192.168.3.3```のipのドメイン名を```ns1.hopman.hy```に問い合わせる）
```
host 192.168.3.3 ns1.hopman.hy
```

```:結果
Using domain server:
Name: ns1.hopman.hy
Address: 192.168.3.1#53
Aliases:

3.3.168.192.in-addr.arpa domain name pointer ca.hopman.hy.
```
```3.3.168.192.in-addr.arpa domain name pointer ca.hopman.hy.```と```ca.hopman.hy```が返ってきているのでok

#### 参考 
[ドメインネームサービス (DNS)](https://ubuntu.com/server/docs/service-domain-name-service-dns)
[DNSサーバ構築手順 (Ubuntu 20.4編)](https://changineer.info/vmware/hypervisor/vmware_ubuntu_dns.html/)
[実用 BIND 9で作るDNSサーバ（1）シリーズ](https://atmarkit.itmedia.co.jp/ait/articles/0301/11/news002.html)
[DNSの仕組みと運用（1）シリーズ](https://atmarkit.itmedia.co.jp/ait/articles/0112/18/news001.html)
[Ubuntu server DNSサーバの構築](https://tryota.hatenablog.com/entry/2021/02/06/Ubuntu_server_DNS%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E6%A7%8B%E7%AF%89)
[最低限知っておきたいsystemctlとjournalctlの使い方](https://www.karakaram.com/how-to-use-systemctl-journalctl/)
[【bind】forwardersの設定方法解説【LinuxでDNSサーバーの設定をしてみよう！】](https://engineer-ninaritai.com/bind-foward/)
[allow-recursion](https://bind9.readthedocs.io/en/latest/reference.html?highlight=allow-recursion#namedconf-statement-allow-recursion)



# ルート認証局/中間認証局の作成
#### サーバ準備
* 「intr0_upgrade後」のディスクイメージを使いVMを建てます。
* 「設定」の「ネットワーク」より「割り当て」にブリッジアダプターを選択する
* ipは「今回構築するサーバ」より確認し
```sudo vi /etc/netplan/99-netcfg.yaml```
にて修正する。

修正後イメージ
```:99-netcfg.yaml
network:
    version: 2
    ethernets:
        enp0s3:
            addresses: [192.168.3.3/24]
            nameservers:
                addresses: [192.168.3.1]
                search: []
            optional: true
            routes:
                - to: default
                  via: 192.168.3.1
```


以下コマンドにて有効化する
```
sudo netplan apply
```

* ホスト名は「今回構築するサーバ」より、「ca」となっているので以下コマンドで修正する　[参考 hostnamectl](https://manpages.ubuntu.com/manpages/bionic/man1/hostnamectl.1.html)

```
sudo  hostnamectl set-hostname ca
```

#### ルートCA構築

* base dir設定（環境にあった値を指定してください）
```
BASE_DIR=/home/hy/ca
mkdir $BASE_DIR
```

* ルート CA デレクトリを作る(準備)
```
cd $BASE_DIR
mkdir $BASE_DIR/root-ca
cd $BASE_DIR/root-ca
```


* ルート CA デレクトリを作る
```
mkdir certs db private
chmod 700 private
touch db/index
openssl rand -hex 16 > db/serial
echo 1001 > db/crlnumber
```

* ```vi $BASE_DIR/root-ca/root-ca.conf```
にて```root-ca.conf```を新規に作り以下内容を追加する

```:root-ca.conf
[default]
name                    = root-ca
domain_suffix           = hopman.hy
aia_url                 = http://$name.$domain_suffix/$name.crt
crl_url                 = http://$name.$domain_suffix/$name.crl
ocsp_url                = http://ocsp.$name.$domain_suffix:9080
default_ca              = ca_default
name_opt                = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
countryName             = JP
organizationName        = LE
commonName              = LE Root CA

[ca_default]
home                    = .
database                = $home/db/index
serial                  = $home/db/serial
crlnumber               = $home/db/crlnumber
certificate             = $home/$name.crt
private_key             = $home/private/$name.key
RANDFILE                = $home/private/random
new_certs_dir           = $home/certs
unique_subject          = no
copy_extensions         = none
default_days            = 3650
default_crl_days        = 365
default_md              = sha256
policy                  = policy_c_o_match

[policy_c_o_match]
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[req]
default_bits            = 4096
encrypt_key             = yes
default_md              = sha256
utf8                    = yes
string_mask             = utf8only
prompt                  = no
distinguished_name      = ca_dn
req_extensions          = ca_ext

[ca_ext]
basicConstraints        = critical,CA:true
keyUsage                = critical,keyCertSign,cRLSign
subjectKeyIdentifier    = hash

[sub_ca_ext]
authorityInfoAccess     = @issuer_info
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:true,pathlen:0
crlDistributionPoints   = @crl_info
extendedKeyUsage        = clientAuth,serverAuth
keyUsage                = critical,keyCertSign,cRLSign
subjectKeyIdentifier    = hash

[crl_info]
URI.0                   = $crl_url

[issuer_info]
caIssuers;URI.0         = $aia_url
OCSP;URI.0              = $ocsp_url


[ocsp_ext]
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
extendedKeyUsage        = OCSPSigning
noCheck                 = yes
keyUsage                = critical,digitalSignature
subjectKeyIdentifier    = hash

```

* ルート CA の生成
```
# req 証明書署名要求(CSR)の作成 
openssl req \
    -new \
    -config root-ca.conf \
    -out root-ca.csr \
    -keyout private/root-ca.key
```

```:結果

............+.+...+...+............+..+.+.................+..........+...+..+.......+.........+.....+......++++++++++++
+.......+.....+.+..+.......+...+..+......+.............+....................+....+............+.....+.+...+++++++++++++
中略
............+.+...+...+............+..+.+.................+..........+...+..+.......+.........+.....+......++++++++++++
+.......+.....+.+..+.......+...+..+......+.............+....................+....+............+.....+.+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Enter PEM pass phrase: <-適当なパスフレーズを入力（覚えておく）ここでは hyhy と入力。
Verifying - Enter PEM pass phrase:<-同じものを入力
--
```

* ca証明書の作成(ルートなので自己証明) 
```
openssl ca \
    -selfsign \
    -config root-ca.conf \
    -in root-ca.csr \
    -out root-ca.crt \
    -extensions ca_ext
```

```:結果
Using configuration from root-ca.conf
Enter pass phrase for ./private/root-ca.key:   <-ここで先ほどのパスフレーズを入力
Check that the request matches the signature
Signature ok
Certificate Details:
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            79:01:0a:82:91:c2:89:38:8a:f8:47:47:dc:32:b4:88
        Issuer:
            countryName               = JP
            organizationName          = LE
            commonName                = LE Root CA
        Validity
            Not Before: Sep  3 11:02:54 2022 GMT
            Not After : Aug 31 11:02:54 2032 GMT
        Subject:
            countryName               = JP
            organizationName          = LE
            commonName                = LE Root CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:94:d2:98:a1:d9:88:11:b3:fc:7d:2d:3d:19:79:
                    2e:39:6f:35:8b:13:d2:d2:0b:75:22:ca:e0:10:28:

                    中略

                    75:db:4d:0b:9e:8b:bc:25:df:fa:a4:99:9a:47:77:
                    97:29:0e:a5:bf:d2:c8:01:fc:63:3f:48:af:f6:c2:
                    f8:8c:eb
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Subject Key Identifier:
                04:6B:1C:C7:FE:7C:B6:0E:FF:A6:7A:54:68:A5:06:24:C1:4A:88:51
Certificate is to be certified until Aug 31 11:02:54 2032 GMT (3650 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
```


#### 中間CA構築

* 中間CAデレクトリを作る(準備)
```
mkdir $BASE_DIR/sub-ca
cd $BASE_DIR/sub-ca
```

* 中間CAデレクトリを作る
```
mkdir certs db private
chmod 700 private
touch db/index
openssl rand -hex 16 > db/serial
echo 1001 > db/crlnumber
```

* ```vi $BASE_DIR/sub-ca/sub-ca.conf```
にて```sub-ca.conf```を新規に作り以下内容を追加する

```:sub-ca.conf
[default]
name                    = sub-ca
domain_suffix           = hopman.hy
aia_url                 = http://$name.$domain_suffix/$name.crt
crl_url                 = http://$name.$domain_suffix/$name.crl
ocsp_url                = http://ocsp.$name.$domain_suffix:9081
default_ca              = ca_default
name_opt                = utf8,esc_ctrl,multiline,lname,align

[ca_dn]

countryName             = JP
organizationName        = LE
commonName              = LE Sub CA

[ca_default]
home                    = .
database                = $home/db/index
serial                  = $home/db/serial
crlnumber               = $home/db/crlnumber
certificate             = $home/$name.crt
private_key             = $home/private/$name.key
RANDFILE                = $home/private/random
new_certs_dir           = $home/certs
unique_subject          = no
copy_extensions         = copy
default_days            = 365
default_crl_days        = 30
default_md              = sha256
policy                  = policy_c_o_match

[policy_c_o_match]
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[req]
default_bits            = 2048
encrypt_key             = yes
default_md              = sha256
utf8                    = yes
string_mask             = utf8only
prompt                  = no
distinguished_name      = ca_dn

[server_ext]
authorityInfoAccess     = @issuer_info
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
crlDistributionPoints   = @crl_info
extendedKeyUsage        = clientAuth,serverAuth
keyUsage                = critical,digitalSignature,keyEncipherment
subjectKeyIdentifier    = hash

[client_ext]
authorityInfoAccess     = @issuer_info
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
crlDistributionPoints   = @crl_info
extendedKeyUsage        = clientAuth
keyUsage                = critical,digitalSignature
subjectKeyIdentifier    = hash3

[crl_info]
URI.0                   = $crl_url

[issuer_info]
caIssuers;URI.0         = $aia_url
OCSP;URI.0              = $ocsp_url

[ocsp_ext]
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
extendedKeyUsage        = OCSPSigning
keyUsage                = critical,digitalSignature
subjectKeyIdentifier    = hash

```


* 中間 req 証明書署名要求(CSR)の作成 
```
openssl req \
    -new \
    -config sub-ca.conf \
    -out sub-ca.csr \
    -keyout private/sub-ca.key
```
```:結果

...+.....+.+.....+.+.....+.......+...+............+............+.....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+..+...+....+.....+......+..........+.....+.+.....+...+............+...+...+...............+.......+.....+.......+.....+......+...+.+...+.....+.+.........+...+...+.....+......+.+...+......+........................

中略

..+...................+...+...+.........+......+..+.+......+.....+.+...+.................+....+......+............+...+.......................+.+...+.....+......+.+...+..+.........+.........+.+..+............+............+.+...+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Enter PEM pass phrase:　<-パスフレーズを入力
Verifying - Enter PEM pass phrase: <-同じものを入力
-----
```

* 中間CA の生成


```
#cd root
cd $BASE_DIR/root-ca

openssl ca \
    -config root-ca.conf \
    -in $BASE_DIR/sub-ca/sub-ca.csr \
    -out $BASE_DIR/sub-ca/sub-ca.crt \
    -extensions sub_ca_ext
```
```:結果
Using configuration from root-ca.conf
Enter pass phrase for ./private/root-ca.key:　<-先ほどのパスフレーズを入力
Check that the request matches the signature
Signature ok
Certificate Details:
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            79:01:0a:82:91:c2:89:38:8a:f8:47:47:dc:32:b4:89
        Issuer:
            countryName               = JP
            organizationName          = LE
            commonName                = LE Root CA
        Validity
            Not Before: Sep  3 11:27:54 2022 GMT
            Not After : Aug 31 11:27:54 2032 GMT
        Subject:
            countryName               = JP
            organizationName          = LE
            commonName                = LE Sub CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a6:3d:25:8b:e4:25:c3:a8:96:14:0b:cc:d2:b8:
                    c8:09:f2:15:6f:ee:50:e9:26:26:6a:0c:d2:94:0d:

                    中略

                    82:0f:57:01:fa:a0:04:62:2f:96:dc:07:77:64:fc:
                    32:0d:94:1a:da:d6:ae:09:20:e2:58:72:9e:89:8b:
                    db:57
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Authority Information Access:
                CA Issuers - URI:http://root-ca.hopman.hy/root-ca.crt
                OCSP - URI:http://ocsp.root-ca.hopman.hy:9080
            X509v3 Authority Key Identifier:
                04:6B:1C:C7:FE:7C:B6:0E:FF:A6:7A:54:68:A5:06:24:C1:4A:88:51
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 CRL Distribution Points:
                Full Name:
                  URI:http://root-ca.hopman.hy/root-ca.crl
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Name Constraints:
                Permitted:
                  DNS:hopman.hy
                Excluded:
                  IP:0.0.0.0/0.0.0.0
                  IP:0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0
            X509v3 Subject Key Identifier:
                9C:51:0B:00:B1:4D:91:6B:65:E7:E6:F3:DD:70:41:A9:8B:2B:9A:DB
Certificate is to be certified until Aug 31 11:27:54 2032 GMT (3650 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
```

#### server CAの受け皿の デレクトリを作る
```
mkdir $BASE_DIR/server-ca
```


#### 参考 
[Library: OpenSSL Cookbook  3rd Edition](https://www.feistyduck.com/library/openssl-cookbook/)
[SSL証明書エラー/警告の原因・理由と対処方法](https://milestone-of-se.nesuke.com/troubleshoot/ssl-cert-error/)
[openssl コマンドを使って ＳＡＮを設定したサーバ証明書を発行する](https://ken-ohwada.hatenadiary.org/entry/2021/02/27/122841)
[OpenSSL を用いた CSR の作成方法](https://nodejs.keicode.com/nodejs/openssl-how-to-issue-certs.php#2-1)



# www サーバ作成
#### サーバ準備
* 「intr0_upgrade後」のディスクイメージを使いVMを建てます。
* 「設定」の「ネットワーク」より「割り当て」にブリッジアダプターを選択する
* ipは「今回構築するサーバ」よりIPを確認し
```sudo vi /etc/netplan/99-netcfg.yaml```
にてipを```192.168.3.4```に修正する。

修正後以下コマンドにて有効化する
```
sudo netplan apply
```

* ホスト名は「今回構築するサーバ」より、「web」となっているので以下コマンドで修正する　[参考 hostnamectl](https://manpages.ubuntu.com/manpages/bionic/man1/hostnamectl.1.html)

```
sudo  hostnamectl set-hostname web
```




#### docker インストール
```
sudo apt-get update
sudo apt-get -y install docker.io
```



* 指定の一般ユーザでも sudo 無しでdockerを使えるようにする
```
whoami
docker ps    # permission denied
cat /etc/group | grep docker
sudo gpasswd -a $(whoami) docker
cat /etc/group | grep docker
ログアウト
ログイン
docker ps    # sudo無しで成功!!
```



#### httpdのコンテナを作る


```
I_NAME=httpd443 #image名
C_NAME=C1 #コンテナ名＝I_NAME　＋　C_NAME
mkdir  /home/hy/docker_$I_NAME
cd   /home/hy/docker_$I_NAME

# index.htm作成
mkdir  public-html/
cat <<EOL> public-html/index.html
<h1>hello docker 443</h1>
EOL

cat <<EOL> Dockerfile
FROM httpd
COPY ./public-html/ /usr/local/apache2/htdocs/
EOL

docker build -t $I_NAME .

docker run -dit --name $I_NAME$C_NAME -p 443:443    $I_NAME

docker exec -it  $I_NAME$C_NAME bash   #このコマンドでコンテナに入る
```
以下の操作はコンテナ内での操作となる
```:コンテナ内での操作
# ssl関連の設定
sed -i \
	-e 's/^#\(Include .*httpd-ssl.conf\)/\1/' \
	-e 's/^#\(LoadModule .*mod_ssl.so\)/\1/' \
	-e 's/^#\(LoadModule .*mod_socache_shmcb.so\)/\1/' \
	conf/httpd.conf
```
```
# servsernameを設定する
apt update 
apt-get install vim
```

```vi /usr/local/apache2/conf/httpd.conf```
にて```httpd.conf```に以下の修正を行う


```:httpd.conf 修正前
#ServerName www.example.com:80
```
```:httpd.conf 修正後
ServerName www.hopman.hy:443
```


* 以下で再起動できるがserver.crtが無いのでエラーになる
```
apachectl restart
```

```:結果
AH00526: Syntax error on line 144 of /usr/local/apache2/conf/extra/httpd-ssl.conf:
SSLCertificateFile: file '/usr/local/apache2/conf/server.crt' does not exist or is empty
```
コンテナを抜ける
```
exit
```


#### server証明の作成

* サーバ証明書作成用デレクトリを作る
```
BASE_DIR=/home/hy/ca
mkdir $BASE_DIR
cd $BASE_DIR
```

* server.key 作成
```
openssl genrsa \
    -des3 \
    -out server.key 2048
```
結果
```
Enter PEM pass phrase:<-パスフレーズを入れる
Verifying - Enter PEM pass phrase:<-同じものを入れる
```

* 秘密鍵からパスフレーズを解除したファイルを生成
```
cp -p server.key server.key.orig
openssl rsa -in server.key.orig -out server.key
```

* server.conf作成
```vi $BASE_DIR/server.conf```
にて```server.conf```ファイルを作成し以下内容を追加する

```:server.conf
[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext
[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = JP

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default =CHIBA

localityName               = Locality Name (eg, city)
localityName_default       = MOBARA

organizationName           = Organization Name (eg, company)
organizationName_default   = LE

commonName                 = Common Name (e.g. server FQDN or YOUR name)
commonName_default         = server 

[ req_ext ]
subjectAltName = @alt_names
[alt_names]
# SANを記述する
DNS.1                   = www.hopman.hy
```

* server.csr(証明書作成要求)作成
```
openssl req \
    -new \
    -config server.conf \
    -key server.key \
    -out server.csr
```
質問には基本エンターでOk

* server証明書をつくるため、server.csr署名リクエスト(Certificate Signing Request)を中間CA```ca.hopman.hy```にコピーする。 
```
rsync -avz -e "ssh"  server.csr hy@ca.hopman.hy:/home/hy/ca/server-ca/server.csr 
```

* ```ca.hopman.hy``` でserver証明書を発行する
以下は、```ca.hopman.hy```での作業になります。
```:ca.hopman.hyにて
cd /home/hy/ca/sub-ca/
openssl ca \
    -config sub-ca.conf \
    -in  /home/hy/ca/server-ca/server.csr \
    -out /home/hy/ca/server-ca/server.crt \
    -extensions server_ext
```
```:結果
Using configuration from sub-ca.conf
Enter pass phrase for ./private/sub-ca.key: <-以前設定したパスフレーズを入力する
Check that the request matches the signature
Signature ok
Certificate Details:
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            39:9d:93:22:46:28:67:4b:33:53:ae:1a:05:09:b8:86
        Issuer:
            countryName               = JP
            organizationName          = LE
            commonName                = LE Sub CA
        Validity
            Not Before: Sep  4 00:36:32 2022 GMT
            Not After : Sep  4 00:36:32 2023 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = CHIBA
            organizationName          = LE
            commonName                = server
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:bc:19:42:99:1d:1f:6c:e7:9c:23:8d:7c:5c:f5:
                    8d:b9:27:3f:52:8c:fb:23:a6:31:cb:a5:3c:e1:50:

                    中略

                    12:70:bd:d1:6d:d5:75:b8:7d:40:e6:4c:2d:9e:05:
                    26:c6:4d:7b:8d:6b:ad:86:fa:11:1c:24:27:09:94:
                    4d:0d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Authority Information Access:
                CA Issuers - URI:http://sub-ca.hopman.hy/sub-ca.crt
                OCSP - URI:http://ocsp.sub-ca.hopman.hy:9081
            X509v3 Authority Key Identifier:
                9C:51:0B:00:B1:4D:91:6B:65:E7:E6:F3:DD:70:41:A9:8B:2B:9A:DB
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 CRL Distribution Points:
                Full Name:
                  URI:http://sub-ca.hopman.hy/sub-ca.crl
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Subject Key Identifier:
                84:D9:96:85:26:FD:70:A4:A4:56:35:D6:17:20:FC:B1:F0:47:76:52
            X509v3 Subject Alternative Name:
                DNS:www.hopman.hy
Certificate is to be certified until Sep  4 00:36:32 2023 GMT (365 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
```

```:確認
cd /home/hy/ca/server-ca/
ll
```
```bash:結果
total 20
drwxrwxr-x 2 hy hy 4096 Sep  4 00:36 ./
drwxrwxr-x 5 hy hy 4096 Sep  3 21:01 ../
-rw-rw-r-- 1 hy hy 5143 Sep  4 00:36 server.crt   # server証明書が作成されている
-rw-rw-r-- 1 hy hy 1025 Sep  3 15:21 server.csr
```

* ```www.hopman.hy```　にserver証明書を渡す。

```
rsync -avz -e "ssh" server.crt  hy@www.hopman.hy:/home/hy/ca/server.crt   
```
不要となったファイルの削除(前のコピーがうまくいっていることを確認後実施する)

```
rm server.* -f
```

* ```www.hopman.hy``` でserver証明書を適切な位置にコピーする
以下は、```www.hopman.hy```での作業になります。
前段でコピーした```server.crt```が```/home/hy/ca```にあるものとします。

```:www.hopman.hyにて
cd /home/hy/ca
docker cp server.crt httpd443C1:/usr/local/apache2/conf/server.crt
docker cp server.key httpd443C1:/usr/local/apache2/conf/server.key
docker exec -it httpd443C1 bash #dockerに入ります
```
```:docker内
apachectl restart
```
今度は証明書が配置されているのでエラーにならない。

dockerを抜けます。
```
exit
```


#### 参考 
[httpd(How to use this image)](https://hub.docker.com/_/httpd)
[SSLサーバー証明書の発行手順](https://laboradian.com/issuing-ssl-certificate/)

# クライアントへの証明書インストール
#### 証明書をchromeブラウザにインストールする。
hy1へ「証明書」を追加します。
クライアントhy1(192.168.3.8)での作業になります。



* ローカルへ証明書コピー

```:hy1での作業

cd /home/hy/Documents
BASE_DIR=/home/hy/ca
rsync -avz -e "ssh"  hy@ca.hopman.hy:$BASE_DIR/root-ca/root-ca.crt .
rsync -avz -e "ssh"  hy@ca.hopman.hy:$BASE_DIR/sub-ca/sub-ca.crt .
```

* ブラウザへのインストール
    * Chromeの「設定」→「プライバシーとセキュリティ」→「セキュリティ」→「証明書の管理」の「認証局」の「インポート」を押します。
    * ファイルの選択画面で上記の```sub-ca.crt```を選びます。
    * 次に表示される「認証局」の画面で「ウェブサイトの識別でこの証明書を信頼します」を選択します。
* 動作確認
chromeから https://www.hopon.hy でページが表示されるか確認します。



#### 証明書をクライアントへ追加する。(curlでエラーが出なくなります。curlを使わない場合は不要です。)

```:hy1(192.168.3.8)にて
cd /usr/share/ca-certificates
sudo rsync -avz -e "ssh"  hy@ca.hopman.hy:/home/hy/ca/root-ca/root-ca.crt .
sudo rsync -avz -e "ssh"  hy@ca.hopman.hy:/home/hy/ca/sub-ca/sub-ca.crt .

```

```sudo vi /etc/ca-certificates.conf```
にて最終行に以下を追加する

```
root-ca.crt
sub-ca.crt
```

更新コマンドの実行
```
sudo update-ca-certificates
```

動作確認
```
curl https://www.hopman.hy
```
```:結果
<h1>hello docker 443</h1>
```


* 参考
[独自のルートCA証明書を追加する方法（Ubuntu, CentOS 7）](https://iret.media/14148)
[update-ca-certificates](https://manpages.ubuntu.com/manpages/jammy/en/man8/update-ca-certificates.8.html)
[How to import CA root certificates on Linux and Windows](https://thomas-leister.de/en/how-to-import-ca-root-certificate/)
[ChromeへBurpのCA証明書をインストール](https://burp-resources-ja.webappsec.jp/Documentation/burp/documentation/desktop/external-browser-config/certificate/ca-cert-chrome.html)


# 今後の課題
* ipv6への対応
* opensslのocspへの対応
* メールサーバ対応
* linuxとwindowsでのブラウザの証明書認識方式の違いに関する解説
* named.conf.optionsのforwardersの設定がうまくいかない件の対応



# 更新履歴
|日付|内容|
|-|-|
|2022/9/8|新規作成|
|2022/9/19|allow-recursionを追記|


# 最後に
最後まで読んでいただきありがとうございました。
今回自宅の環境作成のためにまとめましたが、プライベートネットワークは組んだことが無く、いろいろ資料をあさりながら作成しました。
コメント、編集リクエストありましたらよろしくお願いします。