SOCKSプロキシ経由でアクセス元IPアドレスが制限されたHTTPプロキシに接続するためにTinyProxyで多段プロキシ環境を構築してみた

SOCKSプロキシ経由でアクセス元IPアドレスが制限されたHTTPプロキシに接続するためにTinyProxyで多段プロキシ環境を構築してみた

IP制限付きHTTPプロキシを経由しないとアクセスできない環境に対し、社内SOCKSプロキシを経由して接続したい。でもSOCKSプロキシの設定は自由に変更できない... こんなジレンマを解消するためにTinyproxyによる多段プロキシ環境をDockerコンテナで構築してみました。
2026.03.11

リテールアプリ共創部@大阪の岩田です。

担当している案件のテストのためアクセス元IPアドレスが制限されたHTTPプロキシを経由しないと接続できない環境に接続する必要がありました。
クラスメソッドの社内NW環境から対象環境にアクセスできるようTinyproxyを使った多段プロキシ環境を構築してみたので内容を紹介します。

背景など

以下のブログで紹介されているように、弊社では特定の用途にSOCKSプロキシを利用しています。

https://dev.classmethod.jp/articles/setup-socks-using-delegate/

古い記事なので今では色々と構成が変わってはいるのですが、IP制限のある環境にアクセスする際はSOCKSプロキシ経由でアクセスするのがファーストチョイスになるという点は現在でも変わっていません。単にIP制限のかかったサイトにブラウザでアクセスしたいだけであれば、FoxyProxy等を使ってSOCKSプロキシ経由でアクセスすれば問題なく業務が継続できるのですが、今回はもう少し制限の厳しい環境へのアクセスが必要でした。

具体的にいうとアクセスしたい対象のサイトにはアクセス元のIPアドレスを制限したHTTPプロキシを経由してアクセスする必要がありました。

HTTP Proxyを経由しないとアクセスできない

単にブラウザにHTTP Proxyを設定するだけなら簡単なのですが、外部サービスのHTTP Proxy側にアクセス元IP制限があるため、クラスメソッドのGIPを申請する必要があります。しかし普段利用しているNW環境からインターネットに抜けるGIPは固定ではありません。

HTTP Proxyにはアクセス元IP制限がある

そこで、アクセス元のGIPとしてSOCKSプロキシのGIPを申請した上でSOCKSプロキシからHTTP Proxyを経由させたいのですが、SOCKSプロキシは全社員が利用する環境であり、担当案件の都合で私個人が自由に設定変更できるものではありません。

SOCKSプロキシを経由させればアクセス元IPは固定可能

そこでSOCK Proxy側の設定変更無しに要件を実現するため、Tinyproxyを使った多段プロキシ環境を作ることにしました。

Tinyproxyで多段プロキシ環境を構築

やってみる

さっそくやっていきます。まずTinyproxyのコンテナが必要になるので以下の内容でDockerfileを用意しました。

Dockerfile
FROM alpine:latest

RUN apk add --no-cache \
    proxychains-ng \
    tinyproxy

EXPOSE 8080

CMD ["sh", "-c", "proxychains4 -f /etc/proxychains/proxychains.conf tinyproxy -d -c /etc/tinyproxy/tinyproxy.conf"]

やっていることはシンプルでalpineのベースイメージにTinyproxyをインストール&起動しているぐらいです。

上記のDockerfileのCMDで指定している設定ファイル/etc/tinyproxy/tinyproxy.confは以下の通りです。こちらは特に変わったことをしていません。

tinyproxy.conf
Port 8080
Listen 0.0.0.0
Timeout 600
DefaultErrorFile "/usr/share/tinyproxy/default.html"
LogLevel Info
MaxClients 100
MinSpareServers 5
MaxSpareServers 20
StartServers 10
MaxRequestsPerChild 0

Allow 0.0.0.0/0

DisableViaHeader Yes

キモとなるのがもう1つの設定ファイル/etc/proxychains/proxychains.confです。このファイルで多段プロキシの構成を表現します。

proxychains.conf
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000

