vagrantでプロキシサーバを使用したい

VagrantのゲストOSにProxy設定を行うには、vagrant-proxyconfを使う。plug-inのインストールが必要

$ vagrant plugin install vagrant-proxyconf
$ vagrant plugin list
vagrant-proxyconf (2.0.10, global)
vagrant-vbguest (0.20.0, global)

### focalfossa
vagrantのubuntu/focal64を使いたいと思う
$ vagrant init ubuntu/focal64

公開プロキシのサイトを検索します

とりあえず、最初なので日本のプロキシサーバを使う
http
43.248.24.158 51166
https
133.167.65.45 8080

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"
  config.vm.network "private_network", ip: "192.168.33.10"

  if Vagrant.has_plugin?("vagrant-vbguest")
      config.vbguest.auto_update = false  
  end

  if Vagrant.has_plugin?("vagrant-proxyconf")
    config.proxy.http = "http://43.248.24.158:51166/"
    config.proxy.https = "http://133.167.65.45:8080/"
    config.proxy.no_proxy = "localhost,127.0.0.1,192.168.33.10"
  end
end

$ vagrant up

$ printenv http_proxy https_proxy
http://43.248.24.158:51166/
http://133.167.65.45:8080/

なるほど、proxyについて完全に理解した🔥

プロキシサーバーとは

プロキシサーバとは、内部ネットワークとインターネットの境界で動作し、両者間のアクセスを代理するもの
キャッシュ機能がある
– キャッシュ、ユーザー認証、フィルタリング、ウィルス対策、匿名性確保

### プロキシサーバのメリット
– プロキシ上にログが残る
– プロキシサーバを経由すると、端末のIPが相手に残らない

### 注意点
– 公開プロキシは個人情報を抜き取るものもあるため、個人情報を扱う場合は、公開プロキシは使用しない

リバースプロキシとは、外部インターネットからサーバーへアクセスされる通信を中継する仕組み

なるほど、仕組みは理解したが、使ってみないとわからんな。

[kernel]ネットワーク(TCP/IP)

IP:16.42.0.9

ネットワークアドレス:16.42
ホストアドレス:0.9

サブネットアドレス:16.42.0
ホストアドレス:9

IPアドレスはネットワーク管理者によって割り当てられる
16.42.0と16.42.1というようにサブネットを変える

IPアドレスはIPパケットに含まれている
送信元、送信先のIPはIPヘッダに含まれる
同一のIPサブネットのホスト間では直接IPパケットを送信できるが、それ以外はゲートウェイに送信

TCPはパケットの送受信のためにIPを使用する
IPアドレスだけでなく、アプリケーションのポート番号も指定しなければならない

### linuxのnetwork
Network Application: user
Socket Interface: BSD Socket, INET Sockets
Protocol Layer: TCP, UDP IP
Network Devices: PPP, SLIP, Ethernet

TCPパケットは番号付けされているので、送信されたデータが正しく受信されたか確認する

### BSD Socket Interface
UNIX, INET, AX25(アマチュア無線)、IPX、APPLETALK, X25
Soket type: Stream, Datagram, Raw, Reliable Delivered Messages, Sequenced Packets, Packet

### INET Sockets
インターネットアドレスファミリーをサポート
システムコールで新規ソケットを作成する際は、アドレスファミリ、ソケットタイプ、プロトコルに関する識別子を渡す

INET BSD ソケット上でコネクションを確立
ふたつのアプリケーション間で仮想サーキットを構築する
TCP セグメントには、コネクション情報、開始セグメントのシーケンス番号(sequence number)、接続を開始したホスト側が処理できるセグメントの最大サイズ(maximum segment size, MSS)、送信および受信の際のウィンドウサイズ(window size)、等が含まれる

待機(listen)状態のソケット上のaccept操作ルーチンは、その socket データ構造体から、新規のsocketデータ 構造体を複製

### IP層
socket buffer:ソケットバッファもしくは sk_buff を使用してプロトコル間やネットワークデバイスとの間でデータを受け渡し
head, data, tail, end
sk_buff: push, pull, put, trim

[C言語]ICMP

ICMPとはInternet Control Message Protocol
Internet Protocolのデータグラム処理における誤りの通知や通信に関する情報の通知などのために使用される

