[アップデート] Amazon CloudFront が VPC オリジンの WebSocket をサポートしました
CloudFrontのVPCオリジンを使ってパブリックサブネットを完全廃止したいけど、WebSocketを使いたいから完全廃止できない
こんにちは、のんピ(@non____97)です
皆さんはCloudFrontのVPCオリジンを使ってパブリックサブネットを完全廃止したいけど、WebSocketを使いたいから完全廃止できないとなったことはありますか? 私はあります。
CloudFrontのVPCオリジンを用いることによってGlobal Acceleratorを用いずにインターナルなALBやNLB、EC2インスタンスをCloudFrontのオリジンとして用いることができます。
これにより、オリジンに直接アクセスされる経路を排除することはもちろん、簡単に指定したCloudFrontディストリビューションとのみオリジンと通信できるようになったり、パブリックIPv4アドレスのコストを抑えることができるようになったりと嬉しいことは多くあります。
しかし、VPCオリジンGA当初、WebSocket通信はサポートされていませんでした。
そのため、オリジンにて一部パスはWebSocketを用いる場合、ALB/NLBなどオリジンとなるリソースをパブリックサブネットに配置する必要がありました。これは困ります。
今回、Amazon CloudFront が VPC オリジンの WebSocket をサポートしました。
これにより、WebSocketトラフィックを流すオリジンであってもパブリックサブネットで構成をすることができるようになりました。
実際に試してみました。
やってみた
検証環境
検証環境は以下のとおりです。

パブリックサブネットが存在しないVPCにおいて、ターゲットにWebSocketをおしゃべりするアプリケーションが動作しているECS Fargateに振り分けるインターナルALBをVPCオリジンとして指定します。
ちなみに、CloudFrontでWebSocketを使用する場合については以下AWS公式ドキュメントで言及されています。
全てのリソースはAWS CDKでデプロイしました
aws_cloudfront_originsというL2 Constructもあるので、非常にお手軽に実装できます。
使用したコードは以下GitHubリポジトリに保存しています。
リソース確認
作成されたリソースの確認です。
VPCのリソースマップを確認すると、IGWへのルートを持つルートテーブルが割り当てられたサブネット = パブリックサブネットが存在しないことが分かります。

VPCオリジンの設定は以下のとおりです。
「オリジンのWebSocket用に」という設定は特段ありません。


CloudFrontディストリビューション側のオリジン設定も同じくです。


動作確認
それでは動作確認です。
ブラウザで3つウィンドウを開き、さらにターミナルからもWebSocketで接続し、メッセージのやり取りをしました。

> pnpm dlx wscat -c wss://d1fhfqyui9h81a.cloudfront.net/websocket
Connected (press CTRL+C to quit)
< {"type":"welcome","id":"a83b55ae-92ba-4b01-8c0e-b4079569f24a","clientCount":4}
> こんにちは a83b55ae-92ba-4b01-8c0e-b4079569f24a です
< {"type":"echo","from":"a83b55ae-92ba-4b01-8c0e-b4079569f24a","message":"こんにちは a83b55ae-92ba-4b01-8c0e-b4079569f24a です"}
< {"type":"broadcast","from":"cdeed963-7774-4afb-a565-b9344ddfc327","message":"元気ですか?"}
特に問題なく、リアルタイムに投稿した文字列が各クライアントに反映されました。
また、最後にメッセージを投稿してからALBに設定した接続タイムアウト時間経過後、コネクションが切断されました。

