VPN(IPsec)によるS3からGCSへのprivateデータ転送

インターネット(https)経由でのS3->GCSデータ連携パターンは
以下記事で実験したので
https://note.com/ucwork/n/n825ac1c96764
https://note.com/ucwork/n/n5fe04382409b

次はインターネットVPN(IPsec)経由でのデータ転送を実験してみる

全体的な流れ

こんなイメージ
1. AWS, GCP間をVPNで接続しprivate ipでアクセスできるようにする
2. GCSへのアクセスがprivateか確認する
3. S3へのアクセスもprivateにする
4. S3->GCSへのアクセスをprivateに実現!

とはいえVPN構成作ること自体初めてなので
ひとつひとつ学習しながら進めていく

今回の記事で出来上がった構成を雑に書くとこんな感じ

画像44

VPNで接続する

こちらの素敵記事があったので、そのまんま真似してみる
https://dev.classmethod.jp/articles/aws_gcp_vpn/

AWS側の設定

VPCを作成
とりあえず今回利用するVPCを作成

画像1

Virtual Private Gatewayを作成
VPN接続のためのVirtual Private Gatewayを作成

画像2

作成したVPCにattach

スクリーンショット 2020-07-19 17.18.40

画像4

Route Propagationの設定
VPCのRoute Tableで、Virtual Private GatewayのRoute PropagationをYesに設定。
この設定でVirtual Private Gatewayのルーティング情報がRoute Tableに自動で反映される
Virtual Private GatewayにはBGPで学習した相手のルーティング情報を保持している感じ。きっと

画像5

画像6

GCP側の設定
VPCネットワークの作成
今回使用するVPCネットワーク、private用subnetを作成
後々GCSにprivate接続することを想定してsubnetでは「限定公開のGoogleアクセス」はオンにしておく

画像7

Cloud Router作成
作成したVPCを指定してCloud Routerの作成
これを作成することで、AWS側でGCP側のルート情報を知ることができる

FireShot Capture 056 - Cloud Router の作成 – ハイブリッド接続 – uchiyama-sandbox – Google Cloud Platfor_ - console.cloud.google.com

Cloud VPN作成
公式では高可用性(HA)推奨だが
とりあえず検証したいのでコスト少なそうなClassicで

FireShot Capture 057 - VPN の作成 – ハイブリッド接続 – uchiyama-sandbox – Google Cloud Platform_ - console.cloud.google.com

IPアドレスを作成指定、IPアドレスが指定されるので
トンネルは一旦スルーしてAWSの設定に戻る

画像11

AWSの作業に戻る
VPNの作成
GCPで作成したIPアドレスと指定したASNを設定し作成!
他のオプションは特に触らない

FireShot Capture 058 - Create VPN Connection - VPC Management Console_ - ap-northeast-1.console.aws.amazon.comのコピー

設定のダウンロード
作成したVPNを指定してDownload Configurationを押下
Genericを指定してDownload

画像12

GCPのVPN設定に戻る
AWSでダウンロードした情報を以下の通り入力
・リモートピアIPアドレス:IPSec Tunnel #1 > #3: Tunnel Interface Configuration > Outside IP Addresses > Virtual Private Gatewayを入力
・IKEバージョン:IKEv1を選択
・IKE事前共有キー:IPSec Tunnel #1 > #1: Internet Key Exchange Configuration > Pre-Shared Key
・ ルーティングオプション:動的(BGP)
・ クラウドルーター:作成したCloud Routerを指定

画像14

BGPセッションのペンボタンを押下して、AWSダウンロード情報を入力
・ピアASN:IPSec Tunnel #1 > #4: Border Gateway Protocol (BGP) Configuration > BGP Configuration Options > Virtual Private Gateway ASN
・Cloud Router のBGP IP:
IPSec Tunnel #1 > #3: Tunnel Interface Configuration > Inside IP Addresses > Customer Gateway(CIDRが指す対象のIPアドレスを指定)
・BGP ピア IP:
IPSec Tunnel #1 > #3: Tunnel Interface Configuration > Inside IP Addresses > Virtual Private Gateway
(同上)

画像13

うまく入力できていれば
VPNトンネルのステータス、BGPセッションのステータスが
それぞれ確立になりグリーンアイコンが表示される
※BGPセッションの入力内容間違えててなかなか確立しなかった😫

画像15

AWS側も以下の通りStatusがUPになって確立が確認できる

画像16

VPNのPrivate接続確認

AWS、GCPそれぞれにインスタンスを作成し、PrivateIP指定のpingが通ることを確認してみる