#include <stdio.h>

#include <sys/socket.h> // Internet Protocol family
#include <netinet/in.h> // Internet Protocol family

#include <netinet/ip.h>  // IPヘッダ構造体
#include <netinet/ip_icmp.h> // ICMPヘッダ

unsigned short checksum(unsigned short *buf, int bufsz){

	unsigned long sum = 0;

	while(bufsz > 1){
		sum += *buf;
		buf++;
		bufsz -= 2;
	}

	if(bufsz == 1){
		sum += *(unsigned char *)buf;
	}

	sum = (sum & 0xffff) + (sum >> 16);
	sum = (sum & 0xffff) + (sum >> 16);

	return ~sum;
}

int main(int argc, char** argv[]){

	int sock;
	struct icmphdr hdr;
	struct sockaddr_in addr;
	int n;

	char buf[2000];
	struct icmphdr *icmphdrptr;
	struct iphdr *iphdrptr;

	if(argc != 2){
		printf("usage : %s IPADDR\n", argv[0]);
		return 1;
	}

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(argv[1]);

	sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	if(sock < 0){
		perror("socket");
		return 1;
	}

	memset(&hdr, 0, sizeof(hdr));

	hdr.type = ICMP_ECHO;
	hdr.code = 0;
	hdr.checksum = 0;
	hdr.un.echo.id = 0;
	hdr.un.echo.sequence = 0;

	hdr.checksum = chechsum((unsigned short *)&hdr, sizeof(hdr));

	n = sendto(sock, (char *)&hdr, sizeof(hdr), 0, (struct sockaddr *)&addr, sizeof(addr));
	if (n < 1){
		perror("sendto");
	}

	memset(buf, 0, sizeof(buf));

	n = recv(sock, buf, sizeof(buf), 0);
	if(n < 1){
		perror("recv");
	}

	iphdrptr = (struct iphdr *) buf;

	icmphdrptr = (struct icmphdr *)(buf + (iphdrptr->ihl * 4));

	if(icmphdrptr->type == ICMP_ECHOREPLY){
		printf("received ICMP ECHO REPLY\n");
	} else {
		printf("received ICMP %d\n", icmphdrptr->type);
	}

	close(sock);
	

	return 0;

}

[C言語]UDP

UDPはデータが宛先に届いたかどうかを関知しない為、到着を保証しない
複数の相手に同時にデータを送信できる、TCPは1対1のユニキャストのみ
TCPよりリアルタイム性が高い
用途は映像、音楽のストリーミング、Voice Over IPなど

### UDP受信
– ソケットを作る
– bindするIPアドレスとポートを設定
– ソケットに名前をつける
– データを受け取る

#include <stdio.h>
#include <sys/types.h> // typedef シンボルおよび構造体のコレクション
#include <sys/socket.h> // Internet Protocol family
#include <netinet/in.h> // Internet Protocol family

int main(int argc, char** argv){

	int sock;
	struct sockaddr_in addr; // sockaddr_inはIPアドレスやポート番号を保持する為の構造体

	char buf[2048];

	sock = socket(AF_INET, SOCK_DGRAM, 0); // ソケットの作成

	addr.sin_family = AF_INET; // アドレスファミリ
	addr.sin_port = htons(12345); // ポート番号、 htonsはネットワークバイトオーダに変換
	addr.sin_addr.s_addr = INADDR_ANY; // IPアドレス

	bind(sock, (struct sockaddr *)&addr, sizeof(addr)); // sockはソケットとアドレスの結合

	memset(buf, 0, sizeof(buf)); // バイトメモリブロックのセット
	recv(sock, buf, sizeof(buf), 0); // ソケットからメッセージを受け取る

	printf("%s\n", buf);

	close(sock);

	return 0;

}

### UDP送信
– ソケットを作る
– 宛先を指定して送信

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(){
	
	int sock;
	struct sockaddr_in addr;

	sock = socket(AF_INET, SOCK_DGRAM, 0);

	addr.sin_family = AF_INET;
	addr.sin_port = htons(12345);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));

	close(sock);

	return 0;
}

TCP/IPはデータを切れ目のないストリームとして扱う、ストリームのイメージは固定された通信路
一方、UDPはデータグラム(塊)として扱う