[ProxyList]
# SOCKSプロキシ (クラスメソッド社内NW)
socks5 <SOCKSプロキシのIPアドレス> <SOCKSプロキシのポート番号>

# HTTP Proxy (外部サーバー)
http <外部HTTP ProxyのFQDN> <外部HTTP Proxyのポート番号>

ProxyListのセクションにプロキシサーバーの定義を順番に記載します。

このリストの最初のサーバーはホスト名で指定できないので、IPアドレスで記載する必要があることに注意が必要です。

一応docker-compose.yamlも作成しておきました。

docker-compose.yaml
version: '3.8'
services:
  proxy-chains:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ./tinyproxy.conf:/etc/tinyproxy/tinyproxy.conf
      - ./proxychains.conf:/etc/proxychains/proxychains.conf

これで準備が整ったのでdocker compose upでTinyproxyのコンテナを起動ます。

NOTICE    Mar 10 09:25:16.393 [1]: Initializing tinyproxy ...
NOTICE    Mar 10 09:25:16.393 [1]: Reloading config file (/etc/tinyproxy/tinyproxy.conf)
INFO      Mar 10 09:25:16.393 [1]: Added address [0.0.0.0] to listen addresses.
INFO      Mar 10 09:25:16.393 [1]: Disabling transmission of the "Via" header.
WARNING   Mar 10 09:25:16.393 [1]: You SHOULD set a UserName in the config file. Using current user instead.
NOTICE    Mar 10 09:25:16.393 [1]: Reloading config file finished
INFO      Mar 10 09:25:16.393 [1]: listen_sock called with addr = '0.0.0.0'
INFO      Mar 10 09:25:16.393 [1]: trying to listen on host[0.0.0.0], family[2], socktype[1], proto[0]
INFO      Mar 10 09:25:16.393 [1]: listening on fd [3]
INFO      Mar 10 09:25:16.393 [1]: Setting the various signals.
INFO      Mar 10 09:25:16.393 [1]: Starting main loop. Accepting connections.

起動できたのでChromeからTinyproxy経由で対象サイトにアクセスすると...

無事にアクセスできました!! ※といっても画面キャプチャが乗せられないので文字だけなってしまいますが...

docker logsで確認したTinyproxyのログは以下の通りでした。

CONNECT   Mar 10 09:26:29.599 [1]: Connect (file descriptor 12): 172.27.0.1
CONNECT   Mar 10 09:26:29.599 [1]: Connect (file descriptor 13): 172.27.0.1
CONNECT   Mar 10 09:26:29.599 [1]: Request (file descriptor 12): CONNECT <最終的なアクセス先>:443 HTTP/1.1
CONNECT   Mar 10 09:26:29.599 [1]: Request (file descriptor 13): CONNECT <最終的なアクセス先>:443 HTTP/1.1
INFO      Mar 10 09:26:29.599 [1]: No upstream proxy for <最終的なアクセス先>
INFO      Mar 10 09:26:29.599 [1]: opensock: opening connection to <最終的なアクセス先>:443
INFO      Mar 10 09:26:29.600 [1]: No upstream proxy for <最終的なアクセス先>
INFO      Mar 10 09:26:29.600 [1]: opensock: opening connection to <最終的なアクセス先>:443
INFO      Mar 10 09:26:29.600 [1]: opensock: getaddrinfo returned for <最終的なアクセス先>:443
INFO      Mar 10 09:26:29.600 [1]: opensock: getaddrinfo returned for <最終的なアクセス先>:443
CONNECT   Mar 10 09:26:29.707 [1]: Established connection to host "<最終的なアクセス先>:" using file descriptor 16.
INFO      Mar 10 09:26:29.707 [1]: Not sending client headers to remote machine
[proxychains] Strict chain  ...  <SOCKSプロキシのIPアドレス>:<SOCKSプロキシのポート番号> [proxychains] Strict chain  ...  <SOCKSプロキシのIPアドレス>:<SOCKSプロキシのポート番号>  ...  <HTTP ProxyのFQDN>:<HTTP Proxyのポート番号>  ...  <HTTP ProxyのFQDN>:<HTTP Proxyのポート番号>  ...  <最終的なアクセス先>:443  ...  <最終的なアクセス先>:443  ...  OK
CONNECT   Mar 10 09:26:29.716 [1]: Established connection to host "<最終的なアクセス先>" using file descriptor 14.
INFO      Mar 10 09:26:29.716 [1]: Not sending client headers to remote machine
 ...  OK
