ネットワークの基礎について

#WEBの仕組み
PCはこのように繋がっている。アプリケーション層から指示を受けて別の場所のPCのアプリケーションに連絡する。

<img width="530" alt="スクリーンショット.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510817/63dd91bb-aaaa-12d2-7fc9-014c4af3de52.jpeg">

###物理的ネットワーク
物理的なケーブルやネットワークアダプタなど

###IPアドレス
IPアドレスにはグローバルIPとプライベートIPが存在する。グローバルIPは被ってはいけなく、[DHCP](https://www.cman.jp/network/term/dhcp/)によってルーターに相対的に割り当てられる。ルーターはプライベートIP(ネットワーク部とホスト部で構成されている)を、複数(ネットワーク部は同じで、ホスト部の部分が違うだけ)持っている。そのプライベートIPは近くのデバイスに割り当てられる。参考文献は[ネットワーク部とホスト部](https://www.geolocation.co.jp/learn/ip/02.html)。つまりルーターがないとIPアドレスは得られない。

#####インターネットのアクセスは次のように行われる。

グローバルIPに対するアクセスはルーターのNATやNAPTという技術によってプライベートIP(例えば192.168.2.2)に対するアクセスに変換される。参考文献は[NAT・NAPTとIPアドレス](https://www.geolocation.co.jp/learn/ip/07.html)
↓
プライベートIP(192.168.2.2)にアクセスする。

現状ルーターに接続したデバイスに割り当てられたプライベートIPは
PCは192.168.2.2、スマホは192.168.2.3になっている場合。
↓
PCにアクセスされるようになる。


#####補足
ネットワーク部とホスト部とかはプライベートIPとグローバルIP共通の話。

プライベートIPの場合大規模なネットワーク(つなげるデバイスが多い)ならば、ホスト部の割合が多くないといけなく、小規模ネットワーク(つなげるデバイスが少ない)ならば、ホスト部の割合は少なくて良い。小規模の場合は192.168...で使われることが多い。またプライベートIPはそのネットワーク内(家、会社)のみで使用されるため、プライベートIPは被って良い。どういうことかというと、自分のスマホが家のルーターを通して192.168.2.3というプライベートIPになっていて、会社のルーターを通しても192.168.2.3というプライベートIPになっていても問題ない。なぜなら家のルーターと会社のルーターはそもそもグローバルIDが違うから。参考文献は[IPアドレスの仕組みとは？【図解でわかりやすく5分で解説】](https://www.youtube.com/watch?v=fHG6OqR-Fi8)

グローバルIPの場合は以下の様のネットワーク部とホスト部が確認できる。
参考文献[プロバイダ・ISPが利用しているIP帯(CIDR)の検索手順](https://www.ipvx.info/provider-ip-zone-search/)


#####ネットワーク部とホスト部の分け方

またプライベートIPのネットワーク部:ホスト部の割合のを考えて分ける方法はクラスによって行われる。[IPアドレスの基礎知識](https://qiita.com/mogulla3/items/efb4c9328d82d24d98e6)。小規模ネットワーク(つなげるデバイスが少ない)ならば、ホスト部の割合は少なくて良いので192.168...で使われることが多い。
↓
しかしクラスによる割り当ては無駄が多いため、CIDR (Classless InterDomain Routing) による割り当てが最近導入されている。クラスでしっかりと境界線(桁数)を決めないで、その場に合わせてネットワーク部の桁数、ホスト部の桁数を決める。そして実際にURLとして表示する時は、以下のようにする。参考文献は[CIDR (Classless InterDomain Routing) とは](https://www.geolocation.co.jp/learn/ip/05.html)

```
IPアドレス/ ネットワーク部の桁数
```

DNS
DNSサーバ-によってドメイン名(example.com)とIPアドレス(192....)を変換してくれる。リクエストを送る時には、まずDNSサーバーに行ってドメイン名をIPアドレスに変換する作業をしている。その後リクエストしたいサーバーにアクセスする。

###TCP

TCPにはポートが用意されており、アプリからのどの指示をどのポートから送受信するか決める。他にもポートから発信する時にデータ送信の速度を調整したり、データ受信した時に再送をお願いしたりする。

#####データ送信する時のTCP
データ送信をする時TCPではデータを分割する。その1単位をTCPセグメントと呼ぶ。そのTCPセグメントの頭にTCPヘッドなどいろいろつける。mRNAのポリAキャップみたいな感じ。
↓
データ送信

#####データ受信する時のTCP
TCPセグメントの頭についている物を受け取って、TCP内でTCPセグメントを組み合わせて元のデータの状態にする。
↓
上のアプリ層にお渡しする。

#####なぜ分割するのか
そうしないとネットワークの回線に不平等が生まれる。一人の人間が大量のデータを送信した時、分割せず一気に送った場合、そのネットワークはその人の送信で、手一杯になって他の人が利用できなくなるから。

参考文献は[超わかりやすい！インターネットのしくみ（2/4）～データ編～【音声無し】（パケットやキャッシュなどの考え方を動画で理解できる！）](https://www.youtube.com/watch?v=rY68RRG69N4&t=378s)

###その他WEBの概念

#####HTTPへッダ
HTTPヘッダとはリクエストやレスポンスのデータ(箱)に、どんなデータか示すようなもの(箱にラベルを貼る)。
HTTPヘッダには送った側のIPアドレスやデータ形式を指定したりする。
クライアント側からのリクエストならどんなデータ形式なら受け取れるかを書く。サーバー側からのレスポンスならどんなデータ形式、容量で送ったか示す。
⬇️
header関数を使用することでHTTPヘッダの設定ができる。データ形式ならheader（Contoent-type）で指定する

#AWSでの環境構築(デプロイ準備)
<img width="506" alt="EC2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510817/abf13b61-4654-8bd1-8330-20a819461ae6.jpeg">


以下の順番通りに行う

###VPCの作成
AWSの中でVPCを作成する。やり方はCIDR(ネットワークの大きさがそのくらいになるか)を用いて、VPC(個人のクラウド)の範囲を決める。自分のやりたいことに合わせて、どのくらいの大きさのネットワークにするかを決めるってこと。

###サブネット作成(区間分け)
VPCの中を分割して、インターネットに接続する部分(家のPCって感じ？)やインターネットに繋がらないがその中のネットワークに繋がる部分(家のPCに繋がっているハードな部分って感じ？)を作成する。これをするためにはVPC内での[ネットワーク部とホスト部](https://www.geolocation.co.jp/learn/ip/02.html)を作る必要があるので、それを行う。インターネットに接続する部分のことをパブリックサブネット、プライベートスペースの部分をプライベートサブネットと呼ぶ。VPCの中に部屋を作るってイメージ。あとでこの中に各インスタンス(EC2やRDSなど)を置いていく。

参考文献は[AWS のネットワーク設計入門](https://d1.awsstatic.com/events/jp/2017/summit/slide/D2T3-5.pdf)

###インターネットゲートウェイ作成
ルーター的な存在で、パブリックサブネット(家のPC的存在)と繋がっており、プライベートIPをグローバルIPに変換してくれる。参考文献は[動画で学ぶAWS講座 VPC編 【section3】 インターネットゲートウェイ, EIP, セキュリティグループ, ネットワークACL](https://www.youtube.com/watch?v=OjQSkvjw23c&list=PLtpYHR4V8Mg-hNPfIpCToq3ZLhvXMHFel&index=3)

###ルートテーブル作成
各サブネットが持つべきルールブック。ここにはサブネット間の通信やインターネットゲートウェイへの通信(パブリックサブネットに限る)のルールが記述されている。具体的には、どういう範囲のIPアドレスを指定できるかなど。参考文献は[動画で学ぶAWS講座 VPC編 【section2】 ルートテーブル, プライベートサブネット, パブリックサブネット](https://www.youtube.com/watch?v=lqsiWw-eDzQ&list=PLtpYHR4V8Mg-hNPfIpCToq3ZLhvXMHFel&index=2)と[動画で学ぶAWS講座 VPC編 【section3】 インターネットゲートウェイ, EIP, セキュリティグループ, ネットワークACL](https://www.youtube.com/watch?v=OjQSkvjw23c&list=PLtpYHR4V8Mg-hNPfIpCToq3ZLhvXMHFel&index=3)


###セキュリティーグループの作成
EC2インスタンス単位で設定を行わなければいけない。セキュリティーグループの作成はセキュリティーのルールの作成であり、EC2インスタンス作成時にどのセキュリティーグループを選択するかを決める。

セキュリティーグループで決めることはどのプロトコール(HTTPやSSH)のやりとりを許可して、それをどのポートに限定するかを決める。例えばHTTPプロトコールはポート80でのみ送受信OKにするとか。参考文献は[(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)と[動画で学ぶAWS講座 VPC編 【section3】 インターネットゲートウェイ, EIP, セキュリティグループ, ネットワークACL](https://www.youtube.com/watch?v=OjQSkvjw23c&list=PLtpYHR4V8Mg-hNPfIpCToq3ZLhvXMHFel&index=3)

###RDSインスタンスの作成、配置
RDSとはAWSが提供するDBである。しかしEC2インスタンスにDBシステム(例えばMysQLなど)をインストールして使用する際には作成する必要はない。

RDSを使用する場合はRDSのインスタンスを作成して、任意のサブネットの中に配置させる。参考文献は[(DB・サーバー構築編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/22cfbf4bf7ec95f6ac1c)

###EC2のインスタンス作成、配置
EC2とはクラウド上のサーバー。そのインスタンスを作成し、それをパブリックサブネットに置くことで、インターネットゲートウェイを通して、インターネットアクセスされるようになる。

EC2のインスタンス作成にはAMI選択(EC２のOSwo決める)やどのVPCのどのサブネットに置くか、どのセキュリティーグループを選択するかなどを選びます
↓
最後の選択画面でキーペアを作成するか問われる場面が出る。キーペア(秘密鍵と公開鍵両方)に名前をつけて自分の手元にダウンロードする(再度ダウンロードはできない)。参考文献は[AWSのEC2でインスタンスを作成する手順](https://qiita.com/Quikky/items/2897573a42fd71cfc47f)

おさらいだが公開鍵で暗号化したものは秘密鍵でしか複合できず、秘密鍵で暗号化したもの公開鍵でしか複合できない。秘密鍵は自分だけが所持して、公開鍵はみんなが見れてしまう場所(今回ならインスタンス)に置く。参考文献は[キーペア](https://wa3.i-3-i.info/word17048.html)
↓
アクセスしたい側で公開鍵と秘密鍵を作成し、アクセスされたい方に公開鍵を置く。そうすることでアクセス可能となる。

例としてローカル環境から自分のGitHubにアクセスするために、ローカルで作成した公開鍵をGitHubに登録する。
同様にAWSのインスタンスからGitHubにアクセスするために、AWSのインスタンスで作成した公開鍵をGitHubに登録する。

#####Elastic IPの作成
しかしそれだけではいけない。EC2インスタンスが作成されるとグローバルIPが自動的に振り分けられる。しかしこのグローバルIPはサーバーを再起動させるたびに変わってしまう。そうなるとルートテーブル(ネットーくの設定)などを、再起動するたびに書き換えないといけない。これは大変。
↓
そこでElastic IP(固定されたIP)をグローバルIPも代わりにEC2インスタンスに紐付けることで、再起動してもIPアドレスが変わらないようにする。参考文献は[(DB・サーバー構築編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/22cfbf4bf7ec95f6ac1c)

#AWSへのデプロイ手順1
ここでは実際に作ったアプリをAWSにあげる作業。こちらを参考にさせていただきました。[(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/814e0979217b1a25aa3e)

###ec2-userとしてEC2インスタンスにログイン

インスタンスの起動を確認、インスタンスにパブリックDNSがあるか確認
↓
キーペアをダウンロードしているので、sshで公開鍵認証でec2にログイン。ec2には作成した時点で公開鍵が登録されている状態。公開鍵認証に関して詳しくはこちらを参考にさせていただきました[「よく分かる公開鍵認証」～初心者でもよくわかる！VPSによるWebサーバー運用講座(2)](https://knowledge.sakura.ad.jp/3543/)。要するに接続したい相手のPC側に公開鍵を登録させて、自分のPCに秘密鍵があるならばsshで相手のPC側にアクセスできる。

sshで公開鍵認証でec2にログイン。

```
ssh -i ダウンロードした秘密鍵 ユーザー名(初回はec2-user)@ホスト名(つまりEC2のelasticIP)
```

新しいユーザーを作りたければログイン後自分で作成。root権限もつけたければつける。

###EC2インスタンスでの環境構築
まずyumをインストールして、その後諸々インストール

###gitを使って、GitHubからアプリをクローンする
gitを使用できるようにgitconfigに設定内容を記述
↓
アプリをクローンしてくる場所を作ってあげる。このディレクトリにクローンできるようにしようみたいに。もちろんそのディレクトリの権限は自分がメインで使うユーザーが持つようにする
↓
ルートディレクトリに鍵用のディレクトリ(.ssh)を作成し、そこでssh-keygenで公開鍵、秘密鍵を作成。
↓
GitHubにたいしてアクセスできるようにするために.sshの中にconfigファイルを作りsshによる公開鍵認証を行いやすくする。参考文献は[~/.ssh/configについて](https://qiita.com/passol78/items/2ad123e39efeb1a5286b)。

また前述したが公開鍵認証をするためには自分のPC(今回ならEC2)に秘密鍵があり、相手のPC（今回なら自分のGitHub）に公開鍵がなければいけない。なので自分のGitHubに公開鍵を登録する作業も行う。
↓
GitHubにsshを使ってアクセス
↓
自分の好きな場所にアプリをクローンする

###secret_key_baseの設定(やらなくても良い？)
これは本番環境で必要とされる秘密鍵でcookies整合性確認に使用される。保存方法は環境変数としてSECRET_KEY_BASEに保存する方法とcredentials.yml.encに保存する方法がある。基本的にcredentials.yml.encに保存するのが良い。もし環境変数SECRET_KEY_BASEが存在し、credentials.yml.encの中にもecret_key_baseが設定されていれば、環境変数SECRET_KEY_BASEの方が優先される。

#####credentials.yml.encについて
本番環境にアプリを置くということは外部にアプリを置くということである。しかし外部には公開したくない秘密情報をアプリに記述したい場合がある。その時はconfig/credential.yml.encに記述してやる。config/credential.yml.encは暗号化されている。この内容をアプリ内で使用する際はcinfig/master.keyによって復号され使用される。
また開発者が記述した秘密情報を新たにcredential.yml.encに追加したい場合も、master.keyによって暗号化されcredential.yml.encに反映される。

しかしmaster_keyはgitigoreに登録されているため、githubに共有できない。githubから本番環境にcloneしてもそこにはmaster_keyはない状態。通常credential.yml.encに紐づくmaster_keyはrails newした時にできる。だから開発環境で使用していたmaster_keyをコピペして使用するやり方がある。

また無理やりcredential.yml.encに編集を加えようとすると勝手にmaster_keyができるがそれは使えないらしい。そこでcredential.yml.encに大事な情報がなければ一度今のcredential.yml.encを削除して新たに

```
EDITOR=vim rails credentials:edit
```

をうつとcredential.yml.encとそれに紐づいたmaster_keyが作成される

[Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage](https://qiita.com/scivola/items/cc06ddbfd94d3118f693)

参考文献は[[Rails]credentials.yml.encについてまとめる](https://qiita.com/yamamoto_shuji/items/5afd9ffe13f36ff29677)
[Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)
[
【Rails5.2】秘匿情報はsecret.ymlではなくcredentials.yml.encで管理する【初心者】](https://qiita.com/15grmr/items/a687d0ed211ef60e751c)

実際に自分でなんとかした事例
[master failed to start, check stderr log for detailsを解決したい](https://teratail.com/questions/249527?reply=true)

#AWSへのデプロイ手順2
アプリはEC2のインスタンスのアプリケーションサーバーの中に置く。またEC2のインスタンスの中にWEBサーバーも置く。

EC2のインスタンスのアクセスはまずWEBサーバーに渡される。
↓
WEBサーバーに解決できなければ、アプリケーションサーバーにアクセスさせる。
↓
そのアクセスはアプリケーションサーバーによって翻訳されてアプリに伝えられる。前提としてアプリケーションサーバーとアプリの言語は違う。
↓
アプリがアクセスを読み取りレスポンスを返す。


WEBサーバとアプリケーションサーバーの大きな違いは、WEBサーバは静的な処理(HTML、CSS、JS)を返し、動的な処理が必要になればアプリケーションサーバーにアクセスを渡す。なぜそうなったかというと、分けた方が新たに改修しよう(サーバーの機能を変えるとか)とした時にWEBサーバとアプリケーションサーバーが一緒になっていると変更するのが大変という面+パフォーマンス面で処理が遅くなる。参考文献は[アプリケーションサーバってなに？Webサーバとの違い](https://www.marketingbank.jp/special/cat02/173.php)

アプリケーションサーバーの作成(Unicorn)
↓
WEBサーバーの作成（Nginx）
↓
データベースの設定(MySQLとか)
↓
Nginxの起動でデプロイ完成。