プロキシに阻まれながらAWS CLIをEC2インスタンスから動かしたときの話


この記事の概要

プロキシがある環境下でAWS CLIをEC2インスタンスから使う方法を書きます。
その中でハマったポイントがあったのですが、ハマったことにより知見が深まったのでQiitaに投稿します。
主にAWS CLI周りの話とSquidの話となります。

使ったツール・プロダクト等は以下です。

  • Squid(Windows版)
  • AWS CLI
  • Direct Connect
  • IAM
  • EC2
  • S3(あまり本題には出てきませんが)

背景

弊社には他の多くの会社さんと同様、インターネットへ接続するためのプロキシ(通称「社内プロキシ」)が存在しています。
そんな弊社に所属する私は業務上の事情でAWS CLIでS3上の操作を行う必要が出てきました。
しかし、先日開発用端末を変えたことにより、その端末にAWS CLIがインストールされていないのです。
セキュリティの観点からアクセスキーは発行したくないし、端末にAWS CLIをインストールする以外の方法を検討しました。
そこで、IAMロールをEC2インスタンスにアタッチすることでアクセスキーを発行することなく認証させる方法を知っていたということもあり、この方法を採用しました。
しかも、AWSにはAWS CLIがプリインストールされたAmazon Linuxのイメージが公式で提供されており、これを使えば準備が楽そう…。
AWS CLIを使うには社内プロキシを突破してインターネットへ出る必要がありますが、まあSquidを活用した多段プロキシ構成で切り抜けれるだろうと思い作業を開始しました。

構成・通信の概略を示すと次の通りです。(あくまで概略です。)

AWS CLI自体にはそこそこ慣れているつもりで楽に準備ができるのではと思ったが、その思い上がり故に落とし穴に引っかかる私でありました…。

ハマりポイント その1 AWS CLIを使うにはno_proxy=169.254.169.254が必要

AWS CLIがプリインストールされたEC2インスタンスにIAMロールを付与して…。
インスタンスが起動したらプロキシ設定して…。

$ export http_proxy=http://(SquidのホストIP):(Squidで開けているport)
$ export https_proxy=http://(SquidのホストIP):(Squidで開けているport)
$ export no_proxy=localhost,127.0.0.1

いざaws s3 ls

$ aws s3 ls
Unable to locate credentials. You can configure credentials by running "aws configure".

ん?ちゃんとIAMロール付けてるんですが…。

$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key                <not set>             None    None
secret_key                <not set>             None    None
    region           ap-northeast-1      config-file    ~/.aws/config

一旦ターミナルを落として一呼吸。
もう一度AWS CLIの設定を確認。

$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ********************         iam-role    
secret_key     ********************         iam-role    
    region           ap-northeast-1      config-file    ~/.aws/config

ターミナルを落とした…、まさか!exportコマンドで環境変数をいじったことが影響しているのだろうか?

$ export hoge=fuga
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ********************         iam-role    
secret_key     ********************         iam-role    
    region           ap-northeast-1      config-file    ~/.aws/config

変わらない…。
ということはプロキシの影響か…、しかしAWS CLIってインターネットへの接続が必要だよな…。

調べてみたところ169.254.169.254へのアクセスをプロキシ経由で行わないように設定する必要があるようです。
唐突に謎のIPアドレスが出てきたぞ!?と思ったのですが、169.254.169.254へはインスタンスメタデータを取得するためにアクセスするらしいです。
インスタンスメタデータというのは、その動いているインスタンスに関するデータで、実行中のインスタンスを設定または管理するために使用されるものとのことでした。
そして、インスタンスメタデータへのアクセスはそのインスタンス内からのみアクセスが許可されているということだそうです。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

ということで、no_proxy設定を追加。

$ export no_proxy=localhost,127.0.0.1,169.254.169.254

ハマりポイント その2 SquidでSSL通信をするにはnever_direct allow CONNECTの設定が必要

今度こそaws s3 ls
…レスポンスが返ってこない。
curl http://www.google.comはレスポンスが返ってくる。
AWS CLIはhttps通信らしいので、
curl https://www.google.comを実行すると…、あれ?返ってこない。

Squidのログを見ると503で弾きましたというログが残っている…。
開けてるポートの問題か?もしかして社内プロキシに弾かれて503になっている?
色々想像しましたが、SquidのデフォルトではSSL通信を直接接続しようとするらしいです。

私のググり力が欠如しておりこの辺りの情報がやや少なく、この情報にたどり着くまで紆余曲折を経たのですが、結局この設定をSquidに入れれば解決でした。

squid.conf
never_direct allow CONNECT

結局どのような手順で設定するか

Windows端末にSquidをインストール

  • squid.diladele.comからWindows用インストーラをダウンロード・インストール

※Squid for Windowsはそれなりに実績もあり信頼はできるのですが、squid-cache.orgによる公式の提供はLinux版のみのようなので、あくまで自己責任でのご利用をお願いいたします。

  • Squidを起動
  • 右下のSquidのアイコンをクリックしてOpen Squid Configurationをクリック
  • 以下の設定を変更
squid.conf
(略)
# Squid normally listens to port 3128
http_port (競合しない任意のport番号) # ←わざわざ変えなくても結構ですが念の為
(略)
dns_nameservers (社内でご利用のDNSサーバのIPアドレス)
(略)
  • 以下の設定を末尾に追加
squid.conf
cache_peer (社外へ出るためのプロキシのホスト名もしくはIPアドレス) parent (社外へ出るためのプロキシのport番号) 0 no-query no-netdb-exchange no-digest login=(社外へ出るためのプロキシのID):(社外へ出るためのプロキシのPassword) default
cache deny all

never_direct allow all
never_direct allow CONNECT # ←今回のハマりポイント2
  • 設定ファイルを保存
  • 右下のSquidのアイコンをクリックしてStop Squid ServiceStart Squid Serviceで再起動

IAMロール付きEC2インスタンス作成

(簡易な記述ですみません…。)

  • EC2インスタンス用のIAMロールを適切なポリシーを付与して作成
  • AWS CLIがプリインストールされているイメージからEC2インスタンスを作成
  • EC2インスタンスにIAMロールをアタッチ

EC2インスタンス側での設定

  • EC2インスタンスにSSH接続
  • プロキシ設定を実施
$ export http_proxy=http://(SquidをインストールしたWindows端末のIP):(Squidで開けているport)
$ export https_proxy=http://(SquidをインストールしたWindows端末のIP):(Squidで開けているport)
$ export no_proxy=localhost,127.0.0.1,169.254.169.254 # ←今回のハマりポイント1

最後に

AWS CLIの話とSquidの話をしましたが、設定にしてみたらこんな少しの設定の話です。
でもそんな少しの設定でも色々な学びがあるんだなあと痛感しました。
あと、Squidは使い終わったらこまめにOFFにするようにしましょう。念の為。
気になったところやうまく行かない点などあれば是非コメント下さい。