S3 バケットに配置した PAC (プロキシ自動設定)ファイルを VPC 内の Windows インスタンスに適用してみた
コンバンハ、千葉(幸)です。
先日、PAC(Proxy Auto-Configuration)を S3 に格納し、それを外部から参照する構成を試してみました。
ここでは、「インターネット経由」で「Mac から」の参照でした。今回は、「 VPC エンドポイント経由」で「Windows インスタンスから」参照してみます。
「 PAC ファイルとはなんぞや」といった部分は上記のエントリをご参照ください。
今回の検証に使用する構成
以下のイメージです。
- VPC 内のクライアントから VPC エンドポイント経由で S3 内の PAC ファイルを参照する
- PAC ファイルでは以下が定義されている
- 接続先が
*.amazonaws.com
の場合は直接アクセスする - それ以外の場合はプロキシサーバを経由する
- 接続先が
- 当該 PAC ファイルを適用したクライアントから以下にアクセスし、送信元グローバル IP を確認
検証の簡便さのためにクライアントもパブリックサブネットに配置していますが、実際に運用する際にはプライベートサブネットに配置することになるでしょう。
また、プロキシサーバが同一サブネットにいるのも深い意味はありません。
前回のエントリと重複する部分も多いため、本エントリで主に確認を取りたいのは「 VPC エンドポイント経由のアクセスを許可する 」構成の取り方です。
やってみた
プロキシサーバの構築
前回のエントリで使用したものをそのまま流用します。
Amazon Linux2 で以下を実行しただけのシンプルなものです。
sudo yum install squid -y sudo systemctl enable squid sudo systemctl start squid
グローバル IP アドレスとして 18.xx.xx.xx を割り当てています。
PAC ファイルの作成
こちらも前回のものをほとんど流用します。
以下の内容で、sample_vpc.pac
という名称のファイルを作成しました。
function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".amazonaws.com")) { return "DIRECT"; } else { return "PROXY 192.168.xx.xx:3128; DIRECT"; } }
大まかに、以下のとおり機能します。
- 接続先がホスト名のみでドメインが付与されていない(
isPlainHostName(host)
)か、 - 接続先のドメインが .amazonaws.com (
dnsDomainIs(host, ".amazonaws.com")
)の場合、 - 直接アクセスする(
return "DIRECT";
)。 - それ以外の場合、指定のプロキシを経由する(
PROXY 192.168.xx.xx:3128;
)- (プロキシに接続できなければ直接アクセスする)
前回との差異は、プロキシサーバの指定をグローバル IP でなくプライベート IP としている点のみです。
実際に使用する際には、IAM ロールの使用に必要な169.254.169.254
をプロキシから除外するなど、諸々考慮が必要でしょう。
S3 への PAC ファイルの格納
今回はchibayuki-from-vpce
という名称のバケットを作成し、以下の設定としました。
- バケットのパブリックアクセスブロックをすべてオン
- バケットポリシーで「送信元が VPC エンドポイントであること」を条件とした上ですべてのプリンシパルを許可
- バケット ACL はデフォルト(所有者のみ読み書き可)
- オブジェクト ACL もデフォルト(所有者のみ読み書き可)
具体的なバケットポリシーは以下です。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::chibayuki-from-vpce/*", "Condition": { "StringEquals": { "aws:SourceVpce": [ "vpce-xxxxxxbbff6347e6f" ] } } } ] }
VPC エンドポイントは作成、設定済みであるとします。
暗号化の設定
上記のバケットに PAC ファイルを格納します。
前回のエントリでは特に言及していなかったのですが、オブジェクトの暗号化には考慮が必要です。
オブジェクトを暗号化すること自体は問題ありませんが、その場合にはSSE-S3
での暗号化を指定する必要があります。
KMS キーを使用した場合、そのキーに対するアクセス権を設定できないため、正常に内容を取得できません。( IAM ロールの権限を使用するでもなく、単純な https アクセスのため。)
KMS キーによる暗号化を行ったオブジェクトに curl で GET を試みると、以下のようなエラーが発生します。
<?xml version="1.0" encoding="UTF-8"?> <Error><Code>InvalidArgument</Code><Message>Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.</Message><ArgumentName>Authorization</ArgumentName><ArgumentValue>null</ArgumentValue><RequestId>D17B0DD26B42A2B8</RequestId><HostId>WcfE8PwA46yg/F7sEY3etLDx0ILv+lYbfrkAMTCxy+dl9c5Xv65uTH6PRzWsq7SFbCvqaNz0hW8=</HostId></Error>
クライアントサーバの構築
以下の AMI からパブリックサブネットに構築しました。
- Windows_Server-2019-Japanese-Full-Base-2021.01.13(ami-0822d4ee6dd7c901a)
OS 上の設定は特別なことは行いません。パブリック IP は 52.xx.xx.xx が採番されました。
この時点で、S3 上の PAC ファイルにアクセスできる状態です。
C:\Users\Administrator>curl https://chibayuki-from-vpce.s3-ap-northeast-1.amazonaws.com/sample_vpc.pac function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".amazonaws.com")) { return "DIRECT"; } else { return "PROXY 192.168.xx.xx:3128; DIRECT"; } }
余談ですが、以下のようなパス形式でもアクセス可能です。(上記の方式は仮想ホスト形式)
C:\Users\Administrator>curl https://s3-ap-northeast-1.amazonaws.com/chibayuki-from-vpce/sample_vpc.pac function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".amazonaws.com")) { return "DIRECT"; } else { return "PROXY 192.168.xx.xx:3128; DIRECT"; } }
パス形式でのアクセスが廃止されると 2019年に アナウンスがありましたが、2020年に延期が発表されています。
クライアントサーバから PAC ファイルの参照
クライアントサーバのインターネットプロパティから、「自動構成スクリプトを使用する」を選択し、「アドレス」に PAC ファイルのオブジェクト URL を指定します。
設定を保存したのち、 Internet Explorer から IP 確認サイトにアクセスします。
再掲すると、送信元グローバル IP は以下のとおりです。
- クライアントサーバ:52.xx.xx.xx
- プロキシサーバ:18.xx.xx.xx
checkip.amazonaws.com では、意図通りプロキシを経由せず直接アクセスが行われています。
アクセス情報【使用中のIPアドレス確認】では、こちらも意図通りプロキシを経由してアクセスを行っています。
正常に PAC ファイルが適用されていることが確認できました。
終わりに
VPC 内のサーバから S3 に格納した PAC ファイルを参照してみました。
S3 バケットポリシーを適切に設定すれば、これといった考慮をすることなくPAC ファイルの配布が行えることが分かりました。
VPC 内のサーバに共通したプロキシ設定を適用したい、という場合には使用をご検討ください。
以上、千葉(幸)がお送りしました。