Carpe Diem

備忘録

curlのresolvオプションで名前解決

背景

ドメイン移管の関係でCloudFrontのDNSレコードをDNSimpleからRoute53へ移そうとしていたのですが、完全な移管手続前にRoute53側のレコードでエッジサーバにちゃんとアクセスできるか確認する必要がありました。
digのNS指定を使えばエッジサーバのIPは確認できますが、CloudFrontを直IP指定でアクセスしても403が返るだけです。
そこでcurlresolvオプションを使うことで、IPを指定しつつドメイン名でアクセスするようにしました。

環境

手順

エッジサーバのIPを取得

まずCloudFrontのエッジサーバを見つけます。

$ dig awa.fm  @ns-1032.awsdns-01.org

; <<>> DiG 9.10.6 <<>> awa.fm @ns-1032.awsdns-01.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58104
;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 4, ADDITIONAL: 1
;; WARNING: recursion requested but not available

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

;; ANSWER SECTION:
awa.fm.           60  IN  A   13.35.40.94
awa.fm.           60  IN  A   13.35.40.90
awa.fm.           60  IN  A   13.35.40.89
awa.fm.           60  IN  A   13.35.40.9

;; AUTHORITY SECTION:
awa.fm.           172800  IN  NS  ns-1032.awsdns-01.org.
awa.fm.           172800  IN  NS  ns-2002.awsdns-58.co.uk.
awa.fm.           172800  IN  NS  ns-326.awsdns-40.com.
awa.fm.           172800  IN  NS  ns-690.awsdns-22.net.

CloudFrontはDNSプロトコルEDNS-Client-Subnet拡張によって、最も近いエッジロケーションにリクエストをルーティングします。

aws.typepad.com

なのでここで返ってくるIPは固定でなくdigする度に変わったりします。

resolvオプションでIP指定でリクエス

--resolveオプションは

--resolve ドメイン名:ポート:IP

というフォーマットで使用します。最初のドメイン名はサーバにこのドメインでアクセスしてますよ、という通知のための指定です。
背景で説明したようにCloudFrontは直IPでアクセスできないので、DNSレコードで設定したドメイン名を付けてリクエストを投げます。
ちなみにこれは以下のようにSNIの仕組みを検証する時にも活用できます。

dev.classmethod.jp

ではアクセスしてみましょう

$ curl --resolv awa.fm:443:13.35.40.94 -I https://awa.fm 
HTTP/2 200 
content-type: text/html; charset=utf-8
content-length: 32750
date: Sun, 24 Jun 2018 01:31:11 GMT
cache-control: max-age=0
last-modified: Thu, 31 May 2018 08:45:36 GMT
etag: "e6e1a0330d671a628f5fc60359c4e031"
server: AmazonS3
vary: Accept-Encoding
x-cache: RefreshHit from cloudfront
via: 1.1 51d604be742eb5ae4101b732c73a9dcd.cloudfront.net (CloudFront)
x-amz-cf-id: KequgKt8w0uM8mZSGMTX7GhNZexFTQ-j-wat3O5Dh3Ov6SblSA--9Q==

ちゃんと200が返ってきてリクエストが正常に処理されていることが分かります。またverboseオプションをつけると

$ curl --resolv awa.fm:443:13.35.40.94 -Iv https://awa.fm 
* Added awa.fm:443:13.35.40.94 to DNS cache
* Rebuilt URL to: https://awa.fm/
* Hostname awa.fm was found in DNS cache
*   Trying 13.35.40.94...
* TCP_NODELAY set
* Connected to awa.fm (13.35.40.94) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
...

Connected to awa.fm (13.35.40.94) port 443 (#0)とあるように、ちゃんと指定したIPへアクセスできていることが分かります。

まとめ

curlのresolvオプションを使うことで、IPを指定しつつドメイン名でアクセスできました。

ソース