Object Storage Service (OSS) は、DNS 名前解決によって提供される動的 IP アドレスを使用します。これにより、ファイアウォールのホワイトリストを設定したり、特定のシステム統合を実行したりする際に、アクセス制限や障害が発生する可能性があります。この問題を解決するには、固定パブリック IP アドレスを持つ Elastic Compute Service (ECS) インスタンスに Nginx リバースプロキシをデプロイします。プロキシはアクセスリクエストを OSS に転送し、固定 IP アドレスを使用して OSS リソースにアクセスできるようにします。
仕組み
このソリューションでは、固定パブリック IP アドレスを持つ 1 つ以上の ECS インスタンスをトラフィックの入口として使用します。Nginx はこれらのインスタンス上でリバースプロキシサーバーとして実行され、パブリックアクセスリクエストを OSS に転送します。ワークフローは次のとおりです。
クライアントは、ECS インスタンスの固定パブリック IP アドレス (EIP) を介して OSS リソースへのアクセスリクエストを開始します。
ECS インスタンス上の Nginx サービスがリクエストを受信して処理します。
設定に基づいて、Nginx はリクエストをターゲットの OSS バケットに転送します。
OSS はリクエストを処理し、応答データを Nginx に返します。
Nginx は応答データをインターネット経由でクライアントに送り返し、プロキシプロセスが完了します。
ECS リバースプロキシの設定
ステップ 1: ECS インスタンスの作成
ECS インスタンスは、Nginx リバースプロキシソフトウェアのランタイム環境として機能します。
次の設定で ECS インスタンスを作成します。他のパラメーターにはデフォルト設定を使用できます。
[課金方法] で、[従量課金] を選択します。
[リージョン]: ターゲット OSS バケットが配置されているリージョンを選択します。これにより、内部の同一リージョンエンドポイントを使用してトラフィックコストを節約できます。
[ネットワークとゾーン]: デフォルトの仮想プライベートクラウド (VPC) とゾーンを選択できます。
[インスタンス] で、[すべてのインスタンスタイプ] をクリックし、
ecs.e-c1m2.largeを検索して選択します。説明このインスタンスタイプが売り切れの場合は、別のインスタンスタイプを選択してください。
[イメージ] で、[パブリックイメージ] を選択し、次に [Alibaba Cloud Linux] (Alibaba Cloud Linux 3.2104 LTS 64 ビット) を選択します。
[システムディスク]: [ESSD Entry] ディスク容量を 40 GiB に設定します。
[パブリック IP アドレス] で、[パブリック IPv4 アドレスの割り当て] を選択します。
[帯域幅課金方法]: コストを節約するために [トラフィック量による課金] を選択できます。
[帯域幅]: 5 Mbps 以上の値を選択します。
[セキュリティグループ] で、[新しいセキュリティグループ] を選択します。[IPv4 ポート/プロトコルを開く] セクションで、[HTTP (TCP: 80)] を選択して Nginx リスナーポートを開きます。
[ログオン資格情報] で、[カスタムパスワード] を選択します。ログオン名を [root] に設定し、[ログオンパスワード] を設定します。
ステップ 2: Nginx リバースプロキシのインストールと設定
ECS インスタンスを作成した後、インスタンスに Nginx をインストールし、リバースプロキシルールを設定します。
Nginx サービスをインストールします。
yum install -y nginx設定ファイルを作成して編集します。管理を容易にするために、
/etc/nginx/conf.d/ディレクトリにoss_proxy.confなどの別の設定ファイルを作成します。vi /etc/nginx/conf.d/oss_proxy.conf次の本番グレードの設定テンプレートを設定ファイルにコピーします。次に、テンプレートのコメントに基づいて、バケットの内部の同一リージョンエンドポイントと ECS インスタンスのパブリック IP アドレスを変更します。
# OSS バックエンドを定義し、持続的接続を有効にしてパフォーマンスを向上させます。 upstream oss_backend { # [必須] バケットの内部の同一リージョンエンドポイントに置き換えます。 server your-bucket.oss-cn-hangzhou-internal.aliyuncs.com:80; # 推奨されるキープアライブ接続数。同時接続数に基づいてこの値を調整します。 keepalive 64; } # 本番環境のログ形式を定義します。この形式には、アップストリームの応答時間などの主要な情報が含まれます。 log_format production '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; server { listen 80; # [必須] ECS インスタンスのパブリック IP アドレスまたはこの IP アドレスに解決されるドメイン名に置き換えます。 server_name your_ecs_public_ip_or_domain; # アクセスログのパスとフォーマット。 access_log /var/log/nginx/oss_proxy.access.log production; error_log /var/log/nginx/oss_proxy.error.log; # 動的 DNS 名前解決。これにより、Nginx は OSS バックエンドの IP アドレスの変更を認識できます。 resolver 100.100.2.136 100.100.2.138 valid=60s; # Server Load Balancer または監視システムのヘルスチェックエンドポイント。 location /health { access_log off; return 200 "healthy"; } location / { # リクエストをアップストリームの OSS バックエンドにプロキシします。 proxy_pass http://oss_backend; # 主要な設定: HTTP/1.1 と持続的接続が有効になっていることを確認します。 proxy_http_version 1.1; proxy_set_header Connection ""; # 主要な設定: 署名検証がパスするように、Host ヘッダーを OSS バケットの内部の同一リージョンエンドポイントに設定します。 # [必須] バケットの内部の同一リージョンエンドポイントに置き換えます。 proxy_set_header Host "your-bucket.oss-cn-hangzhou-internal.aliyuncs.com"; # クライアントの送信元 IP アドレスを転送します。 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; # プロキシのタイムアウト期間を設定します。 proxy_connect_timeout 10s; proxy_send_timeout 30s; proxy_read_timeout 30s; # アップロードできるファイルの最大サイズ。値 0 は制限がないことを示します。必要に応じてこのパラメーターを設定します。 client_max_body_size 1024m; } }設定が正しいことを確認したら、ファイルを保存してエディターを終了します。
Nginx 設定ファイルの構文を確認します。
nginx -tsyntax is okとtest is successfulが表示された場合、設定構文は正しいです。Nginx サービスを開始して設定を適用します。
systemctl start nginx
リバースプロキシの検証
バケットのアクセス権限に基づいて検証方法を選択します。
公開読み取りおよび公開読み書きバケット
ブラウザで、URL http://ecs_public_ip/object_path を使用して OSS のオブジェクトにアクセスします。ecs_public_ip を ECS インスタンスのパブリック IP アドレスに置き換えます。これは ECS コンソールで確認できます。object_path をバケット内のオブジェクトのアクセスパスに置き換えます。たとえば、ファイル dest.jpg がバケットの exampledir ディレクトリに保存されている場合、object_path は exampledir/dest.jpg です。次の図は、成功したアクセス試行を示しています。

