Y_Yamashitaのブログ

勉強したことのアウトプット・メモ中心。たまに日記とか。

「AWSの基礎を学ぼう 特別編 最新サービスをみんなで触ってみる - Amazon Route 53 Resolver DNS Firewall」をJAWS-UG CLI支部チックにやってみた

はじめに

先日の7/31(土)に以下のハンズオンに参加しました。

awsbasics.connpass.com

今回は、ハンズオン当日にGUIで実施したDNS Firewallの設定を、CLIで実施してみたいと思います。
また、最近JAWS-UG CLI支部のハンズオンにちょくちょく参加するようになったので、折角なのでそちらで学習したお作法やコマンドを意識しながらやってみたいと思います。

JAWS-UG CLI支部についてはこちらをご参照ください。CLI手順だけでなく、サービスの特徴や運用の勘所なども学べて、とても勉強になります。

jawsug-cli.connpass.com



今回のハンズオンの内容と手順

今回のハンズオンの内容や手順については、以下にまとめられているのでこちらを参照ください。

dev.classmethod.jp

今回は、上記手順の「3. DNS Firewall 設定」と「4. 動作確認」をCLIで実施していきます。

CLIでの手順

それでは、CLIでの手順を実際に見ていきます。CLIで実施する場合、マネジメントコンソールでの手順と一部順番が変わるので、その辺も確認しながらやっていきます。

0.動作環境と使用コマンド

今回は、以下の動作環境で作業を実施しました。

YuY:~/environment $ aws --version
aws-cli/1.19.112 Python/2.7.18 Linux/4.14.238-182.422.amzn2.x86_64 botocore/1.20.112
YuY:~/environment $ 



DNS Firewallの設定は、route53resolverコマンドで実施します。コマンドの詳細は以下を参照してください。

route53resolver — AWS CLI 1.20.11 Command Reference

なお、CLIバージョン2では、バージョン1で使用可能だったサブコマンドがいくつか無くなっているようで、以下の手順は実行できませんでした。詳細は後述します。

1.事前のDNSクエリ確認

まずは事前のDNSクエリ確認を実施します。ハンズオン手順の「Step 2-3」に該当する箇所です。

YuY:~/environment $ dig example.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35625
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       93.184.216.34

;; Query time: 2 msec
;; SERVER: 10.1.0.2#53(10.1.0.2)
;; WHEN: Sun Aug 01 08:13:09 UTC 2021
;; MSG SIZE  rcvd: 56

YuY:~/environment $ 

example.comのAレコードが返ってきていることが確認できます。

2.DNS Firewall ルールグループ作成

さて、いよいよここから本題のDNS Firewall設定です。まずはDNS Firewallのルールグループを作成します。

# ルールグループ名を定義
YuY:~/environment $ FW_RULE_GR_NAME='handson0731-gr'
YuY:~/environment $ 

# ルールグループを作成
YuY:~/environment $ aws route53resolver create-firewall-rule-group \
>     --name ${FW_RULE_GR_NAME}
{
    "FirewallRuleGroup": {
        "Status": "COMPLETE", 
        "Name": "handson0731-gr", 
        "CreationTime": "2021-08-01T08:44:58.245974Z", 
        "CreatorRequestId": "988bb4be-db45-419a-869e-e8624732a249", 
        "ModificationTime": "2021-08-01T08:44:58.245974Z", 
        "ShareStatus": "NOT_SHARED", 
        "Arn": "arn:aws:route53resolver:ap-northeast-1:XXXXXXXXXXXX:firewall-rule-group/rslvr-frg-3f7127xxxxxxxxxx", 
        "RuleCount": 0, 
        "OwnerId": "XXXXXXXXXXXX", 
        "Id": "rslvr-frg-3f7127xxxxxxxxxx", 
        "StatusMessage": "Created Firewall Rule Group"
    }
}
YuY:~/environment $ 

