如何建立 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