AWS側の設定
private想定のsubnetをVPCに作成

画像19

private subnetにEC2を作成
適当なAMI, Instance Typeを指定

画像17

画像18

作成したサブネットを指定

画像20

Security GroupのInbound指定
pingを受け付けられるようにICMPのInboundルールを追加

画像21

作成したprivate EC2に踏み台経由でssh接続
作成したEC2はprivateなので、踏み台用のpublicなEC2作成する
まずはVPCにpublic想定のsubnet作成

画像25

作成したpublic想定のsubnetにEC2作成
基本は上記でEC2作成した手順通りだが、サブネットを作成したもの指定
Public IPをEnableにする

画像43

お家からssh接続できるようにSecurity Group設定
SourceはMy IP選択すると接続中のGlobal IP設定される

画像27

作成したEC2にssh接続するためにはInternet Gatewayへのルートを設定した
Route Tableが必要なので新たに作成

画像29

画像28

作成したRoute tableのRouteにInternet Gatewayを追加

画像30

Route tableとsubnetを適切に関連付ける
Internet GatewayのRouteがあるRoute Tableをpublic想定のsubnetにセット

画像31

踏み台(Bastion)EC2経由でprivateなEC2に接続!
publicなEC2の「IPv4 Public IP」とprivateなEC2の「Private IPs」を指定してssh接続

$ ssh -o ProxyCommand='ssh -i ~/Downloads/ucwork.pem ec2-user@[bastion global ip] -W [target private ip]:22' -i ~/Downloads/ucwork.pem ec2-user@[target private ip]
...

       __|  __|_  )
      _|  (     /   Amazon Linux AMI
     ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
4 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@xxx ~]$

接続でけた!

GCP側にもインスタンス作成
インスタンス作成
作成したサブネットを指定してGCE作成
外部IPなしでprivateに設定

画像33

pingを受け付けられるようにICMPを受け入れるFW作成

画像42

privateなGCEに接続するために、publicなサブネットを作成

画像33

publicなサブネットに踏み台用GCE(Bastion)を作成
外部IP(エフェメラル)を指定

画像34

ssh接続できるようにtcp:22を許可するセキュリティグループ作成

画像23

publicなインスタンスに公開鍵登録

スクリーンショット 2020-07-21 22.08.12

踏み台インスタンスからprivateインスタンスにSSH接続確認

$ ssh -o ProxyCommand='ssh -i ~/.ssh/id_rsa [ssh user name]@[bastion global ip] -W 10.4.1.2:22' -i  ~/.ssh/id_rsa shintaro.uchiyama@10.4.1.2
...
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
...
Last login: Tue Jul 21 12:54:09 2020 from xxx
shintaro.uchiyama@ucwork-gce:~$

接続できた!!
AWS, GCPそれぞれprivate ip指定で接続確認

AWS
以下の通りEC2からGCEにping飛ばして疎通確認

$ ssh -o ProxyCommand='ssh -i ~/Downloads/ucwork.pem ec2-user@[bastion global ip] -W 10.1.1.47:22' -i ~/Downloads/ucwork.pem ec2-user@10.1.1.47
...
Last login: Thu Jul 23 13:10:44 2020 from 10.1.2.238

      __|  __|_  )
      _|  (     /   Amazon Linux AMI
     ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
4 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-1-1-47 ~]$
[ec2-user@ip-10-1-1-47 ~]$ # インターネットには出れないこと確認
[ec2-user@ip-10-1-1-47 ~]$ ping -c 3 youtube.com
PING youtube.com (172.217.26.46) 56(84) bytes of data.

--- youtube.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2043ms
[ec2-user@ip-10-1-1-47 ~]$ # 出れない!privateや!
[ec2-user@ip-10-1-1-47 ~]$ 
[ec2-user@ip-10-1-1-47 ~]$ # GCPのprivateなGCEにping
[ec2-user@ip-10-1-1-47 ~]$ ping -c 3 10.4.1.2
PING 10.4.1.2 (10.4.1.2) 56(84) bytes of data.
64 bytes from 10.4.1.2: icmp_seq=1 ttl=63 time=8.46 ms
64 bytes from 10.4.1.2: icmp_seq=2 ttl=63 time=7.14 ms
64 bytes from 10.4.1.2: icmp_seq=3 ttl=63 time=6.98 ms

--- 10.4.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 6.987/7.533/8.468/0.667 ms
[ec2-user@ip-10-1-1-47 ~]$ # 接続できてる!!

GCP
以下の通りGCEからEC2にping飛ばして疎通確認