TCPとUDPについてわかってきました。

5G周波数割り当てとソケット通信の仕組み

– 5Gでは低い周波数(VHF帯)から高い周波数(ミリ波帯)の複数の周波数帯を組み合わせて利用し、場所、時間、アプリケーションなどにより最適な使い方を採用
– 10Gbps + 高速移動対応
– 電波(Hz=1秒間の振動数)とは電磁波。電波を使って通信を行う場合、変調という操作を行い、伝達したい情報を載せる

27.00GHz 〜 27.40GHz 楽天
27.40GHz 〜 27.80GHz NTTドコモ
27.80GHz 〜 28.20GHz au
29.10GHz 〜 29.50GHz ソフトバンク
※4GではドコモにはLowにあたる3,480MHz~3,520MHz、KDDIには3,520MHz~3,560MHz、ソフトバンクは3,560MHz~3,600MHz

周波数帯(バンド)は機種によって事なる
高い周波数帯の電波は回り込みにくいため、屋内やビル街で繋がりにくい可能性がある

1.周波数利用効率のさらなる向上
L Non-Orthogonal Multiple Access:電力ドメインを使って複数ユーザーの信号を重畳することで、さらなるスループットを向上させる
L Massive MIMO: 100以上のアンテナ素子を使い指向性の高いアクティブアンテナを用いて、ビームフォーミングによる干渉回避と、多数のユーザーの同時接続を可能にするMIMO技術であり、20GHz帯など、高い周波数と相性がよく、容量不足の解消につなげる

2. ネットワークの高密度化
L HetNet (Heterogeneous Network):セル半径の異なるシステムを同一エリア内に混在させ、これらを協調して動作させ、ネットワーク全体のキャパシティを大幅に改善する技術
L デュアルコネクティビティ(C/U分離): 端末と基地局は、接続を制御する「C-plane」(制御信号)と、実際のデータが流れる「U-plane」(ユーザーデータ信号)の2つの信号を送受している。広範囲をカバーするマクロセルでC-Planeを、速度を稼ぎやすいスモールセルでU-planeを別々に通信する「C/U分離」方式により、ネットワークを高密度化

パケット制御技術を使っている。パケット通信では、1本の回線で同時に複数の通信が可能(回線交換方式は回線を占有してしまう)
1パケットは128バイト
Packet Assembly and Disassemblyとはパケットの組立/分解装置の事
データはTCPヘッダ、IPヘッダと共に送信される
通信データはOSのTCP処理で行う

TCP/IP階層: プロトコル
アプリケーション層: HTTP, SMTP, POP, FTP
トランスポート層: TCP, UDP
インターネット層: IP
ネットワークインターフェイス層: イーサネット、無線LAN, PPP…

IPアドレスとはネットワークアドレスとホストアドレスに別れる
16.42.0.9で、16.42をネットワークアドレス、0.9をホストアドレス(サブネットとホストアドレスに分割できる)とする
IPアドレスの変換は/etc/hostsで行うか、DNSサーバで変換
IPパケットはgatewayに送信される

Ethernet Frame(イーサネット規格に従って通信する時のデータ): Destination Ethernet address, Source ethernet address, Protocol, Data, Checksum
IP Packet: Length, Protocol, Checksum, Source IP address, Destination IP address, Data
TCP Packet: Source TCP address, Destination TCP address, SEQ, ACK, Data

登録済みのポートは/etc/servicesにある
$ sudo cat /etc/services

http            80/tcp          www www-http    # WorldWideWeb HTTP
http            80/udp          www www-http    # HyperText Transfer Protocol
http            80/sctp                         # HyperText Transfer Protocol

ネットワーク接続一覧の確認
$ netstat -a

パケット送信の流れ
1. Raw Socket作成
2. IPヘッダー作成
3. UDPヘッダー作成
4. 送信

payloadとはデータ送信における正味のデータ部分
Linuxでは、socket()関数を利用してソケットを作成できる
サーバ側はソケットを作成し、接続待ちをするIPアドレスとポートを設定し、接続を受け付け通信を行う
クライアント側はソケットを作成し、接続相手を設定し通信を行う

socket()-> bind() -> listen() -> accept() -> read()/write() -> close()
apacheの場合、不特定多数のクライアントとやり取りするので、子プロセスで複数のaccept()の状態を作る

