# 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が見つかるはずなので、クリックして、起動します。 ![image](https://hackmd.io/_uploads/S1f7uGBnC.png) VirtualBoxアプリが起動したらCAをダブルクリックします。 ![image](https://hackmd.io/_uploads/HJHFufr3A.png) すると、起動中であればログが流れていて、起動処理が終わっていれば真っ暗な画面になっているはずです。 マウスで真っ暗な画面をクリックすると、以下のような画面が見えるはずです。 ![image](https://hackmd.io/_uploads/SJZwLfBn0.png) ここで、ユーザ名をクリックすると入力欄が出てくるはずです。 私の手元の環境ではこのまま進むとデスクトップが動かなくなってしまったため、 デスクトップアプリを以下のように変更します。 ![image](https://hackmd.io/_uploads/HyG6lIS20.png) 右下の歯車マークをクリックし、 ![image](https://hackmd.io/_uploads/B1LcW8S2C.png) 「Ubuntu on Xorg」に変更してください。 vagrantユーザはデフォルトでvagrant/vagrantです。 ログインするとwelcomeな画面が表示されますがそのままにしておきます。 ![image](https://hackmd.io/_uploads/HyuRKGHnA.png) ログインできたら画面左側のアイコンからFirefoxを起動します。 ![image](https://hackmd.io/_uploads/Hk8BqPS3A.png) 画面右上の三本線のボタン(ハンバーガーメニュー)から、Settingsをクリックします。 ![image](https://hackmd.io/_uploads/ByfOcGHnR.png) 左側のメニューから、Privacy & Securityをクリックします。 ![image](https://hackmd.io/_uploads/BJ-ocGS2C.png) 真ん中よりは下の方で、Certificatesの項目で、「View Certificates...」をクリックします。 ![image](https://hackmd.io/_uploads/rJIK6LBnC.png) Certificate Managerがポップアップするので、Authoritiesタブをクリックします。次にImport...をクリックします。 ![image](https://hackmd.io/_uploads/ryYVgwBhC.png) vagrantユーザのホームディレクトリにcacert.pemをコピーしておいたはずなので、それを選択します。 ![image](https://hackmd.io/_uploads/SyZWMDr3A.png) 証明書を信頼するか確認されますので、チェック二つ付けてOKをクリックします。 (ここでViewをクリックすれば証明書の内容を確認可能です) ![image](https://hackmd.io/_uploads/BySczvB30.png) 一覧に戻るので、「test.local」がインポートされたことを確認します。 かなり下の方にあるはずです。 ![image](https://hackmd.io/_uploads/HyYEXwH3A.png) 確認できたらOKをクリックし、設定変更を終了します。 #### httpsアクセスを確認する。 vagrantユーザのホームにurl.txtを用意してあるはずなので、それを開いてコピペすると楽です。 以下の3点を試してみましょう。 1. railsアプリへの直接アクセス。プロトコルはhttp。 2. リバースプロキシを経由してのアクセス。プロトコルはhttp。 3. リバースプロキシを経由してのアクセス。プロトコルは==https==。 それぞれ以下のurlとなります。別のタブを開いてそれぞれ見比べてみてください。 ![image](https://hackmd.io/_uploads/SkQl8DB2A.png) ![image](https://hackmd.io/_uploads/BJHfLDH2R.png) CAのubuntuについて日本語対応していないので文字が表示おかしい箇所ありますが、通信はちゃんと暗号化されていることが確認できましたね! ## ****お疲れ様でした`\(^o^)/`**** ## イメージ ![image](https://hackmd.io/_uploads/rJ9JWVybkx.png)