$ ssh -o ProxyCommand='ssh -i ~/.ssh/id_rsa shintaro.uchiyama@[bastion global ip] -W 10.4.1.2:22' -i  ~/.ssh/id_rsa shintaro.uchiyama@10.4.1.2
...
Last login: Fri Jul 24 01:27:21 2020 from 10.4.2.2
[user name]@ucwork-gce:~$
[user name]@ucwork-gce:~$ # インターネットには出れないこと確認
[user name]@ucwork-gce:~$ ping -c 3 youtube.com
PING youtube.com (172.217.25.206) 56(84) bytes of data.

--- youtube.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 26ms
[user name]@ucwork-gce:~$ # 出れない!privateや!
[user name]@ucwork-gce:~$
[user name]@ucwork-gce:~$ # AWSのprivateなEC2にping
[user name]@ucwork-gce:~$ ping -c 3 10.1.1.47
PING 10.1.1.47 (10.1.1.47) 56(84) bytes of data.
64 bytes from 10.1.1.47: icmp_seq=1 ttl=253 time=8.10 ms
64 bytes from 10.1.1.47: icmp_seq=2 ttl=253 time=8.10 ms
64 bytes from 10.1.1.47: icmp_seq=3 ttl=253 time=7.01 ms

--- 10.1.1.47 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 7.014/7.736/8.099/0.510 ms
[user name]@ucwork-gce:~$ # pingできてる!!

長かった。これでVPN接続してそれぞれpingでprivate ip宛に接続できた

S3へのアクセスをprivateにしてみる

当初の目的を忘れかけてきたが、S3からGCSにprivateでデータを送信することだった👶S3、GCSへのアクセスもprivateにする

S3へprivate接続するためにVPC Endpoint作成

対象のVPC、private subnetに関連したRoute Tableを指定して作成

画像32

S3へのprivate接続を確認

$ # privateなEC2に接続
$ ssh -o ProxyCommand='ssh -i ~/Downloads/ucwork.pem ec2-user@[bastion global ip] -W [target private ip]:22' -i ~/Downloads/ucwork.pem ec2-user@[target private ip]
...

       __|  __|_  )
      _|  (     /   Amazon Linux AMI
     ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
4 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@xxx ~]$ 
[ec2-user@xxx ~]$ ping -c 3 youtube.com
PING youtube.com (172.217.25.78) 56(84) bytes of data.

--- youtube.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2038ms

[ec2-user@xxx ~]$ # EC2からインターネットに接続できなさそう
[ec2-user@xxx ~]$
[ec2-user@xxx ~]$ aws s3 ls --region ap-northeast-1 --recursive s3://[bucket-name]/access_allow/
Unable to locate credentials. You can configure credentials by running "aws configure".
[ec2-user@xxx ~]$ # uge...認証せねばならぬみたい
[ec2-user@xxx ~]$
[ec2-user@xxx ~]$ aws configure
AWS Access Key ID [None]: [AWS Access Key ID]
AWS Secret Access Key [None]: [AWS Secret Access Key]
Default region name [None]: ap-northeast-1
Default output format [None]:
[ec2-user@xxx ~]$
[ec2-user@xxx ~]$ # s3への接続確認
[ec2-user@xxx ~]$ aws s3 ls --region ap-northeast-1 --recursive s3://[bucket-name]/access_allow/
2020-07-12 13:44:44          0 access_allow/
2020-07-12 13:47:02         14 access_allow/test.csv

S3のバケットにPrivateにアクセスできた!
S3アクセスのためのIAMポリシー周りの設定はこの辺見てちょ
https://note.com/ucwork/n/n5fe04382409b

GCSへのアクセスをprivateにする

private用subnet作成時に「限定公開のGoogleアクセス」を指定してるので
S3へのアクセスもprivateに行けるはず!

$ ssh -o ProxyCommand='ssh -i ~/.ssh/id_rsa [user name]@[bastion global ip] -W 10.4.1.2:22' -i  ~/.ssh/id_rsa [user name]@10.4.1.2
...
Last login: Fri Jul 24 02:05:59 2020 from 10.4.2.2
[user name]@ucwork-gce:~$
[user name]@ucwork-gce:~$ ping -c 3 youtube.com
PING youtube.com (172.217.25.206) 56(84) bytes of data.

--- youtube.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 27ms
[user name]@ucwork-gce:~$ # インターネットには接続できてない
[user name]@ucwork-gce:~$
[user name]@ucwork-gce:~$ gsutil ls
gs://xxx
[user name]@ucwork-gce:~$ # gcsに接続できた!!

S3からGCSへprivateデータ転送

