GCP上配置firewall 防火墙教程
GCP上配置firewall 防火墙教程
程式写好部署完毕、执行环境准备完成、资料库就绪,服务准备上线了!
等等!在Google Cloud 上开放服务之前,你有没有确认过服务是不是能够被正常存取呢?是不是有内部使用的服务能被外人存取呢?在这里我们带你看看GCE firewall ,让您了解透过使用GCE firewall 能够为您的服务做到何种程度的存取控制,在维持可以正常提供服务的同时减少让人有机可乘之处。
准备测试环境
建立测试GCE firewall 用的network 。
gcloud compute --project "demo-project" \
networks create "demo" --mode "auto"
然后建立两个放在demo network中的GCE instance 。
gcloud compute --project "demo-project" \
instances create "demo-1" --zone "asia-east1-a" \
--machine-type "f1-micro" \
--subnet "demo" \
--image-project "debian-cloud" \
--image-family "debian-8" \
--boot-disk-size "10" \
--boot-disk-type "pd-standard" \
--boot-disk-device-name "demo-1"
gcloud compute --project "demo-project" \
instances create "demo-2" --zone "asia-east1-a" \
--machine-type "f1-micro" \
--subnet "demo" \
--metadata "startup-script=apt-get install nginx-light -y && echo \"Hello \$HOSTNAME\" | tee /var/www/html/index.html > /dev/null" \
--image-project "debian-cloud" \
--image-family "debian-8" \
--boot-disk-size "10" \
--boot-disk-type "pd-standard" \
--boot-disk-device-name "demo-2"
以 source IP 控制存取
我们在本机先试着用SSH连上demo-1 。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'echo "Hello World"'
等了一段时间之后,我们得到了以下讯息(这里假设demo-1 的external IP是222.111.111.111 ) 。
ssh: connect to host 222.111.111.111 port 22: Operation timed out
ERROR: (gcloud.compute.ssh) [/usr/bin/ssh] exited with return code [255]. See https://cloud.google.com/compute/docs/troubleshooting#ssherrors for troubleshooting hints.
大概是说明无法连线,请我们去找某某文件解决这个问题。不过没关系,我们先执行下面这个指令,列出demo 这个network中所有的firewall rule 。
gcloud compute --project "demo-project" \
firewall-rules list | awk '{ if ( $2 ~ /(NETWORK|demo)/ ) print }'
执行完后我们会发现目前没有任何firewall rule 。在这里我们就来说明一下GCE firewall 是怎么运作的,基本上GCE firewall 对于流入的流量就是「你没说可以的就是不行!」,所以没有firewall rule 等于没有任何流量可以送达GCE instance ,我们必须要新增firewall rule 去决定哪里来的流量(source) 可以透过什么管道(protocol & port number) 送达哪些GCE instance (target) 。
所以我们在本机执行以下指令查询自己对外使用的IP 。
curl https://ipinfo.io/ip
这里假设我们查到自己的IP是111.111.111.111 ,接着执行以下指令加入firewall rule让我们能以这个IP作为source 、透过SSH (使用TCP port 22 )连上GCE instance 。
gcloud compute --project "demo-project" \
firewall-rules create "demo-allow-ssh" \
--network "demo" --source-ranges "111.111.111.111" --allow tcp:22
之后我们再次试着连上demo-1 。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'echo "Hello World"'
因为我们已经新增了firewall rule ,所以这次顺利的以SSH连上了demo-1 ,看到指令执行完出现的Hello World 了。
以 target instance 上的 tag 控制存取
上面我们已经介绍了如何以source IP 来控制存取GCE instance ,但有时你不想、或是不需要让所有的GCE instance 都能被存取,这时我们能够使用tag 来进一步控制firewall rule 适用的范围。
我们可以执行以下指令修改稍早我们建立的firewall rule ,限制做为target的GCE instance要有ssh 这个tag 。
gcloud compute --project "demo-project" firewall-rules update "demo-allow-ssh" --target-tags "ssh"
之后我们试着连上demo-1 。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'echo "Hello World"'
因为demo-1 上并没有ssh 这个tag ,所以firewall rule不让流量通过。
所以我们来帮demo-1 加上ssh 这个tag 。
gcloud compute --project "demo-project" instances add-tags "demo-1" --tags "ssh"
之后再来试验一次。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'echo "Hello World"'
因为demo-1 这个target GCE instance上已经有ssh tag ,加上source IP是111.111.111.111 ,所以我们就能看到Hello World 这个结果了。
以 source instance 上的 tag 控制存取
tag 能够用在限制target GCE instance ,也能用在限制source GCE instance ,借此控制GCE instance 间的存取。
我们先来试着从demo-1 存取demo-2 上的HTTP服务(使用TCP port 80 ) 。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'curl http://demo-2/ 2>/dev/null'
因为没有适用的firewall rule所以流量无法从demo-1 送达demo-2 。
所以我们来加firewall rule ,这个firewall rule准许有着src tag的GCE instance可以存取有着tgt tag GCE instance的TCP port 80 。
gcloud compute --project "demo-project" \
firewall-rules create "demo-allow-src2tgt" \
--network "demo" --source-tags "src" --target-tags "tgt" --allow tcp:80
然后帮demo-2 加上tag tgt 。
gcloud compute --project "demo-project" instances add-tags "demo-2" --tags "tgt"
再次尝试连线。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'curl http://demo-2/ 2>/dev/null'
还是失败,因为demo-1 没有src 这个tag ,现在我们帮他加上去。
gcloud compute --project "demo-project" instances add-tags "demo-1" --tags "src"
再度尝试连线。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'curl http://demo-2/ 2>/dev/null'
这次我们看到了Hello demo-2 ,代表我们顺利的用source tag & target tag控制了网路的存取。
接着我们做另外一个实验,这里假设demo-2 的external IP是222.111.111.222 ,我们改执行以下指令。
gcloud compute --project "demo-project" ssh "demo-1" --zone "asia-east1-a" \
--command 'curl http://222.111.111.222/ 2>/dev/null'
这个实验的连线没有建立成功。这里要说明一下,虽然意图一样是要从demo-1 存取demo-2 ,但之前我们都是以GCE instance name来存取, GCE会透过内部的DNS帮我们把instance name转换成internal IP ,所以实际上demo-1 是用internal IP在存取demo-2 的。而source tag只适用在GCE instance间以internal IP互相存取的场合,所以当我们尝试存取demo-2 的external IP时,实际上GCE firewall看到的source是demo-1 的external IP ,这时我们就要改用source IP的方式来控制存取了。
总结
这里我们带各位走过了最常见的、以source IP 作为GCE firewall 控管方式的设定,之后我们也透过target tag 让GCE firewall 限制可以被存取的GCE instance 的范围,最后也展示了以source tag来限制GCE instance 间的存取。如此你可以实现限制某些服务只有来自特定的IP (如办公室) 可以存取、终端用户只能存取带有特定tag 的GCE instance 上的HTTP 服务、或是只有API server 可以存取DB server 等控管流入GCE instance 流量的方式。至于GCE instance 对外的流量,基本上除了往经常被SMTP 服务使用的TCP port 25, 465, 587 送的流量外,其他对外的流量是不会被阻挡,也无法透过GCE firewall 的任何设定阻挡,这部份必须自己在GCE instance 上面做设定控管。
另外,有一种firewall 被称作web application firewall (WAF) ,与GCE firewall 不同的是WAF 是针对HTTP(S) 流量进行过滤,在侦测到有SQL injection, Cross-Site Scripting 等攻击流量经过(不论流入或流出) 时阻挡该流量通过。如此你可以让GCE firewall 开放HTTP(S) (TCP port 80, 443) 的流量通过WAF , 在WAF 过滤完这些流量以后再放行到真正处理HTTP(S) request 的GCE instance 上,然后HTTP response 再经过WAF 的过滤,最终回到使用者的浏览器上。在这边我们只先说明WAF 与GCE firewall 不同的地方以及适用的情况,并不实际操作给各位看。
QQ咨询
旺旺咨询