一、背景
Amazon API Gateway(以下简称)是AWS的托管的API网关服务。许多企业需要将自身应用的数据接口暴露给第三方合作伙伴,但使用专线成本较高,或者因面向多个互联网服务交互,因此将接口暴露在互联网上。为提升接口安全性,可采用为API Gateway设置来源IP地址限制的办法,提升安全。API Gateway支持设置Resource Policy,通过资源策略中填写IP Condition来限制可以访问的IP访问,包括白名单允许,或者显式拒绝。
使用API Gateway自带的策略控制IP地址有一些局限,因为资源策略是随着API Gateway的部署Stages
下发生效的,因此有时候仅需要IP地址的策略变更,但是为了让其生效,需要对整个接口开发的版本和Stages阶段创建新的版本,并进行流量切换。如此过程对整个应用开发和运行体系的影响较大。那么有什么办法实施Out-of-band方式(带外)的IP策略管控呢?这里就可以用到Amazon WAF。
Amazon WAF(以下简称WAF)是AWS的托管Web Application Firewall应用防火墙。WAF支持设置OSI网络模型七层的规则,包括对HTTP/HTTPS请求的URI/Header等信息进行检查。通过WAF实施IP地址检查规则,并将WAF绑定到API Gateway上,简单方便,不影响当前API Gateway的开发、部署。WAF优先于所有API Gateway策略,在网络层生效。因此WAF配置的规则,优先于API Gateway的Resource Policy中配置的IP Condition规则。
本例配置中,会将来自本地的IP加入白名单,并拒绝除本地之外的所有IP请求。
二、使用WAF保护API Gateway
1、验证API Gateway访问从互联网访问正常
首先进入API Gateway界面,从向导创建一个默认的petstore
的演示用API接口。这个接口默认不带身份验证,默认类型为regional
也就是当前AWS区域级别可以访问,有外网入口。创建完毕后,执行部署,生成一个新的Stage
。
进入Stages
界面,可以看到接口信息如下截图。

在这个界面中,可以看到新创建的API接口,以及支持调用的方法。如图中支持GET和POST。接下来将接口复制下来,用curl命令校验下接口能否正常访问。如下截图。

可看到API Gateway接口访问正常。
2、在WAF中创建IP sets地址集
在`Stages
界面,点击右侧的WAF菜单位置的Create Web ACL
链接。如下截图。

进入WAF界面后,请注意WAF的控制台是全局的,右上角显示Region的界面会显示为Global
。在AWS中国区,这个Global
的意思是北京region和宁夏region统一管理。在海外区,这个Global
的意思是全球所有region。这里不用担心,后续创建ACL时候会再次选择正确的region。
此时先不要着急点击创建按钮,而是先要创建IP地址集(IP sets)。点击页面左侧菜单的IP sets
。如下截图。

在IP地址集页面上,选择正确的区域。WAF管理控制台虽然是全局的,但是设置规则是regional级别的,因此把IP地址集要设定到正确的区域。本例中为宁夏区域。如下截图。

输入IP地址集的信息,包括名称、描述,确认region的正确。如果有多个地址段,在文本框内每行输一个。然后点击Create IP set
按钮。如下截图。

显示绿色信息创建完成。如下截图。

3、创建Web ACL设置规则
在左侧菜单,点击Web ACLs按钮
,在页面右侧切换到正确的region,本例为宁夏区域。然后点击页面右侧的Create web ACL
按钮继续。如下截图。

在配置WAF规则向导第一步,输入名称,在Region
位置选择正确的区域(本例为宁夏),然后点击下方的Add Amazon Web Services resources
,将WAF和API Gateway绑定。如下截图。

在绑定云资源的对话框里边,选择Amazon API Gateway
,然后从资源清单中,选择本例创建的API Gateway的Stages
的名称。如果有多个API Gateway,或者一个API Gateway的接口有多个Stages
部署,那么这里也要选择多个不同的Stages
的名称,以实现保护。如果只选一个,那么意味着其他的Stages
部署不会被保护。选择好了之后,点击Add
按钮。如下截图。

绑定好了后,在资源清单中,能看到刚才选择的Stages
的名字了。现在点击Next
下一步。如下截图。

在向导第二步,Add rules and rule groups
界面,点击Add rules
,有两个选项,第一个选项是AWS托管规则,第二个是自定义规则。这里选择第二项Add my own rules and rule groups
。如下截图。

在自定义规则的界面上,将上方的Rule type
选择为IP set
类型,即IP规则。在Rule名称位置,输入一个平淡但是友好的名称作为规则名称。在IP set
位置,从下拉框中,选择本文前一个步骤自定义IP地址集时候设定的名称。在下方针对入站访问的来源,WAF支持可能是经过NAT等通道的场景,一般选择第一个选项针对网络层体现的最终IP。如果有特定的HTTP Header标记真实客户端IP,那么也可以选择第二个选项IP address in header
,并手工制定特定的Header名称。一般不需要调整这个选项,选择第一个Source IP address
即可。如下截图。

将页面向下滚动,将本条规则行为选为Allow
即允许通过。因为本例的配置是对特定IP白名单,拒绝其他所有IP,所以这里选择对本条IPAllow
放行。然后点击右下角的Add rule
。如下截图。

在添加完毕自定义规则后,页面返回了向导第二步,在页面上方已经看到刚才的规则被添加进来,且Action
行为的位置显示为Allow
。接下来,要将所有非这个来源IP的流量设置为拒绝。在下方Default web ACL action for requests that don't match any rules
位置,表示默认规则的处理,这里将Default action
选择为Block
拒绝访问。然后点击页面右下角的Next
下一步按钮。

在向导第三步,设置多条规则的优先级。如果有多个防护规则,一般建议将网络层IP拒绝的规则放在最上方第一条,以便有限屏蔽无关流量,减少总体扫描量。如果只有一条的话,可直接点击Next
下一步。如下截图。

在向导第四步,上方的下方的Amazon CloudWatch metrics
选项保持默认打开即可。在下方的Request sampling options
采样设置,选择Enable sampled requests
,这样在WAF规则Rule下方即可看到部分访问的采样,同时包括允许和拒绝的信息。最后点击Next
按钮下一步继续。如下截图。

向导最后一步Review,无需调整任何设置,直接将页面卷动到最下方,点击Create web ACL
按钮。如下截图。

显示绿色的则表示创建WAF ACL完成。如下截图。

4、验证WAF工作
首先从本地网络(也就是被授权Allow放行)的位置发起访问,可看到访问正常。
接下来更换到其他的网络环境,对刚才被保护的URL发起访问。可看到返回报错信息。
[root@ip-172-31-16-68 ~]# curl https://038iiposid.execute-api.cn-northwest-1.amazonaws.com.cn/prod-v1/pets
{"message":"Forbidden"}
[root@ip-172-31-16-68 ~]#
现在回到WAF服务界面,来到Web ACLs
菜单,点击刚才新创建的ACL,点击Overview
标签页。然后向下卷动页面。如下截图。

在页面下方的Sampled requests
位置可以看到最近的访问记录取样,可查看其中列出的允许的规则和拒绝的规则都与预期一致。

至此配置完成。