つまり様々なデータはsocket化して基本的にTCP/IPで、変調して電磁波で送受信して、クライアントとサーバでやり取りしてるってことね。
そして1パケットは128バイトってことは、リクエストに応じたパケットを作成しているのね。
この辺、義務教育で勉強したかったな。しかし、subnetやgatewayはawsの概念と一緒だな。Linux研究せなあかん。

VPC、public subnet、InternetGateway、RouteTableの作成

EC2の構成を見ると、VPCの中にsubnetがあり、その中にEC2が入る。
従って、EC2の前にVPC、subnetを作成していく。

1. VPCの作成
CIDR block

2. Subnetの作成
どこと通信できるか設定

3. Route Tableの作成
Subnet間や外部通信用の設定
SubnetとInternet Gatewayの設定

4. Internet Gatewayの作成
インターネットと通信することをRoute Tableに許可
VPCにアタッチして、Route Tableに紐づけ

5. Network ACLの設定
SubnetのInBound(内部への通信)とOutBound(外部への通信)制御の設定

6. Security Groupの設定
インスタンスのInBound(内部への通信)とOutBound(外部への通信)制御の設定

### 1. VPCの作成
name-tag: dev-vcp
IPv4 CIDR block: 192.168.0.0/16 (10.0.0.0/16などでも可)
※「/16」は16個のアドレスができるという意味。ネットマスク
※CIDRとはIPアドレスの記述形式

CIDR block: A.B.C.D/E
AはVPC作成時に設定(内部のルーティング)
BはVPC作成時に設定(内部のルーティング)
EはVPC作成時に設定
CはSubnet作成時に設定(subnetごとに分ける)
DはSubnet作成後に自動設定(Cから自動生成)

VPC作成時に、VPCのトラフィックをルーティングするためのルールを登録する「ルートテーブル」というリソースも作成される

### 2. subnetの作成
name-tag: dev-subnet-public
vpc: dev-vpc
VPC CIDRs: 192.168.0.0/16
IPv4 CIDR block: 192.168.1.0/28

### 3. Internet Gateway
name-tag: dev-igw
作成後、actionでdev-vcpにattach

### 4. RouteTable作成
どのIPアドレス宛の通信をInternet Gatewayにむけるか決める
name-tag: dev-routetable
vpc: dev-vpc

– ルートテーブルにインターネットゲートウェイへのルートを登録する
->ルートの編集
Destination: 0.0.0.0/0
Target: Internet-gateway igw-********
※VPC内宛以外の通信に関してはインターネットゲートウェイに向く

ルートテーブルからサブネットに紐付け
Subnet Associationsタブをクリック

以上で、VPC(dev-vcp)の中にpublic subnet(dev-subnet-public)ができて、RouteTable(dev-routetable)で、Internet Gatewayに紐付けられている状態ができました。

defaultVPCではなく、実際に作ることで、VPC、public subnet、InternetGateway、RouteTableについて、大幅に理解が深まります。

NATとSTUN・TURNサーバー

WebRTC通信
– Peer to Peer、ブラウザ間で直接通信
– UDP/IPを使用、オーバーヘッドが少ない
– 鍵交換で暗号化通信を行う
-> 相手のIPアドレス、動的なUDPポート番号を知る必要がある
-> 通信経路の仕組みがInteractive Connectivity Establishment、その候補がICE Candidate
–> NATを通過するためのSTUNサーバから取得したポートマッピング
–> Firewallを越えるための、TURNによるリレーサーバーを介した中継通信
–> このやりとりをシグナリングと言う。WebSocketなど複数の方法がある
-> 複数人通信の場合には、それぞれのユーザとSDP/IPのconnectionをつくる必要がある

NATとは
 グローバルIPとローカルのネットワークIPとの変換
 複数のPC/デバイスが同時に通信できるよう、ポートマッピングによるポート変換
 →ブラウザはローカルのIP、UDPポートはわかるが、グローバルのIP、UDPはわからない
 →→Peer to Peerはグローバルの情報を交換する必要がある

STUN(Session Traversal Utilities for NATs)
NATで変換されたIP/UDPを外のSTUNサーバーから教えてもらう
→グローバル情報をシグナリングサーバーけいゆうで相手に渡す
STUNサーバーはGoogleのstun.l.google.com:19302など

