# v3.5 構築手順:インフラ
## 前提
- 2024年時点でのwindowsへの構築手順。
- インターネット接続速度、ダウンロードやインストールで時間がそこそこかかる。
## 構築手順
### windows updateを実行する。
powershellまたはGUIで、OSに対して更新プログラムを適用する。
https://atmarkit.itmedia.co.jp/ait/articles/2405/24/news030.html
### chocolateyでWindowsにアプリを幾つかインストールする。
公式サイトに従いchocolatey自体をインストールする。
オプションのユーザ登録は不要。
管理者権限PowerShellでワンライナー実行のはず。
https://chocolatey.org/install
chocolatey自体のインストールが終わったら、以下のコマンドで幾つかアプリをインストールする。
```powershell
choco install -y googlechrome vscode virtualbox vagrant cmder
```
### virtualbox上のubuntuでDNS、リバースプロキシ、CAを構築する。
#### 大まかな流れ
1. vagrant設定
2. DNS構築
3. RP構築
4. 「v3.5 構築手順:アプリ」に従ってアプリをwsl上に構築
5. netsh interface portproxy addを利用してhttpアクセス確認
6. CA構築
7. httpsアクセス確認
:::success
:bulb: 証明書、CAなどセキュリティに関する体系的な理解は以下の書籍などを確認してみてください。
**暗号技術入門**
https://cr.hyuki.net/
証明書に関する章が一連の流れ、攻撃の可能性、対策の必要性を説明してくれています。
色々な人が要約をブログなどにまとめていたりもします。
http://www.spiritek.co.jp/spkblog/2017/01/26/%E6%9A%97%E5%8F%B7%E6%8A%80%E8%A1%93%E5%85%A5%E9%96%8010-%E8%A8%BC%E6%98%8E%E6%9B%B8/
:::
#### vagrant設定
cmderを起動して以下を実行する。
```
mkdir moneta_infra
cd moneta_infra
vagrant box add bento/ubuntu-24.04 https://app.vagrantup.com/bento/boxes/ubuntu-24.04/versions/202404.26.0/providers/virtualbox/amd64/vagrant.box
vagrant box list
vagrant init
code Vagrantfile
```
Vagrantfileを以下の内容に更新する。
```ruby
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "bento/ubuntu-24.04"
config.vm.provider "virtualbox" do |vb|
# VBoxManage modifyvmの設定
# リモートディスプレイ/サーバーon off
vb.customize ["modifyvm", :id, "--vrde", "off"]
end
config.vm.define :ubuntu2404DNS do | ubuntu2404 |
ubuntu2404.vm.hostname = "ubuntu2404DNS"
ubuntu2404.vm.network :private_network, ip: "192.168.31.1", virtualbox__intnet: "intnet1"
end
config.vm.define :ubuntu2404RP do | ubuntu2404 |
ubuntu2404.vm.hostname = "ubuntu2404RP"
ubuntu2404.vm.network :private_network, ip: "192.168.31.2", virtualbox__intnet: "intnet1"
end
config.vm.define :ubuntu2404CA do | ubuntu2404 |
ubuntu2404.vm.hostname = "ubuntu2404CA"
ubuntu2404.vm.network :private_network, ip: "192.168.31.3", virtualbox__intnet: "intnet1"
end
end
```
cmderで以下のコマンドを実行し、3台の仮想マシンを自動設定、起動する。
```
vagrant up
```
:::success
:bulb: vagrantコマンドはVagrantfileのあるディレクトリで機能します。
もしcmderを新しく立ち上げた場合などは、ディレクトリを移動してからコマンド実行してください。このページの手順とおりなら以下になるはずです。
```
cd C:\tools\Cmder\moneta_infra
```
:::
:::success
:bulb: vagrant upがタイムアウトしたり、何らかのエラーとなることは良くあります。メッセージを確認して、VirtualBoxアプリも確認しつつ、タイムアウトであればリトライなど、対処していきましょう。
SSH auth method: private key
で止まることは多い気がします。そのメッセージになったら、VirtualBoxアプリから対象サーバをダブルクリックし、コンソール画面を出してみてください。処理が流れていれば内部的には進んでいると言えます。
:::
#### DNSサーバを構築する。
cmderでDNSサーバにssh接続します。
```
vagrant ssh ubuntu2404DNS
```
以下をサーバに対して実行します。
```
sudo apt update
sudo apt install bind9 -y
named -v
systemctl status named
cd /etc/bind/
sudo touch named.conf.external-zones
sudo vi named.conf.external-zones
```
以下の内容で更新する。
```
zone "test.local." IN {
type master;
file "/etc/bind/test.local";
allow-update { none; };
};
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo cp -p named.conf named.conf_bk
sudo vi named.conf
```
最終行に以下を追記する。
```
include "/etc/bind/named.conf.external-zones";
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo cp -p named.conf.options named.conf.options_bk
sudo vi named.conf.options
```
以下の内容で更新する。
```
acl public-subnet {
192.168.31.0/24;
};
options {
directory "/var/cache/bind";
recursion yes;
forwarders {
8.8.8.8;
8.8.4.4;
};
forward only;
allow-query {
localhost;
public-subnet;
};
dnssec-validation auto;
listen-on-v6 { none; };
};
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo cp -p db.local test.local
sudo vi test.local
```
以下の内容で更新する。
「192.168.1.1」の箇所は、Windows側のIPを記載してください。コマンドプロンプトでipconfigなどで確認して置き換えてください。
```
;
; BIND data file for Nginx Server Reverse Proxy DNS Setting
;
$TTL 86400
$ORIGIN test.local.
@ IN SOA ubuntu2404DNS.test.local. ubuntu2404DNS.test.local. (
2024083103 ; Serial
3600 ; Refresh
1800 ; Retry
1209600 ; Expire
86400 ) ; Negative Cache TTL
;
IN NS ubuntu2404DNS.test.local.
IN A 192.168.31.1 ; BIND9 DNS Server IP
;
ubuntu2404DNS.test.local. IN A 192.168.31.1 ; BIND9 DNS Server IP
ubuntu2404RP.test.local. IN A 192.168.31.2 ; Nginx ReverceProxy IP
ubuntu2404CA.test.local. IN A 192.168.31.3 ; openssl CA IP
monetasv.test.local. IN A 192.168.1.1 ; moneta sv IP
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo chown root:bind *.*
named-checkconf
sudo systemctl restart named
sudo systemctl status named
sudo sed -i "s/nameserver 127.0.0.53/nameserver 192.168.31.1/g" /etc/resolv.conf
nslookup ubuntu2404DNS.test.local
nslookup ubuntu2404RP.test.local
nslookup google.com
host ubuntu2404DNS.test.local
host ubuntu2404RP.test.local
host google.com
```
DNS作業は以上です。
#### リバースプロキシサーバを構築する。
cmderでRPサーバにssh接続します。
```
vagrant ssh ubuntu2404RP
```
以下をサーバに対して実行します。
```
sudo apt update
sudo apt install openssl -y
sudo apt install nginx -y
sudo systemctl status nginx
openssl version
sudo systemctl enable nginx
curl localhost
sudo vi /etc/nginx/conf.d/server.conf
```
以下の内容で更新する。
proxy_passはWindows端末のIPであり、コマンドプロンプトでipconfigなどで確認して置き換えてください。ポート番号の3001はnetshの設定で後ほど指定します。
```
server{
listen 3000;
server_name 192.168.31.2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://192.168.1.1:3001/;
}
}
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo systemctl restart nginx
sudo systemctl status nginx
sudo sed -i "s/nameserver 127.0.0.53/nameserver 192.168.31.1/g" /etc/resolv.conf
sudo cp -p /etc/nginx/conf.d/server.conf /etc/nginx/conf.d/dns_server.conf
sudo vi /etc/nginx/conf.d/dns_server.conf
```
以下の内容で更新する。
```
server{
listen 3000;
server_name ubuntu2404RP.test.local;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://monetasv.test.local:3001/;
}
}
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo systemctl restart nginx
sudo systemctl status nginx
```
一旦リバースプロキシ作業は以上です。後ほど証明書関係のやり取りが発生します。
#### アプリの動作環境を構築する。
以下の手順を実施して、railsアプリ側を構築しましょう。
https://hackmd.io/@kubo4ka/B1-WvNvjR
アプリの構築手順では http://127.0.0.1:3000 でrailsアプリがlistenします。今回は他の端末からアクセスできるようにIPを指定してサーバを起動しなおしましょう。
また、DNSを利用した攻撃の対策機能がある為、今回は許可設定も追加します。
先ずWindowsターミナルでrailsアプリを起動しているウインドウを開き、Ctrl+Cでrailsアプリを停止します。
次にwsl上のubuntuのIPを確認します。
```
ip a | grep "inet "
```
inet 127.0.0.1/8 scope host lo
という、ループバックアドレスではない方のIPでrailsサーバを起動し直します。
手元の環境では以下でした。
inet 172.20.239.35/20 brd 172.20.239.255 scope global eth0
ただ、サーバ起動前にDNS許可設定をしておきましょう。以下のファイルの最終行のendの上に2行追記します。
/home/moneta/project/rails/moneta3.5/config/environments/development.rb
```
config.hosts << "ubuntu2404rp.test.local"
config.hosts << "monetasv.test.local"
```
ではrailsアプリを起動しましょう。
```
rails s -b 172.20.239.35
```
次に、netsh interface portproxy addを利用してvirtualbox上のDNSなどのubuntuから、wsl上のrailsアプリにアクセスできるように設定を行います。
Windowsキー+Rで「ファイル名を指定して実行」を起動し、
powershellと入力し、
Ctrl+Shiftを押しながらエンターを押して、管理者権限でpowershellを起動します。
念の為WindowsからIPがどう見えているか以下で確認します。
```
wsl -e hostname -I
```
以下のコマンドで設定を追加します。
```
netsh interface portproxy add v4tov4 listenaddress=* listenport=3001 connectaddress=172.20.239.35 connectport=3000
```
待ち受けポートを3001とし、この設定で変換が行われていることを確認しやすくしておきます。
railsアプリの作業は以上です。
:::success
:bulb: 今回の検証が終わったら、portproxyの設定は消しておきましょう。
```
netsh interface portproxy show all
netsh interface portproxy delete v4tov4 listenaddres=* listenport=3001
netsh interface portproxy show all
```
:::
#### CAサーバを構築する。
cmderでCAサーバにssh接続します。
```
vagrant ssh ubuntu2404CA
```
CA作業では途中でインタラクティブにパスワードや組織の情報を入力するタイミングがあります。パスワードや「test.local」といったドメイン名を一致させる以外は任意となります。
また、証明書関係の作業は、証明してほしい人、証明してあげる人、という、複数の登場人物が現れます。作業があっちこっち移動しますので、作業対象を指差し確認しましょう。
- 証明してほしい人 : リバースプロキシ
- 証明してあげる人 : CA
以下をCAサーバに対して実行します。
```
sudo sed -i "s/nameserver 127.0.0.53/nameserver 192.168.31.1/g" /etc/resolv.conf
nslookup ubuntu2404DNS.test.local
sudo apt update
sudo apt install openssl -y
openssl version
sudo mkdir -p /etc/ssl/CA/certs
sudo mkdir -p /etc/ssl/CA/private
sudo mkdir -p /etc/ssl/CA/crl
sudo mkdir -p /etc/ssl/CA/newcerts
sudo chmod 700 /etc/ssl/CA/private
echo "01" | sudo tee /etc/ssl/CA/serial
sudo touch /etc/ssl/CA/index.txt
sudo cp -p /etc/ssl/openssl.cnf /etc/ssl/CA/
sudo vi /etc/ssl/CA/openssl.cnf
```
以下の行番号の箇所を更新する。viでは「:set nu」としてエンターすると便利です。
```
82 dir = /etc/ssl/CA # Where everything is kept
86 unique_subject = no # Set to 'no' to allow creation of
105 copy_extensions = copy
112 default_days = 3650 # how long to certify for
255 keyUsage = critical, digitalSignature, cRLSign, keyCertSign
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
cd /etc/ssl/CA/
sudo openssl req -config /etc/ssl/CA/openssl.cnf -new -keyout /etc/ssl/CA/private/cakey.pem -out /etc/ssl/CA/careq.pem
sudo openssl ca -config /etc/ssl/CA/openssl.cnf -create_serial -out /etc/ssl/CA/cacert.pem -days 3650 -batch -keyfile /etc/ssl/CA/private/cakey.pem -selfsign -extensions v3_ca -infiles /etc/ssl/CA/careq.pem
```
==ここで、作業対象サーバをリバースプロキシに変更します。==
今の画面についてexitするか、cmderであればCtrl+Tで新しいタブを追加することが可能です。新しいタブを開いた場合はcdを忘れないようにしましょう。リバースプロキシは証明してほしい側でしたね。
cmderでRPサーバにssh接続します。
```
vagrant ssh ubuntu2404RP
```
以下をRPサーバに対して実行します。
```
cd
sudo openssl genrsa -out ./server.key 2048
sudo touch san.cnf
sudo vi san.cnf
```
以下の内容で更新する。
```
[ req ]
default_bits = 2048
encrypt_key = no
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
countryName = JP
stateOrProvinceName = Tokyo
localityName = Shinjuku
organizationName = test.local
commonName = *.test.local
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
subjectKeyIdentifier = hash
subjectAltName = @alt_names
[alt_names]
DNS.1 = test.local
DNS.2 = *.test.local
```
viを「:wq」などで保存して終了し、以下を継続実施する。
scpに関して、vagrantユーザはデフォルトでvagrant/vagrantです。
```
sudo openssl req -new -config san.cnf -key server.key -out server.csr
scp server.csr vagrant@ubuntu2404CA.test.local:/home/vagrant/
```
一旦リバースプロキシ作業は終わります。
==CAの作業に戻ります。==
```
cd
sudo openssl ca -config /etc/ssl/CA/openssl.cnf -policy policy_anything -out server.crt -infiles server.csr
scp server.crt vagrant@ubuntu2404RP.test.local:/home/vagrant/
cp /etc/ssl/CA/cacert.pem .
vi url.txt
```
以下の内容で更新する。
```
http://monetasv.test.local:3001/
http://ubuntu2404RP.test.local:3000/
https://ubuntu2404RP.test.local:443/
```
:::success
:bulb: 例えば以下のような実行結果になっていると思います。
```
vagrant@ubuntu2404CA:~$ sudo openssl ca -config /etc/ssl/CA/openssl.cnf -policy policy_anything -out server.crt -infiles server.csr
Using configuration from /etc/ssl/CA/openssl.cnf
Enter pass phrase for /etc/ssl/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 2 (0x2)
Validity
Not Before: Sep 3 14:19:23 2024 GMT
Not After : Sep 1 14:19:23 2034 GMT
Subject:
countryName = JP
stateOrProvinceName = Tokyo
localityName = Shinjuku
organizationName = test.local
commonName = *.test.local
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
38:98:E0:BD:0B:43:99:36:20:F9:30:E3:6C:EE:F5:2E:96:C5:B0:D8
X509v3 Authority Key Identifier:
70:19:6D:D5:CA:C4:32:5A:69:65:25:F2:E1:9A:9E:FC:29:4A:72:1A
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:test.local, DNS:*.test.local
Certificate is to be certified until Sep 1 14:19:23 2034 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
Database updated
vagrant@ubuntu2404CA:~$
```
:::
CA作業は以上です。
サーバ側作業の最後となる、==リバースプロキシ作業に移ります。==
```
cd
sudo chown root:root server.crt
sudo mkdir -p /etc/nginx/ssl
sudo cp -p server.crt /etc/nginx/ssl/
sudo cp -p server.key /etc/nginx/ssl/
sudo touch /etc/nginx/ssl/passwd
sudo vi /etc/nginx/ssl/passwd
```
以下の内容で更新する。#証明書のパスワードと一致すれば任意です。
```
moneta
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo chmod 600 /etc/nginx/ssl/passwd
sudo cp -p /etc/nginx/conf.d/dns_server.conf /etc/nginx/conf.d/dns_https.conf
sudo vi /etc/nginx/conf.d/dns_https.conf
```
以下の内容で更新する。
```
server{
listen 443 ssl;
server_name *.test.local;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_password_file /etc/nginx/ssl/passwd;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
location / {
proxy_pass http://monetasv.test.local:3001/;
}
}
```
viを「:wq」などで保存して終了し、以下を継続実施する。
```
sudo systemctl restart nginx
sudo systemctl status nginx
curl http://monetasv.test.local:3001/
curl http://ubuntu2404RP.test.local:3000/
curl https://ubuntu2404RP.test.local:443/
curl -k https://ubuntu2404RP.test.local:443/
```
リバースプロキシ作業は以上です。
#### クライアントPC役を構築する。
以上でサーバ側の作業は終わりました。今度は動作確認をしていきましょう。
クライアントPCを新たに仮想マシン用意しても良いのですが、リソースが勿体ないので、証明書発行して役目の終わったCAをクライアント役として利用します。
cmderでCAにssh接続します。
```
vagrant ssh ubuntu2404CA
```
以下のコマンドを実行して、ubuntuにデスクトップ環境を追加します。
かなり時間がかかるので放置しておきます。
```
sudo apt install ubuntu-desktop -y
```
完了後、以下のコマンドでOSをリブートします。
```
sudo reboot
```
起動したら、cmderでvagrant sshし、DNS設定を行っておきます。
```
sudo sed -i "s/nameserver 127.0.0.53/nameserver 192.168.31.1/g" /etc/resolv.conf
```
今度はGUIで操作をするので、Windows上でVirtualBoxアプリを起動します。
Windowsキーを押して「oracle」辺りまで打てば以下のようにVirtualBoxが見つかるはずなので、クリックして、起動します。