VPC間をCloud VPNで接続、VPC(AWS)->S3、VPC(GCP)->GCSへのprivate接続はできたけど、
当初の目的を達成にするためには、VPC(AWS)->GCSへのprivate接続が必要なことにここめできて気づく👶

ググってみた感じこの記事が目的を達成してくれそう!
ざくっというとGCSやBigQueryなど*.googapis.comへのアクセスをVPN経由にして、GCS内からprivateアクセスされる感じ

*.googleapis.comをprivate.googleapis.com(199.36.153.8/30)へ向ける
普通にするとインターネット経由しないとアクセスできないGlobalIPに対してアクセスしようとする

$ dig bigquery.googleapis.com +short
172.217.161.74

VPN経由してprivateにGoogleリソースにアクセスするためには
private.googleapis.com(199.36.153.8/30)にリクエストをしなければいけないらしい
ということで、Route53でPrivateなHosted Zoneを作成して
*.googleapis.comを199.36.153.8/30にアクセスするようにする

画像36

以下4IPアドレスをAレコードとして登録
199.36.153.8, 199.36.153.9, 199.36.153.10, 199.36.153.11

画像37

しばらく待ってると、IPが変わる!

[ec2-user@ip-10-1-1-47 ~]$ dig bigquery.googleapis.com +short
172.217.161.74
[ec2-user@ip-10-1-1-47 ~]$ 
[ec2-user@ip-10-1-1-47 ~]$ dig bigquery.googleapis.com +short
199.36.153.8
199.36.153.9
199.36.153.10
199.36.153.11

199.36.153.8/30をVPNに向ける
作成していたCloud Routerを編集してカスタムルートを追加する
これにより、AWS側がこのルートを学習し、Route Tableに追加される

画像38

AWSのルートに追加されてる!

スクリーンショット 2020-07-25 0.03.34

gsutilでのS3からGCSへのデータ転送確認

AWSからgsutilコマンド実行してデータ転送することを想定
ということで、privateなEC2にgsutilをインストールする!

NAT Gatewayを配置するpublicなsubnet作成

画像41

作成したsubnetを対象にNAT Gateway作成

画像40

privateなサブネットのRouteにNAT Gatewayを指定

画像42

これでprivate EC2からインターネット接続できるので
公式にならってgsutilコマンドをインストールする

サービスアカウント鍵のアップロード
権限を付与したサービスアカウント鍵をEC2にアップロードする

scp -o ProxyCommand='ssh -i ~/Downloads/ucwork.pem ec2-user@[bastion global ip] -W 10.1.1.47:22' -i ~/Downloads/ucwork.pem ~/Downloads/[credential file].json ec2-user@10.1.1.47:~/credential.json

AWS IAMのCredential情報を設定
S3アクセス間のあるIAM Credential情報を設定

[ec2-user@ip-10-1-1-47 ~]$ cat ~/.boto
[Credentials]

aws_access_key_id = [aws_access_key_id]
aws_secret_access_key = [aws_secret_access_key]
s3_host = s3-ap-northeast-1.amazonaws.com

データ転送検証
ついにきた!!データ転送検証確認
EC2がインターネットに接続できない状態で動作検証したいので
gsutilコマンドインストールのためにセットしたNAT GatewayへのRouteを削除して以下検証を行う!!!

[ec2-user@ip-10-1-1-47 ~]$ ping -c 3 youtube.com
PING youtube.com (172.217.175.238) 56(84) bytes of data.

--- youtube.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2054ms

[ec2-user@ip-10-1-1-47 ~]$ # インターネットには出れない状態
[ec2-user@ip-10-1-1-47 ~]$
[ec2-user@ip-10-1-1-47 ~]$ gsutil cp s3://[bucket-name]/access_allow/test.csv gs://[bucket-name]/test2.csv
Copying s3://[bucket-name]/access_allow/test.csv [Content-Type=text/csv]...
/ [1 files][   14.0 B/   14.0 B]
Operation completed over 1 objects/14.0 B.
[ec2-user@ip-10-1-1-47 ~]$ # 遅れていそうな雰囲気!
[ec2-user@ip-10-1-1-47 ~]$
[ec2-user@ip-10-1-1-47 ~]$ gsutil ls gs://[bucket-name]/
gs://[bucket-name]/test2.csv

データ転送できてたぁあぁああああああ!!!

まとめ

とにかく長かった。初めはVPN接続したことないからやってみようくらいの気持ちだったが。こんなに長くなってしまった。

業務で取り組むことがあれば、次は絶対Terraformでやって再現しやすいようにしよう👳



この記事が気に入ったらサポートをしてみませんか?