非公開バケット
アクセスしたいバケットが非公開の場合、アクセス URL には署名情報を含める必要があります。次の手順では、コンソールからファイルの署名付き URL を取得する方法について説明します。署名とその生成方法の詳細については、「署名バージョン 4 (推奨)」をご参照ください。
[バケット] ページに移動し、ターゲットバケットをクリックします。
アクセスしたいファイルについて、[アクション] 列の [詳細] をクリックします。
[ファイル URL のコピー] をクリックします。URL で、https を http に、バケットドメイン名を ECS インスタンスのパブリック IP アドレスに置き換えます。
ブラウザで変更した URL にアクセスします。

本番環境での適用
このソリューションを本番環境で使用する場合は、サービスの安定性、セキュリティ、および費用対効果を確保するために、これらのベストプラクティスに従ってください。
ベストプラクティス
高可用性アーキテクチャ: 単一障害点を防ぐために、Server Load Balancer とマルチゾーンデプロイメントの ECS インスタンスで構成される本番アーキテクチャを使用します。
HTTPS の有効化: 本番環境では、データ転送のセキュリティを確保するために HTTPS アクセスを強制します。Nginx に SSL 証明書を設定し、HTTP から HTTPS への自動リダイレクトを設定する必要があります。次のコードは設定方法を示しています。
説明HTTPS サービスにアクセスできるようにするには、ECS インスタンスが属するセキュリティグループでポート 443 を開く必要があります。詳細については、「セキュリティグループルールの追加、変更、または削除」をご参照ください。
# ... upstream と log_format の設定は変更されません ... # HTTP サーバーブロック: HTTPS へのリダイレクトを強制します。 server { listen 80; # [必須] ECS インスタンスのパブリック IP アドレスまたはこの IP アドレスに解決されるドメイン名に置き換えます。 server_name your_ecs_public_ip_or_domain; # すべての HTTP リクエストを HTTP 301 ステータスコードを使用して HTTPS にリダイレクトします。 return 301 https://$host$request_uri; } # HTTPS サーバーブロック: 実際のリクエストサービスを処理します。 server { # ポート 443 で SSL 接続をリッスンします。 listen 443 ssl http2; # [必須] ECS インスタンスのパブリック IP アドレスまたはこの IP アドレスに解決されるドメイン名に置き換えます。 server_name your_ecs_public_ip_or_domain; # --- SSL 証明書の設定 --- # [必須] SSL 証明書と秘密鍵ファイルへのパスに置き換えます。 ssl_certificate /path/to/your/fullchain.pem; ssl_certificate_key /path/to/your/private.key; # --- SSL セキュリティ強化設定 --- ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # アクセスログのパスとフォーマット。 access_log /var/log/nginx/oss_proxy.access.log production; error_log /var/log/nginx/oss_proxy.error.log; # 動的 DNS 名前解決 (元の設定と同じ)。 resolver 100.100.2.136 100.100.2.138 valid=60s; # ヘルスチェックエンドポイント (元の設定と同じ)。 location /health { access_log off; return 200 "healthy"; } location / { # ... すべての proxy_* 設定は元の設定と同じです ... proxy_pass http://oss_backend; proxy_http_version 1.1; proxy_set_header Connection ""; # [必須] バケットの内部の同一リージョンエンドポイントに置き換えます。 proxy_set_header Host "your-bucket.oss-cn-hangzhou-internal.aliyuncs.com"; proxy_set_header X-Forwarded-For $proxy_add_x_forw_for; proxy_set_header X-Real-IP $remote_addr; # X-Forwarded-Proto ヘッダーを追加して、クライアントが HTTPS 経由でサービスにアクセスしていることをバックエンドに通知します。 proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 10s; proxy_send_timeout 30s; proxy_read_timeout 30s; client_max_body_size 1024m; } }プロキシバッファーの設定: 大きなファイルのダウンロードやアップロードを伴うシナリオでは、プロキシバッファーを有効にして適切に設定します。これにより、サーバーのメモリ使用量が最適化され、低速なクライアントがバックエンドの OSS への接続を長時間占有するのを防ぎ、全体的なサービスパフォーマンスが向上します。location ブロックに次の設定を追加できます。
location / { # ... その他の proxy_* 設定 ... # プロキシバッファリングを有効にし、バッファーの数とサイズを設定します。 proxy_buffering on; proxy_buffers 8 128k; proxy_buffer_size 128k; proxy_busy_buffers_size 256k; }EIP の使用: プロキシクラスターの入口 (SLB インスタンスまたは ECS インスタンス) に Elastic IP アドレス (EIP) を関連付けて、入口の安定した IP アドレスを確保します。
アクセスにドメイン名を使用する: ドメイン名解決を設定して、プロキシサーバーの IP アドレスを指すようにします。IP アドレスの代わりにドメイン名を使用してサービスを提供します。これにより、将来の運用管理とスケーリングが簡素化されます。
フォールトトレランス戦略
ヘルスチェック: Server Load Balancer を設定して、Nginx の
/healthエンドポイントで定期的なヘルスチェックを実行し、障害のあるインスタンスを自動的に分離します。タイムアウト設定: バックエンド OSS からの応答遅延によって引き起こされる多数の積み上げ接続を防ぐために、
proxy_connect_timeoutやproxy_read_timeoutなどの Nginx タイムアウトパラメーターを適切に設定します。リトライメカニズム: クライアントアプリケーションがリトライをサポートしている場合は、アプリケーション層で 5xx エラーのリトライロジックを追加します。
リスク防止
セキュリティ強化: ECS セキュリティグループとネットワーク ACL で、必要な IP アドレスとポートにのみアクセス権限を付与します。一般的な Web 攻撃から防御するために、プロキシのフロントエンドに Web Application Firewall (WAF) をデプロイすることを検討してください。
監視とアラート: Nginx のアクセスログとエラーログ、およびリクエストの遅延、エラー率、ECS インスタンスの CPU、メモリ、ネットワーク使用量などの主要なパフォーマンスメトリックを監視します。必要に応じて、これらのメトリックにアラートのしきい値を設定します。
変更とロールバックの管理: Nginx 設定への変更を徹底的にテストおよび検証します。問題が発生した場合に迅速にロールバックできるように、設定ファイルの履歴バージョンを保持します。
よくある質問
ブラウザでバケット内の画像や Web ファイルをプレビューするにはどうすればよいですか?
OSS のセキュリティメカニズムのため、ブラウザからデフォルトのドメイン名を使用して OSS の画像や Web ファイルにアクセスすると、ファイルはプレビューされずに強制的にダウンロードされます。これらのファイルをブラウザで直接プレビューするには、カスタムドメイン名をバケットにマッピングし、Nginx 設定でマッピングされたカスタムドメイン名を使用する必要があります。カスタムドメイン名のマッピング方法の詳細については、「カスタムドメイン名での OSS へのアクセス」をご参照ください。
非公開バケットにアクセスしたときに返される 403 Forbidden エラーをトラブルシューティングするにはどうすればよいですか?
403 エラーは通常、署名検証または権限設定に関連しています。次のようにエラーをトラブルシューティングできます。
Nginx 設定の確認:
proxy_set_header Host命令の値が、アクセスしたいバケットの内部の同一リージョンエンドポイントと完全に一致していることを確認します。これは、V4 署名検証を成功させるための重要な要素です。署名生成の確認: 署名付き URL の署名を計算するために使用される
Hostヘッダーが、Nginx 設定のHostヘッダーと同じであることを確認します。バケット権限の確認: バケットポリシーまたは RAM ポリシーが必要な権限を付与しているかどうかを確認します。
ECS ロール権限付与の確認: アプリケーションがインスタンス RAM ロールを使用して OSS にアクセスする場合、そのロールにターゲットバケットへのアクセスに必要な権限が付与されていることを確認します。
大きなファイルのアップロードに失敗し、413 Request Entity Too Large エラーが返された場合はどうすればよいですか?
このエラーは、アップロードされたファイルのサイズが Nginx のデフォルトの制限を超えたために発生します。Nginx 設定ファイルで、server または location ブロックの client_max_body_size の値を調整します。たとえば、client_max_body_size 2048m; と設定すると、最大 2 GB のファイルをアップロードできます。設定を変更した後、Nginx 設定を再読み込みして変更を有効にします。
アクセスが時々失敗し、Nginx ログに 502 Bad Gateway エラーが表示されるのはなぜですか?
502 エラーは、Nginx がバックエンド (OSS) から有効な応答を取得できないことを示します。考えられる原因は次のとおりです。
DNS 名前解決の問題: Nginx 設定に
resolver命令が含まれているかどうかを確認します。この命令がない場合、Nginx はキャッシュされた古い IP アドレスを使用して OSS にアクセスし続ける可能性があります。ネットワーク接続性: ECS インスタンスのセキュリティグループのアウトバウンドルールとネットワーク ACL 設定を確認し、ターゲットリージョンの OSS エンドポイントのポート 80 へのアクセスが許可されていることを確認します。
エンドポイント設定エラー:
proxy_passとproxy_set_header Hostで設定された OSS エンドポイントのスペルが正しく、有効であるかどうかを確認します。
単一の Nginx インスタンスを使用して複数の異なるバケットをプロキシするにはどうすればよいですか?
Nginx の map 命令を使用して、リクエストの Host ヘッダーに基づいて、プロキシするバックエンドバケットを動的に選択できます。
# /etc/nginx/conf.d/multi_oss_proxy.conf
# Host ヘッダーを OSS バケットの内部の同一リージョンエンドポイントに動的にマッピングします。
map $http_host $oss_backend_host {
# [必須] a.example.com を bucket-a の内部の同一リージョンエンドポイントにマッピングします。
"a.example.com" "bucket-a.oss-cn-hangzhou-internal.aliyuncs.com";
# [必須] b.example.com を bucket-b の内部の同一リージョンエンドポイントにマッピングします。
"b.example.com" "bucket-b.oss-cn-shenzhen-internal.aliyuncs.com";
# デフォルト値。このパラメーターは空のままにするか、デフォルトのバケットに設定できます。
default "";
}
server {
listen 80;
# 複数のドメイン名でリッスンします。
server_name a.example.com b.example.com;
# ... ログやリゾルバーなどのその他の設定 ...
location / {
# マッピング結果が空の場合、404 エラーが返されます。
if ($oss_backend_host = "") {
return 404;
}
# proxy_pass と Host ヘッダーを動的に設定します。
proxy_pass http://$oss_backend_host;
proxy_set_header Host $oss_backend_host;
# ... その他の proxy_* 設定 ...
}
}