一連の処理についてECS Fargateで動作しているアプリケーションが出力した一部ログは以下のとおりです。
{
"level": "info",
"time": "2026-05-25T13:02:54.569Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "11e254eb-5557-40ca-8832-3c37f5ed37ea",
"url": "/websocket",
"userAgent": "<ユーザーエージェント>",
"forwardedFor": "<クライアントのIPv6アドレス>, 130.176.119.40",
"cloudfrontId": "snx71Wifama59uLy3vfwcHaHwHmRrcVUi-e8vZtyU1FpHh069dBYQA==",
"clientCount": 1,
"msg": "ws connected"
}
{
"level": "info",
"time": "2026-05-25T13:03:08.958Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "cdeed963-7774-4afb-a565-b9344ddfc327",
"url": "/websocket",
"userAgent": "<ユーザーエージェント>",
"forwardedFor": "<クライアントのIPv6アドレス>, 130.176.116.164",
"cloudfrontId": "MraeHrTsMC2y5IHzWfDEVIKfI0tO2Pe47ev-C75yV822i2ANbcsmUw==",
"clientCount": 2,
"msg": "ws connected"
}
{
"level": "info",
"time": "2026-05-25T13:03:17.351Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "3c237116-9d54-4647-8e56-464c1025a9f5",
"url": "/websocket",
"userAgent": "<ユーザーエージェント>",
"forwardedFor": "<クライアントのIPv6アドレス>, 130.176.118.52",
"cloudfrontId": "WEHsZ_fwFs8GOmrQbrighqlVkRAaRtURlpeKO0a9QPbvly5e8Pjdbw==",
"clientCount": 3,
"msg": "ws connected"
}
{
"level": "info",
"time": "2026-05-25T13:03:46.975Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "11e254eb-5557-40ca-8832-3c37f5ed37ea",
"bytes": 31,
"isBinary": false,
"msg": "ws message received"
}
{
"level": "info",
"time": "2026-05-25T13:03:46.976Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "11e254eb-5557-40ca-8832-3c37f5ed37ea",
"broadcastCount": 2,
"msg": "ws message broadcasted"
}
{
"level": "info",
"time": "2026-05-25T13:04:04.623Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "cdeed963-7774-4afb-a565-b9344ddfc327",
"bytes": 31,
"isBinary": false,
"msg": "ws message received"
}
{
"level": "info",
"time": "2026-05-25T13:04:04.623Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "cdeed963-7774-4afb-a565-b9344ddfc327",
"broadcastCount": 2,
"msg": "ws message broadcasted"
}
{
"level": "info",
"time": "2026-05-25T13:08:50.946Z",
"pid": 6,
"hostname": "ip-10-10-8-174.ec2.internal",
"id": "71ca940a-8e32-4471-9938-9b9af4c18687",
"code": 1006,
"reason": "",
"clientCount": 0,
"msg": "ws closed"
}
また、接続時時に全てのヘッダーを出力するようにした場合は以下のようなログが出力されました。
{
"level": "info",
"time": "2026-05-25T13:42:28.172Z",
"pid": 8,
"hostname": "ip-10-10-8-98.ec2.internal",
"id": "4ddd7969-9270-4ff6-b7e5-eadb48066e43",
"method": "GET",
"httpVersion": "1.1",
"url": "/websocket",
"headers": {
"x-forwarded-for": "<クライアントのIPv6アドレス>, 130.176.114.52",
"x-forwarded-proto": "http",
"x-forwarded-port": "80",
"host": "d1fhfqyui9h81a.cloudfront.net",
"x-amzn-trace-id": "Root=1-6a1451c4-4e3233e1196d4b12222f32ce",
"upgrade": "websocket",
"connection": "upgrade",
"sec-websocket-key": "Rnhou3qbnI2nVKLvsTWapg==",
"sec-websocket-extensions": "permessage-deflate; client_max_window_bits",
"cache-control": "no-cache",
"pragma": "no-cache",
"user-agent": "<ユーザーエージェント>",
"via": "1.1 ece5d4a731ece5ff46c564ab2b946ede.cloudfront.net (CloudFront)",
"x-amz-cf-id": "3QinF8qURdlfjvILoXcZZqalpUXpxOCEI4nLyjxNpODDTK1thF1D7w==",
"sec-websocket-version": "13",
"origin": "https://d1fhfqyui9h81a.cloudfront.net",
"accept-language": "ja,en-US;q=0.9,en;q=0.8",
"accept-encoding": "gzip, deflate, br, zstd"
},
"remoteAddress": "10.10.8.96",
"remotePort": 10026,
"remoteFamily": "IPv4",
"clientCount": 1,
"msg": "ws connected"
}
X-Forwarding-Forヘッダーの130.176.114.52はCloudFrontのオリジンのIPアドレスです。
> whois 130.176.114.52
% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object
refer: whois.arin.net
inetnum: 130.0.0.0 - 130.255.255.255
organisation: Administered by ARIN
status: LEGACY
whois: whois.arin.net
changed: 1993-05
source: IANA
# whois.arin.net
NetRange: 130.175.0.0 - 130.176.255.255
CIDR: 130.176.0.0/16, 130.175.0.0/16
NetName: AMAZO-4
NetHandle: NET-130-175-0-0-1
Parent: NET130 (NET-130-0-0-0-0)
NetType: Direct Allocation
OriginAS:
Organization: Amazon.com, Inc. (AMAZO-4)
RegDate: 2021-01-28
Updated: 2022-06-22
Ref: https://rdap.arin.net/registry/ip/130.175.0.0
OrgName: Amazon.com, Inc.
OrgId: AMAZO-4
Address: Amazon Web Services, Inc.
Address: P.O. Box 81226
City: Seattle
StateProv: WA
PostalCode: 98108-1226
Country: US
RegDate: 2005-09-29
Updated: 2026-04-17
Comment: For details of this service please see
Comment: http://ec2.amazonaws.com
Ref: https://rdap.arin.net/registry/entity/AMAZO-4
OrgRoutingHandle: IPROU3-ARIN
OrgRoutingName: IP Routing
OrgRoutingPhone: +1-206-555-0000
OrgRoutingEmail: aws-routing-poc@amazon.com
OrgRoutingRef: https://rdap.arin.net/registry/entity/IPROU3-ARIN
OrgNOCHandle: AANO1-ARIN
OrgNOCName: Amazon AWS Network Operations
OrgNOCPhone: +1-206-555-0000
OrgNOCEmail: amzn-noc-contact@amazon.com
OrgNOCRef: https://rdap.arin.net/registry/entity/AANO1-ARIN
OrgRoutingHandle: ARMP-ARIN
OrgRoutingName: AWS RPKI Management POC
OrgRoutingPhone: +1-206-555-0000
OrgRoutingEmail: aws-rpki-routing-poc@amazon.com
OrgRoutingRef: https://rdap.arin.net/registry/entity/ARMP-ARIN
OrgDNSHandle: DNS1131-ARIN
OrgDNSName: DNS
OrgDNSPhone: +1-202-555-0000
OrgDNSEmail: ipmanagement+dns@amazon.com
OrgDNSRef: https://rdap.arin.net/registry/entity/DNS1131-ARIN
OrgAbuseHandle: AEA8-ARIN
OrgAbuseName: Amazon EC2 Abuse
OrgAbusePhone: +1-206-555-0000
OrgAbuseEmail: trustandsafety@support.aws.com
OrgAbuseRef: https://rdap.arin.net/registry/entity/AEA8-ARIN
OrgTechHandle: ANO24-ARIN
OrgTechName: Amazon EC2 Network Operations
OrgTechPhone: +1-206-555-0000
OrgTechEmail: amzn-noc-contact@amazon.com
OrgTechRef: https://rdap.arin.net/registry/entity/ANO24-ARIN
CloudFrontのVPCオリジンがWebSocketをサポートしたことで、WebSocketを扱う場合でもパブリックサブネットを完全に廃止できるようになった
CloudFront が VPC オリジンの WebSocket をサポートしたアップデートを紹介しました。
CloudFrontのVPCオリジンがWebSocketをサポートしたことで、WebSocketを扱う場合でもパブリックサブネットを完全に廃止できるようになりました。
コスト的にもセキュリティ的にもパブリックサブネットを廃止できるなら廃止したいところです。もし、WebSocket利用をしているがためにVPCオリジンを採用できなかった場合は今一度検討してみましょう。
AWS BlogsにパブリックオリジンからVPCオリジンに移行するステップを紹介した記事も参考になるかと思います。
推奨は以下記事でも紹介されているCloudFrontの継続的デプロイを用いる方式のようです。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!