CONNECT   Mar 10 09:26:30.083 [1]: Connect (file descriptor 15): 172.27.0.1
CONNECT   Mar 10 09:26:30.083 [1]: Connect (file descriptor 17): 172.27.0.1
CONNECT   Mar 10 09:26:30.084 [1]: Request (file descriptor 17): CONNECT <最終的なアクセス先>:443 HTTP/1.1
CONNECT   Mar 10 09:26:30.084 [1]: Request (file descriptor 15): CONNECT <最終的なアクセス先>:443 HTTP/1.1
INFO      Mar 10 09:26:30.084 [1]: No upstream proxy for <最終的なアクセス先>
INFO      Mar 10 09:26:30.084 [1]: opensock: opening connection to <最終的なアクセス先>:443
INFO      Mar 10 09:26:30.084 [1]: No upstream proxy for <最終的なアクセス先>
INFO      Mar 10 09:26:30.085 [1]: opensock: opening connection to <最終的なアクセス先>:443
INFO      Mar 10 09:26:30.085 [1]: opensock: getaddrinfo returned for <最終的なアクセス先>:443
INFO      Mar 10 09:26:30.085 [1]: opensock: getaddrinfo returned for <最終的なアクセス先>:443
CONNECT   Mar 10 09:26:30.095 [1]: Connect (file descriptor 22): 172.27.0.1
CONNECT   Mar 10 09:26:30.096 [1]: Request (file descriptor 22): CONNECT <最終的なアクセス先>:443 HTTP/1.1
INFO      Mar 10 09:26:30.096 [1]: No upstream proxy for <最終的なアクセス先>
INFO      Mar 10 09:26:30.096 [1]: opensock: opening connection to <最終的なアクセス先>:443
INFO      Mar 10 09:26:30.097 [1]: opensock: getaddrinfo returned for <最終的なアクセス先>:443
CONNECT   Mar 10 09:26:30.213 [1]: Established connection to host "<最終的なアクセス先>" using file descriptor 23.
INFO      Mar 10 09:26:30.213 [1]: Not sending client headers to remote machine
[proxychains] Strict chain  ...  <SOCKSプロキシのIPアドレス>:<SOCKSプロキシのポート番号> [proxychains] Strict chain  ...  <SOCKSプロキシのIPアドレス>:<SOCKSプロキシのポート番号> [proxychains] Strict chain  ...  <SOCKSプロキシのIPアドレス>:<SOCKSプロキシのポート番号>  ...  <HTTP ProxyのFQDN>:<HTTP Proxyのポート番号>  ...  <HTTP ProxyのFQDN>:<HTTP Proxyのポート番号>  ...  <HTTP ProxyのFQDN>:<HTTP Proxyのポート番号>  ...  <最終的なアクセス先>:443  ...  <最終的なアクセス先>:443  ...  <最終的なアクセス先>:443  ...  OK
 ...  OK
 ...  OK
CONNECT   Mar 10 09:26:30.223 [1]: Established connection to host "<最終的なアクセス先>" using file descriptor 20.
INFO      Mar 10 09:26:30.223 [1]: Not sending client headers to remote machine
CONNECT   Mar 10 09:26:30.224 [1]: Established connection to host "<最終的なアクセス先>" using file descriptor 18.
INFO      Mar 10 09:26:30.224 [1]: Not sending client headers to remote machine
INFO      Mar 10 09:26:30.341 [1]: Closed connection between local client (fd:17) and remote client (fd:18)

まとめ

今後社内で需要があるかもしれないので公開しておきます。

もし似たような構成の環境があれば参考にしてください。

参考

この記事をシェアする

FacebookHatena blogX

関連記事