アプリ用バックエンド開発の効率を上げる、プロキシ環境
はじめに
モバイルアプリやフロントエンドの開発において、こんな悩みはありませんか?
- 「特定のAPI通信だけを踏み台サーバー経由にしたい(VPNだと全通信が重くなる)」
- 「本番/検証ドメイン (
api.example.com) の向き先を、アプリをリビルドせずに手元のローカルサーバーに向けたい」 - 「でも HTTPS (SSL) のエラーが出るので、結局サーバーにデプロイして確認している...」
- 「
/etc/hostsを汚したくない」
この記事では、SSHの標準機能 と PAC (Proxy Auto-Config)、そして 正規のSSL証明書 を組み合わせることで、これらの悩みを解決する「最強の試行錯誤環境」の構築手順をまとめます。
デプロイ待ち時間ゼロで、手元のコードを書き換えるだけで本番相当のドメインでの動作確認が可能になります。
構成の概要
PC(Mac/Windows/Linux)を踏み台サーバーにSSH接続し、以下の経路を作ります。
- SOCKS Proxy: 特定の通信だけをSSHトンネルに流す。
- Custom DNS: 特定ドメインの解決を制御する(DNS Spoofing)。
- Local HTTPS Server: 本物(または検証用)の証明書を使い、ローカルでAPIを騙る。
(※イメージ: クライアントPCが中心となり、SSHトンネルを通してDNSとプロキシを制御します)
登場人物とポート設定
| 役割 | Local Port | Remote Port | 説明 |
|---|---|---|---|
| SOCKS Proxy | 11080 |
- | SSH -D で作成。通信の出口。 |
| HTTP Server | 3080 |
3080 |
PACファイルを配布するPythonサーバー。 |
| DNS Server | 53 |
3053 |
カスタムDNSサーバー。 |
1. サーバー側 (Bastion Host) の準備
踏み台サーバー(以下 bastion-host)上で、DNSとPAC配布サーバーを準備します。
1-1. PACファイルの作成
プロキシのルールを記述した socks.pac を作成します。
ここでのポイントは、SOCKSプロキシの宛先に クライアントPC(あなたのマシン)のLAN内IPアドレス を指定することです。
※スマホ等の実機から接続するため、localhost ではなく実IPが必要です。
function FindProxyForURL(url, host) {
// 例: 特定ドメインのみSOCKS経由にする場合
// if (shExpMatch(host, "*.example.com")) {
// return "SOCKS 192.168.1.10:11080";
// }
// 今回はシンプルに全通信をSOCKSへ
// ※ 192.168.1.10 は あなたのPCのIPアドレス に書き換えてください
return "SOCKS 192.168.1.10:11080;";
}
1-2. サーバーの起動
Pythonと dnserver を使用します。
# 1. PAC配布サーバー (3080番)
# -d でPACファイルのディレクトリを指定
python -m http.server -d /path/to/socks.pac-dir 3080 &
# 2. DNSサーバー (3053番)
# 設定ファイル zones.toml は対象ドメインをPCのIPに向けるよう記述
# /usr/local/dnserver/bin/dnserver --port 3053 /usr/local/dnserver/etc/zones.toml &
2. クライアント側からの接続
SSHコマンド一発でトンネルを構築します。
スマホなど外部からの接続を受け付けるため -g (Gateway Ports) を付与します。
# 踏み台へ接続 (ローカルの53番を使うためsudoが必要な場合あり)
sudo ssh -g -D 11080 \
-L 3080:localhost:3080 \
-L 53:localhost:3053 \
bastion-host
⚠️ Security Warning:
-gオプションはLAN内の他端末からの接続を許可します。カフェや公共Wi-Fiなどの信頼できないネットワークでは絶対に使用しないでください。第三者に踏み台を悪用されるリスクがあります。
3. クライアントPCのDNS設定
ここが重要です。OSのDNS設定を変更し、クエリをSSHトンネル(ローカルの53番)へ流します。
【重要】DNS over TCP について
SSHのポートフォワーディングは TCP です。通常のDNSはUDPを使用しますが、この構成では TCP で名前解決を行う必要があります。多くのOSはフォールバックしてくれますが、挙動として理解しておいてください。
Mac (macOS)
- 「システム設定」 > 「ネットワーク」 を開く。
- 接続中のネットワークを選択し、「詳細...」 をクリック。
- 「DNS」 タブを選択。
- 左側のDNSサーバーリストの「+」を押し、
127.0.0.1を追加して一番上に移動させる。
Windows
-
Win + Rキーを押し、ncpa.cplと入力して実行。 - 使用しているアダプターを右クリック > 「プロパティ」。
- 「インターネット プロトコル バージョン 4 (TCP/IPv4)」 を選択し、「プロパティ」。
- 「次の DNS サーバーのアドレスを使う」を選択。
- 優先 DNS サーバーに
127.0.0.1を入力。
Linux (Ubuntu/Debian系)
一時的な変更として /etc/resolv.conf を編集します。
sudo vi /etc/resolv.conf
nameserver 127.0.0.1
4. スマホ・アプリ側の設定 (PAC)
iPhoneやAndroidの実機検証を行う場合、Wi-Fi設定でプロキシを構成します。
- Wi-Fi設定画面を開く。
- HTTPプロキシ 設定を 「自動 (Automatic)」 に変更。
-
URL に以下を入力:
http://192.168.1.10:3080/socks.pac
(※PCのIPアドレスを指定します。SSH転送され、リモートのPythonサーバーから取得されます)
5. HTTPS開発環境の構築 (ここがキモ)
ここまでの設定で、スマホからのアクセスはPCを経由するようになりました。
最後に、PC上でHTTPSサーバーを偽装し、アプリを騙します。
前提条件: 正規の証明書を利用する
今回は mkcert などのオレオレ認証局ではなく、Let's Encryptなどで取得した正規の証明書 (fullchain.pem, privkey.pem) を利用する方法を紹介します。
これにより、iOS側へのプロファイルインストールが不要になり、SSL Pinningをしていないアプリであればそのまま通信が可能になります。
ローカルHTTPSプロキシの起動
local-ssl-proxy (npm) などを使い、ローカルの開発サーバー(例: 3000番)をHTTPS(443番)として公開します。
# 証明書を使って 443 -> 3000 へ転送
# (ポート443を使うためsudoが必要な場合あり)
sudo npx local-ssl-proxy \
--source 443 \
--target 3000 \
--cert /path/to/fullchain.pem \
--key /path/to/privkey.pem
何が起きるか?
- アプリが
https://api.example.comにアクセス。 - SSH経由のDNSが、PCのIP (
192.168.1.10等) を返す。 - アプリがPCの443番ポートへ接続。
- PCは 「正規の証明書」 を提示。
- アプリは「信頼された認証局の証明書」かつ「SSL Pinningなし」なので、正常なサーバーとして接続を受け入れる。
- リクエストが手元の
localhost:3000に到達!
これで、サーバーへのデプロイ待ち時間ゼロで、手元のコードを書き換えるだけでアプリの挙動確認が可能になります。
セキュリティ上の注意
この構成は非常に強力ですが、以下の点に注意してください。
-
秘密鍵の管理:
本番(または検証)ドメイン用の秘密鍵をローカルPCにコピーすることになります。紛失や流出がないよう、テスト終了後は速やかに削除するなど、取り扱いには細心の注意を払ってください。 -
公共Wi-Fiでの利用禁止:
-gオプションは閉じたLAN内(自宅やオフィスの信頼できるネットワーク)でのみ使用してください。 -
設定の戻し忘れ:
作業終了後は、PCのDNS設定やスマホのプロキシ設定を元に戻すのを忘れないようにしましょう。
まとめ
- SOCKS で通信経路を確保
- PAC でプロキシ適用ルールを制御
- DNS で名前解決をカスタマイズ
- 正規証明書 でHTTPSを透過
これらをSSH一本で束ねることで、アプリ開発のデバッグ速度は劇的に向上します。ぜひお試しください。