
SOCKSプロキシ経由でアクセス元IPアドレスが制限されたHTTPプロキシに接続するためにTinyProxyで多段プロキシ環境を構築してみた
リテールアプリ共創部@大阪の岩田です。
担当している案件のテストのためアクセス元IPアドレスが制限されたHTTPプロキシを経由しないと接続できない環境に接続する必要がありました。
クラスメソッドの社内NW環境から対象環境にアクセスできるようTinyproxyを使った多段プロキシ環境を構築してみたので内容を紹介します。
背景など
以下のブログで紹介されているように、弊社では特定の用途にSOCKSプロキシを利用しています。
古い記事なので今では色々と構成が変わってはいるのですが、IP制限のある環境にアクセスする際はSOCKSプロキシ経由でアクセスするのがファーストチョイスになるという点は現在でも変わっていません。単にIP制限のかかったサイトにブラウザでアクセスしたいだけであれば、FoxyProxy等を使ってSOCKSプロキシ経由でアクセスすれば問題なく業務が継続できるのですが、今回はもう少し制限の厳しい環境へのアクセスが必要でした。
具体的にいうとアクセスしたい対象のサイトにはアクセス元のIPアドレスを制限したHTTPプロキシを経由してアクセスする必要がありました。

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

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

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

やってみる
さっそくやっていきます。まずTinyproxyのコンテナが必要になるので以下の内容で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は以下の通りです。こちらは特に変わったことをしていません。
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です。このファイルで多段プロキシの構成を表現します。
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も作成しておきました。
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)
まとめ
今後社内で需要があるかもしれないので公開しておきます。
もし似たような構成の環境があれば参考にしてください。






