如何建立 Google Cloud VPN

當你想要將服務轉換到 Google Cloud 上,卻發現你無法將所有元件搬移上去,得要在分散於兩個不同網路的元件之間傳遞資料時,你會開始在想「我要怎麼在兩個受信任的網路之間傳遞資料而不被竊聽?幫每個元件之間的連線都改用 SSL/TLS 連線嗎?如果該元件不支援 SSL/TLS 怎麼辦?」。這時我們可以採用 IPsec VPN ,將兩個網路之間的通訊進行加密,藉此保護你的資料不會以明文的方式在網際網路上進行傳輸,也省去要對多個元件分別修改設定 SSL/TLS 的困擾。而 IPsec VPN 是被 Google Cloud VPN 支援的,所以我們在此使用 Google Cloud VPN 來為兩端的網路間建立安全的通道。

需求與限制

  • 兩端(分別是 in-house 與 Google Cloud 端)都需要有 VPN gateway 。 in-house 端可以是獨立的 VPN gateway 設備,也可以在 server 上透過安裝軟體完成。 Google Cloud 端則由 Google Cloud VPN 提供。
  • in-house 端的 VPN gateway 需要支援 IKEv1 或 IKEv2 pre-shared key authentication 。
  • in-house 端的 VPN gateway 需要支援 ESP Tunnel Mode 。
  • 兩端的 VPN gateway 都需要有 static public IP 。
  • 如果 in-house VPN gateway 外有 firewall ,請開放 udp:500,4500 這兩個 port 以便讓 ESP & IKE 流量通過
  • 兩端網路使用的 IP range 不可以重疊
  • 準備好 <secret-key> ,在設定兩端的 VPN gateway 時會用到。
這裡為了簡化說明,我們會使用 Google Cloud 來建立 in-house 端的環境。

準備 in-house 端與 Google Cloud 端的網路

建立 in-house 端網路
gcloud compute - -project "in-house-project" networks create "vpn" --mode "custom" gcloud compute --project "in-house-project" networks subnets create "vpn-asia-east1" --network "vpn" --region "asia-east1" --range "192.168.0.0/24" gcloud compute --project "in-house-project" firewall-rules create "vpn-allow-ssh" --allow tcp:22 --network "vpn" --source-ranges "0.0.0.0/0" gcloud compute --project "in-house-project" firewall-rules create "vpn-allow-internal" --allow tcp,udp,icmp --network "vpn" --source-ranges "192.168.0.0/24" gcloud compute --project "in-house-project" firewall-rules create "vpn-allow-gcloud" --allow tcp,udp,icmp --network "vpn" --source-ranges "10.240.0.0/24"
  這裡將 in-house 端網路的 IP range 設定為 192.168.0.0/24 ,同時設定了 firewall 讓我們能透過 SSH 連上 GCE instance 進行操作、讓 in-house 端網路內部互連以及與 Google Cloud 端網路能夠互連。 接著建立 Google Cloud 端網路
gcloud compute --project "google-cloud-project" networks create "vpn" --mode "custom" gcloud compute --project "google-cloud-project" networks subnets create "vpn-asia-east1" --network "vpn" --region "asia-east1" --range "10.240.0.0/24" gcloud compute --project "google-cloud-project" firewall-rules create "vpn-allow-ssh" --allow tcp:22 --network "vpn" --source-ranges "0.0.0.0/0" gcloud compute --project "google-cloud-project" firewall-rules create "vpn-allow-internal" --allow tcp,udp,icmp --network "vpn" --source-ranges "10.240.0.0/24" gcloud compute --project "google-cloud-project" firewall-rules create "vpn-allow-inhouse" --allow tcp,udp,icmp --network "vpn" --source-ranges "192.168.0.0/24"
  這裡將 Google Cloud 端網路的 IP range 設定為 10.240.0.0/24 ,與 in-house 端的 192.168.0.0/24 有所不同,這裡也同時設定了 firewall 讓我們能透過 SSH 連上 GCE instance 進行操作、讓 Google Cloud 端網路內部互連以及與 in-house 端網路能夠互連。 最後請執行以下指令,在兩個 project 內各保留一個 public IP 供 VPN gateway 使用。
gcloud compute --project "in-house-project" addresses create "vpn-gateway" --region "asia-east1" gcloud compute --project "google-cloud-project" addresses create "vpn-gateway" --region "asia-east1"
  記下保留下來的 IP address ,這裡假設在 in-house-projectgoogle-cloud-project 保留下來的 IP 分別是 111.111.111.111111.111.222.222 ,之後會用到。

準備 in-house 端環境