# ルールグループIDの取得
YuY:~/environment $ FW_RULE_GR_ID=$( \
> aws route53resolver list-firewall-rule-groups \
> --query FirewallRuleGroups[?Name==\`${FW_RULE_GR_NAME}\`].Id \
> --output text \
> ) \
> && echo ${FW_RULE_GR_ID}
rslvr-frg-3f7127xxxxxxxxxx
YuY:~/environment $ 

ルールグループIDを取得する理由は、この後のコマンドで引数として必要になるためです。

3.ドメインリスト作成

続いて、フィルタリングルールを作る前に、先にドメインリストの作成を実施します。CLIの場合、フィルタリングルールの作成時にドメインリストIDを指定する必要があるためです。

# ドメインリスト名を定義
YuY:~/environment $ DOMAIN_LIST_NAME='example-list'
YuY:~/environment $ 

# ドメインリストを作成
YuY:~/environment $ aws route53resolver create-firewall-domain-list \
> --name ${DOMAIN_LIST_NAME}
{
    "FirewallDomainList": {
        "Status": "COMPLETE", 
        "Name": "example-list", 
        "CreationTime": "2021-08-01T09:21:15.074053Z", 
        "CreatorRequestId": "4698e450-6c16-4115-8e38-eed0efb99e78", 
        "ModificationTime": "2021-08-01T09:21:15.074053Z", 
        "Arn": "arn:aws:route53resolver:ap-northeast-1:XXXXXXXXXXXX:firewall-domain-list/rslvr-fdl-7a6d3xxxxxxxxxx", 
        "DomainCount": 0, 
        "Id": "rslvr-fdl-7a6d3xxxxxxxxxx", 
        "StatusMessage": "Created Firewall Domain List"
    }
}
YuY:~/environment $

# ドメインリストIDの取得
YuY:~/environment $ FW_DOMAIN_LIST_ID=$( \
> aws route53resolver list-firewall-domain-lists \
> --query "FirewallDomainLists[?Name==\`${DOMAIN_LIST_NAME}\`].Id" \
> --output text \
> ) \
> && echo ${FW_DOMAIN_LIST_ID}
rslvr-fdl-7a6d3xxxxxxxxxx
YuY:~/environment $ 

ドメインリストIDも、ルールグループID同様、この後のコマンドで引数として必要となります。

4.ドメインリストへのドメインの追加

続いて、ドメインリストにドメインexample.com」を追加します。

# ドメインの定義
YuY:~/environment $ FW_DOMAIN='example.com'
YuY:~/environment $

# ドメインリストへのドメインの追加 
YuY:~/environment $ aws route53resolver update-firewall-domains \
> --firewall-domain-list-id ${FW_DOMAIN_LIST_ID} \
> --operation ADD \
> --domains ${FW_DOMAIN}
{
    "Status": "COMPLETE", 
    "Id": "rslvr-fdl-7a6d3d4778xxxxx", 
    "StatusMessage": "Created Firewall Domain List", 
    "Name": "example-list"
}
YuY:~/environment $ 

# ドメインの追加の確認
YuY:~/environment $ aws route53resolver list-firewall-domains \
> --firewall-domain-list-id ${FW_DOMAIN_LIST_ID} \
> --query "Domains[]" \
> --output text
example.com.
YuY:~/environment $ 



5.フィルタリングルール作成

続いて、フィルタリングルールを作成します。

# フィルタリングルール名を定義
YuY:~/environment $ FW_RULE_NAME='handson0731-rule'
YuY:~/environment $ 

# フィルタリングルールを設定
YuY:~/environment $ aws route53resolver create-firewall-rule \
> --name ${FW_RULE_NAME} \
> --firewall-rule-group-id ${FW_RULE_GR_ID} \
> --firewall-domain-list-id ${FW_DOMAIN_LIST_ID} \
> --action BLOCK \
> --block-response NODATA \
> --priority 1
{
    "FirewallRule": {
        "Name": "handson0731-rule", 
        "CreationTime": "2021-08-01T11:52:21.983902Z", 
        "CreatorRequestId": "7dfbada3-455a-420b-975a-5a4c489761a1", 
        "ModificationTime": "2021-08-01T11:52:21.983902Z", 
        "Priority": 1, 
        "BlockResponse": "NODATA", 
        "FirewallDomainListId": "rslvr-fdl-7a6d3xxxxxxxxxx", 
        "Action": "BLOCK", 
        "FirewallRuleGroupId": "rslvr-frg-3f7127xxxxxxxxxx"
    }
}
YuY:~/environment $ 



6.ルールグループにVPCを関連付け

続いて、ルールグループにVPCを関連付けます。関連付けにはVPC IDが必要なので、まずはVPC IDを取得します。

# VPC名の定義
YuY:~/environment $ FW_VPC_NAME='handson-dns-firewall-20210731-VPC'
YuY:~/environment $ 

# VPC IDの取得
YuY:~/environment $ FW_VPC_ID=$( \
> aws ec2 describe-tags --filter "Name=tag-value,Values=${FW_VPC_NAME}" \
> --query "Tags[].ResourceId" \
> --output text \
> ) \
> && echo ${FW_VPC_ID}
vpc-0808ed7xxxxxxxxxx
YuY:~/environment $ 

VPC名は、「{ハンズオン手順のStep1-2で入力したスタック名}-VPC」になっているかと思います。(ハンズオン手順では「handson0731」になっていますが、私は「handson-dns-firewall-20210731」と入力していたため、そちらを指定しています。)

VPC IDが取得できたら、ルールグループにVPCを関連付けます。

# 関連付け名の定義
YuY:~/environment $ FW_ASSOCIATE_NAME='handson-dns-firewall-20210731'
YuY:~/environment $ 

# 関連付け 
YuY:~/environment $ aws route53resolver associate-firewall-rule-group \
>     --firewall-rule-group-id ${FW_RULE_GR_ID} \
>     --vpc-id ${FW_VPC_ID} \
>     --priority 101 \
>     --name ${FW_ASSOCIATE_NAME}
{
    "FirewallRuleGroupAssociation": {
        "Status": "UPDATING", 
        "VpcId": "vpc-0808ed7xxxxxxxxxx", 
        "Name": "handson-dns-firewall-20210731", 
        "CreationTime": "2021-08-01T12:10:42.351432Z", 
        "MutationProtection": "DISABLED", 
        "CreatorRequestId": "3c68e290-da71-476e-bb26-7f108683b938", 
        "ModificationTime": "2021-08-01T12:10:42.351432Z", 
        "Priority": 101, 
        "StatusMessage": "Creating Firewall Rule Group Association", 
        "Id": "rslvr-frgassoc-7a0ba2xxxxxxxxxx", 
        "Arn": "arn:aws:route53resolver:ap-northeast-1:XXXXXXXXXXXX:firewall-rule-group-association/rslvr-frgassoc-7a0ba2xxxxxxxxxx", 
        "FirewallRuleGroupId": "rslvr-frg-3f7127xxxxxxxxxx"
    }
}
YuY:~/environment $ 

上記を見ると、Statusが"UPDATING"、StatusMessageが"Creating Firewall Rule Group Association"となっており、まだ関連付けが完了していないことが分かります。そのため、少し時間を置いてから、次の手順で再度StatusとStatusMessageを取得します。

7.ルールグループへのVPC関連付けの完了確認

再度StatusとStatusMessageを取得、関連付けが完了したことを確認します。

# 関連付けIDの取得
YuY:~/environment $ FW_ASSOCIATION_ID=$( \
> aws route53resolver list-firewall-rule-group-associations \
> --firewall-rule-group-id ${FW_RULE_GR_ID} \
> --query "FirewallRuleGroupAssociations[].Id" \
> --output text \
> ) \
> && echo ${FW_ASSOCIATION_ID}
rslvr-frgassoc-7a0ba2xxxxxxxxxx
YuY:~/environment $ 

# Status、StatusMessageの取得
YuY:~/environment $ aws route53resolver get-firewall-rule-group-association \
> --firewall-rule-group-association-id ${FW_ASSOCIATION_ID} \
> --query "FirewallRuleGroupAssociation.[Status, StatusMessage]" \
> --output text
COMPLETE        Finished rule group association update
YuY:~/environment $ 

Statusが「COMPLETE」、StatusMessageが「Finished rule group association update」に変わりました。

8.動作確認

DNS Firewallの設定が一通り終わったので、改めて動作確認します。ハンズオン手順の「4.動作確認」の部分です。

YuY:~/environment $ dig example.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1611
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      A

;; Query time: 3 msec
;; SERVER: 10.1.0.2#53(10.1.0.2)
;; WHEN: Sun Aug 01 12:26:30 UTC 2021
;; MSG SIZE  rcvd: 40

YuY:~/environment $ 
YuY:~/environment $ 
YuY:~/environment $ 
YuY:~/environment $ dig example.com @8.8.8.8

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> example.com @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14379
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            20694   IN      A       93.184.216.34

;; Query time: 3 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Aug 01 12:27:02 UTC 2021
;; MSG SIZE  rcvd: 56

YuY:~/environment $ 

ハンズオン手順と同じ結果になりました。どうやら問題なくDNS Firewallの設定が出来たようです。

補足:CLIバージョン1とバージョン2の差異について

冒頭にも記載した通り、今回のCLI手順はCLIバージョン1での手順となります。CLIバージョン2では「create-firewall-rule-group」等のサブコマンドが使えないらしく、同じ手順を実行することが出来ませんでした。

以下に、バージョン1とバージョン2で使用できるサブコマンドの差分を記載します。※マイナーバージョンの違いでも差分が出るかもしれないので、一例として見てください。

# aws cliバージョン1の場合
YuY:~/environment $ aws --version
aws-cli/1.19.112 Python/2.7.18 Linux/4.14.238-182.422.amzn2.x86_64 botocore/1.20.112
YuY:~/environment $ 
YuY:~/environment $ 
YuY:~/environment $ aws route53resolver 
associate-firewall-rule-group                 get-resolver-rule 
associate-resolver-endpoint-ip-address        get-resolver-rule-association 
associate-resolver-query-log-config           get-resolver-rule-policy 
associate-resolver-rule                       import-firewall-domains 
create-firewall-domain-list                   list-firewall-configs 
create-firewall-rule                          list-firewall-domain-lists 
create-firewall-rule-group                    list-firewall-domains 
create-resolver-endpoint                      list-firewall-rule-group-associations 
create-resolver-query-log-config              list-firewall-rule-groups 
create-resolver-rule                          list-firewall-rules 
delete-firewall-domain-list                   list-resolver-dnssec-configs 
delete-firewall-rule                          list-resolver-endpoint-ip-addresses 
delete-firewall-rule-group                    list-resolver-endpoints 
delete-resolver-endpoint                      list-resolver-query-log-config-associations 
delete-resolver-query-log-config              list-resolver-query-log-configs 
delete-resolver-rule                          list-resolver-rule-associations 
disassociate-firewall-rule-group              list-resolver-rules 
disassociate-resolver-endpoint-ip-address     list-tags-for-resource 
disassociate-resolver-query-log-config        put-firewall-rule-group-policy 
disassociate-resolver-rule                    put-resolver-query-log-config-policy 
get-firewall-config                           put-resolver-rule-policy 
get-firewall-domain-list                      tag-resource 
get-firewall-rule-group                       untag-resource 
get-firewall-rule-group-association           update-firewall-config 
get-firewall-rule-group-policy                update-firewall-domains 
get-resolver-dnssec-config                    update-firewall-rule 
get-resolver-endpoint                         update-firewall-rule-group-association 
get-resolver-query-log-config                 update-resolver-dnssec-config 
get-resolver-query-log-config-association     update-resolver-endpoint 
get-resolver-query-log-config-policy          update-resolver-rule
YuY:~/environment $ 



# aws cliバージョン2の場合
[cloudshell-user@ip-10-0-141-253 ~]$ aws --version
aws-cli/2.1.28 Python/3.8.8 Linux/4.14.225-168.357.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off
[cloudshell-user@ip-10-0-141-253 ~]$ 
[cloudshell-user@ip-10-0-141-253 ~]$ aws route53resolver 
associate-resolver-endpoint-ip-address       delete-resolver-query-log-config             get-resolver-query-log-config                list-resolver-endpoint-ip-addresses          put-resolver-query-log-config-policy
associate-resolver-query-log-config          delete-resolver-rule                         get-resolver-query-log-config-association    list-resolver-endpoints                      put-resolver-rule-policy
associate-resolver-rule                      disassociate-resolver-endpoint-ip-address    get-resolver-query-log-config-policy         list-resolver-query-log-config-associations  tag-resource
create-resolver-endpoint                     disassociate-resolver-query-log-config       get-resolver-rule                            list-resolver-query-log-configs              untag-resource
create-resolver-query-log-config             disassociate-resolver-rule                   get-resolver-rule-association                list-resolver-rule-associations              update-resolver-dnssec-config
create-resolver-rule                         get-resolver-dnssec-config                   get-resolver-rule-policy                     list-resolver-rules                          update-resolver-endpoint
delete-resolver-endpoint                     get-resolver-endpoint                        list-resolver-dnssec-configs                 list-tags-for-resource                       update-resolver-rule
[cloudshell-user@ip-10-0-141-253 ~]$ 

aws-cliバージョン2の場合に、DNS Firewallの設定をCLIでどのように実施すればよいのかは、少し調べてみただけではよく分かりませんでした。また機会がある時に調査したいと思います。

おわりに

というわけで、CLIDNS Firewallの設定をすることが出来ました。
手順書の内容をコピペするだけではなく、これまで勉強した事を活かしながら手探りでやって、結果的に上手くいったので良かったです。
ただ、ハンズオン手順の「5.DNSクエリログの記録」と「6.片付け」がまだ残っているため、今度はそちらもCLIで実施したいと思います。

追伸:今回、「JAWS-UG CLI支部チックにやる」と冒頭で記載しましたが、CLI支部では変数を定義した時には必ずヒアドキュメントで中身の確認をしているのに、今回は省略しちゃいました。この辺、まだまだ徹底が足りないですね。