VirtualBoxアプリが起動したらCAをダブルクリックします。

すると、起動中であればログが流れていて、起動処理が終わっていれば真っ暗な画面になっているはずです。
マウスで真っ暗な画面をクリックすると、以下のような画面が見えるはずです。

ここで、ユーザ名をクリックすると入力欄が出てくるはずです。
私の手元の環境ではこのまま進むとデスクトップが動かなくなってしまったため、
デスクトップアプリを以下のように変更します。

右下の歯車マークをクリックし、

「Ubuntu on Xorg」に変更してください。
vagrantユーザはデフォルトでvagrant/vagrantです。
ログインするとwelcomeな画面が表示されますがそのままにしておきます。

ログインできたら画面左側のアイコンからFirefoxを起動します。

画面右上の三本線のボタン(ハンバーガーメニュー)から、Settingsをクリックします。

左側のメニューから、Privacy & Securityをクリックします。

真ん中よりは下の方で、Certificatesの項目で、「View Certificates...」をクリックします。

Certificate Managerがポップアップするので、Authoritiesタブをクリックします。次にImport...をクリックします。

vagrantユーザのホームディレクトリにcacert.pemをコピーしておいたはずなので、それを選択します。

証明書を信頼するか確認されますので、チェック二つ付けてOKをクリックします。
(ここでViewをクリックすれば証明書の内容を確認可能です)

一覧に戻るので、「test.local」がインポートされたことを確認します。
かなり下の方にあるはずです。

確認できたらOKをクリックし、設定変更を終了します。
#### httpsアクセスを確認する。
vagrantユーザのホームにurl.txtを用意してあるはずなので、それを開いてコピペすると楽です。
以下の3点を試してみましょう。
1. railsアプリへの直接アクセス。プロトコルはhttp。
2. リバースプロキシを経由してのアクセス。プロトコルはhttp。
3. リバースプロキシを経由してのアクセス。プロトコルは==https==。
それぞれ以下のurlとなります。別のタブを開いてそれぞれ見比べてみてください。


CAのubuntuについて日本語対応していないので文字が表示おかしい箇所ありますが、通信はちゃんと暗号化されていることが確認できましたね!
## ****お疲れ様でした`\(^o^)/`****
## イメージ