step 1 在 in-house 端網路建立 VPN gateway 可以參考 Set up a VPN gateway ,在 in-house 端的網路內找一台 Linux server ,安裝 strongSwan 來當作 VPN Gateway 。 執行以下指令,建立一個 GCE instance 當作 VPN gateway ,設定 firewall 開放 ESP & IKE 流量後,使用 SSH 連上它
gcloud compute --project "in-house-project" instances create "vpn-gateway" --zone "asia-east1-b" --machine-type "f1-micro" --subnet "vpn-asia-east1" --private-network-ip "192.168.0.2" --address 111.111.111.111 --can-ip-forward --tags "vpn-gateway" --image-family "debian-8" gcloud compute --project "in-house-project" firewall-rules create "vpn-allow-ike-esp" --allow udp:500,udp:4500 --network "vpn" --source-ranges "111.111.222.222" --target-tags "vpn-gateway" gcloud compute --project "in-house-project" ssh "vpn-gateway" --zone "asia-east1-b"
  之後開始安裝 strongSwan ,這裡先來準備設定檔 ipsec.conf 。這裡可以使用你習慣的編輯器,將以下設定貼入設定檔中。設定檔裡面的 left 指的是現在正在設定的 VPN gateway 所在的網路相關設定, right 則是另一端網路的相關設定。
conn myconn  authby=psk  auto=start  dpdaction=hold  esp=aes128-sha1!  forceencaps=yes  ike=aes128-sha1-modp2048!  keyexchange=ikev2  mobike=no  type=tunnel  left=%any  leftid=111.111.111.111  leftsubnet=192.168.0.0/24  leftauth=psk  leftikeport=4500  right=111.111.222.222  rightsubnet=10.240.0.0/24  rightauth=psk  rightikeport=4500
  然後執行以下指令安裝並設定 strongSwan ,記得將 <secret-key> 替換成你想要的字串
sudo apt-get update sudo apt-get install strongswan -y echo "%any : PSK \"<secret-key>\"" | sudo tee /etc/ipsec.secrets > /dev/null echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf > /dev/null sudo sysctl -p sudo cp ipsec.conf /etc sudo ipsec restart sudo ipsec up myconn
  step 2 在 in-house 端網路設定前往 Google Cloud 端網路的 route
gcloud compute --project "in-house-project" routes create "inhouse2gcloud" --destination-range "10.240.0.0/24" --network "vpn" --next-hop-instance "vpn-gateway" --next-hop-instance-zone "asia-east1-b" --priority "1000"
  step 3 在 in-house 端網路建立 VPN client
gcloud compute --project "in-house-project" instances create "vpn-client" --zone "asia-east1-b" --machine-type "f1-micro" --subnet "vpn-asia-east1" --image-family "debian-8" gcloud compute --project "in-house-project" ssh "vpn-client" --zone "asia-east1-b"
  然後安裝 Nginx
sudo apt-get update sudo apt-get install nginx-light -y echo "This is a response coming from in-house." | sudo tee /var/www/html/index.html > /dev/null
 

準備 Google Cloud 端環境

step 1 設定 Google Cloud VPN 記得將 <secret-key> 替換成你想要的字串
gcloud compute --project "google-cloud-project" target-vpn-gateways create "vpn-gateway" --region "asia-east1" --network "vpn" gcloud compute --project "google-cloud-project" forwarding-rules create "vpn-gateway-rule-esp" --region "asia-east1" --address "111.111.222.222" --ip-protocol "ESP" --target-vpn-gateway "vpn-gateway" gcloud compute --project "google-cloud-project" forwarding-rules create "vpn-gateway-rule-udp500" --region "asia-east1" --address "111.111.222.222" --ip-protocol "UDP" --port-range "500" --target-vpn-gateway "vpn-gateway" gcloud compute --project "google-cloud-project" forwarding-rules create "vpn-gateway-rule-udp4500" --region "asia-east1" --address "111.111.222.222" --ip-protocol "UDP" --port-range "4500" --target-vpn-gateway "vpn-gateway" gcloud compute --project "google-cloud-project" vpn-tunnels create "tunnel2inhouse" --region "asia-east1" --peer-address "111.111.111.111" --shared-secret "<secret-key>" --ike-version "2" --target-vpn-gateway "vpn-gateway"
  step 2 在 Google Cloud 端網路設定前往 in-house 端網路的 route
gcloud compute --project "google-cloud-project" routes create "gcloud2inhouse" --network "vpn" --next-hop-vpn-tunnel "tunnel2inhouse" next-hop-vpn-tunnel-region "asia-east1" --destination-range "192.168.0.0/24"
  step 3 在 Google Cloud 端網路建立 VPN client
gcloud compute --project "google-cloud-project" instances create "vpn-client" --zone "asia-east1-b" --machine-type "f1-micro" --subnet "vpn-asia-east1" --image-family "debian-8" gcloud compute --project "google-cloud-project" ssh "vpn-client" --zone "asia-east1-b"
  然後安裝 Nginx
sudo apt-get update sudo apt-get install nginx-light -y echo "This is a response coming from Google Cloud." | sudo tee /var/www/html/index.html > /dev/null
 

執行測試

gcloud compute --project "in-house-project" ssh vpn-client --command 'curl http://10.240.0.2 2>/dev/null' gcloud compute --project "google-cloud-project" ssh vpn-client --command 'curl http://192.168.0.3 2>/dev/null'
  如果分別看到 This is a response coming from Google Cloud.This is a response coming from in-house. 的話,就代表兩邊網路之間的 VPN 連線已經建立成功了!

Reference