TURN(Traversal Using Relays around NAT)
ストリームデータの受け渡しにリレーする
TURNサーバが入ると厳密にはPeer to Peerではなくなる
データのデコード、エンコードは行わないので、ネットワーク負荷が高くなる

あれ、Bitcoinって、P2Pだけど、STAN, TURN使ってるんだっけ?
否、BitcoinはTCP😂

DNS

DNSはDomain Name Systemの略
ドメイン名とIPアドレスの対応付け
メールの宛先ホストを指示

→ IPアドレスではわかりにくい為、名前で指定
ARPANETではホスト名とIPアドレスの対応表としてHOSTS.txtを使用していた。
SRI-NICから入手して接続。SIR-NICはホストとIPの更新作業を行なっていた。実態はAT&Tなど
現在の/etc/hosts と同様

ファイルの増大化に伴い、1983年にRFC882、RFC883発表 これが現在のDNSの元
RFC882:https://tools.ietf.org/html/rfc882
RFC883:https://tools.ietf.org/html/rfc883

DNSの仕組み
名前空間最上位にルートサーバが作成。ルートサーバはjp, comなどドメイン名を管理
ドメインを階層構造で管理、更新を分散化

問い合わせを行う為のDNSサーバはキャッシュ機能がある

セカンダリDNSとは負荷分散、障害対策のために、DNSを二つ用意する
DNSSECとはデータ作成元の認証やデータの完全性を確認できるよう仕様を拡張するもの

1つの権威DNSサーバが管理する範囲をゾーンと呼び、その情報をゾーン情報と呼ぶ
ゾーン情報は、Aレコード、MXレコード、NSレコードなど多数のゾーン情報がある

SOA: ゾーン情報を記載(ドメインDNS, ドメイン管理者、更新間隔、転送再試行、レコード有効時間、キャッシュ有効時間) 他のDNSに転送する
NS: ドメインのDNSサーバ名を指定
A: ホストのIPアドレス
PTR: IPアドレスに対するホスト名
CNAME: ホスト名のエイリアス
MX: ドメインのメール・サーバ名
HINFO: ホストの追加情報
WKS: ホストで実行されているサービス情報
TXT: ホストへのテキスト情報

ネームサーバーとは、インターネット通信時にドメイン名をIPアドレスに変換する名前解決を行うサーバー
ネームサーバー = DNSサーバー

Route53で言う所の SOAがゾーン情報、NSがドメインのDNSサーバーに当たる

AWSのroute53で登録するとDNSサーバーがawsになる。

サーバー側で、virtual hostを設定すると、指定したディレクトリをさす

<VirtualHost *:80>
DocumentRoot /www/example1
ServerName www.example.com

# Other directives here

</VirtualHost>

ルートネームサーバからサーバに繋げるのはわかるけど、シードDNSがクライアントにipを返す仕組みがわからないな。

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ nslookup google.com
Server: 10.0.2.3
Address: 10.0.2.3#53

Non-authoritative answer:
Name: google.com
Address: 216.58.199.238

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ nslookup 216.58.199.238
Server: 10.0.2.3
Address: 10.0.2.3#53

Non-authoritative answer:
238.199.58.216.in-addr.arpa name = kix05s02-in-f238.1e100.net.
238.199.58.216.in-addr.arpa name = kix05s02-in-f14.1e100.net.

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ dig google.com

; <<>> DiG 9.9.5-3ubuntu0.19-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54587 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;google.com. IN A ;; ANSWER SECTION: google.com. 205 IN A 216.58.197.14 ;; Query time: 48 msec ;; SERVER: 10.0.2.3#53(10.0.2.3) ;; WHEN: Fri Nov 01 11:29:11 UTC 2019 ;; MSG SIZE rcvd: 55

WebRTC

ウェブブラウザやモバイルアプリケーションにシンプルなAPI経由でリアルタイム通信を提供するオープンソースPJ
https://webrtc.org/

-Supported Browsers & Platforms
Firefox, Opera, Android, iOS

使用するAPI
– MediaStream
– PeerConnection
– DataChannel

P2P、Node.js、WebSocket
あれ??? これもしかして、、、