LANの内壁を抜けて外へ通信させる ~SSHとproxychains-ng~

Page content

経路的にSSHできるなら戻れるのでは?

インターネットへのアクセスがFirewallの設定で遮断されているLAN内のサーバへ、リモートからSSHログインし、そのサーバ上でインターネットのリソースを使いたい、という状況はよくある。

そんな状況に相当する、OS・導入パッケージの更新作業apt update && apt upgradeや新しいモジュールの導入作業pip installを、必要なファイルをscpでコピーしてから行う、“オフラインインストール”で実施することは不可能ではない。が、オンラインインストールよりも手間と時間を費やさねばならず、億劫なことになりがちだ。

しかし考えてみると、手元のマシンからサーバへSSHログインはできているのだから、逆向きの経路を作って、サーバからインターネットへアクセスしようとする通信をスマートにその経路へ流すことはできないだろうか? もしこれが可能なら、手元のマシンをインターネットアクセス時の踏み台にできるぞ。

そう当たりをつけて調べてみると、やはり予想通り、SSHトンネリングと組み合わせての便利なツールがこの世に存在していたのであった。

proxychains-ngというwrapper

今回見つけたツールは、次のproxychains-ngというもの。

末尾の-ngはNew Generationの意味で、元々あるツールproxychainsの後継とのこと。

このツールは、OSのライブラリ環境をハックし、ネットワークを利用する各種コマンドにwrapperとしてかますだけの簡単操作で、コマンドでの通信がSOCKS/HTTPプロキシを経由するように仕向けてくれるもの (Torのtorsocksと同様かな)。DNSアクセスもうまく処理してくれるそうだ。

想定環境

次の図のような環境において、「サーバBからインターネットを使う」動作を、proxychains-ngとOpenSSHを併用することで実現する。

[マシンA] --> (インターネット) --> [Firewall] --> [踏み台サーバJ] --> [サーバB]

マシンAとサーバBは、次の条件を満たしているものとする。

  • お手元のマシンA:
    1. インターネットへアクセスできる
    2. 踏み台サーバJなどを経由したSSH多段接続またはSSH直接接続で、LAN内のサーバBにログインできる
  • LAN内のサーバB:
    1. sshdが動作している
    2. インターネットへのアクセスがFirewallなどで遮断されている
    3. proxychains-ngを導入可能 (root権限は必須ではない)

proxychains-ngをサーバBへ導入

proxychains-ngの最新版を、Releases · rofl0r/proxychains-ngから取得してサーバBに転送し、次のコマンドで展開してmakeする。ちなみにmakeは、x86_64の他にaarch64アーキテクチャでも問題なく行えた。

$ tar Jxvf ./proxychains-ng-4.14.tar.xz
$ cd proxychains-ng-4.14
$ ./configure --prefix=/usr --sysconfdir=/etc
$ make

$ ls -al proxychains4 libproxychains4.so # makeされたファイルを確認
$ sudo make install # optional (やらなくても動作可能)

設定ファイルproxychains.confの一例として、次の内容のファイルを用意する。

$ cat /etc/proxychains.conf
strict_chain
proxy_dns
quiet_mode
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000

[ProxyList]
socks5 127.0.0.1 1080

設定ファイルproxychains.confは、READMEによると次の順に探索されるので、自分の好みの場所に設置しておく。

proxychains looks for config file in following order:
1)	file listed in environment variable PROXYCHAINS_CONF_FILE or
	provided as a -f argument to proxychains script or binary.
2)	./proxychains.conf
3)	$(HOME)/.proxychains/proxychains.conf
4)	$(sysconfdir)/proxychains.conf  **

** usually /etc/proxychains.conf

なお、実行ファイルproxychains4を引数無しで実行すると、次の使い方メッセージが表示される。

$ ./proxychains4

Usage:	./proxychains4 -q -f config_file program_name [arguments]
	-q makes proxychains quiet - this overrides the config setting
	-f allows one to manually specify a configfile to use
	for example : proxychains telnet somehost.com
More help in README file

SSHにSOCKSプロキシのふりをさせる

マシンAからサーバBへSSHアクセスするための設定 (SSH多段接続など) は、すでに出来ているものとして説明は省略。

a) sshコマンドを2つ組み合わせる方法

SOCKSプロキシのふりをさせるSSHトンネリングの方法は、sshポートフォワーディングについて図示してみる - Qiitaで紹介されている次の2つが伝統的なものらしい。これらではsshの-R-Dの組み合わせを使う。詳細は、図もある各リンク先を参照。

b) sshコマンド1つの方法: “reverse dynamic forwarding”

比較的新しい、SOCKSプロキシのふりをさせるSSHトンネリングの方法として、接続先のサーバーへインターネット接続を共有しつつssh接続する - Qiitaで見つけた次の方法が簡素なので、今回これを覚えておきたい。こちらではsshの-Rのみを使う。

# マシンAで実行
$ ssh -R 1080 ユーザB@サーバB

この指定方法でSOCKSプロキシのふりをさせることができるのは、OpenSSH 7.6での新機能ssh(1): add support for reverse dynamic forwarding.によると思われる。

サーバBからインターネットへ

上記 b) のようにマシンAでssh -R 1080 ユーザB@サーバBを実行した後、次にサーバBでは、curlaptなどの、インターネットを利用するコマンドの前にproxychains4を付けて実行する。

# マシンAで実行
$ ssh -R 1080 ユーザB@サーバB

# サーバBで実行
$ proxychains4 curl ifconfig.me
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/local/lib/libproxychains4.so
217.178.XXX.YYY

$ sudo proxychains4 apt update
(以降省略)

するとこれだけで、LAN内にあるサーバBから、マシンAを踏み台にしたインターネットへの通信が成立する。

長い間、当該環境での制約と思い込んでいたネットワーク上の壁を、こんなにも簡単に抜け出てしまえるとは。SSH周りは奥が深い。

追記 [2021-02-08]

サーバBのbash (シェル環境) ごとproxychains4を介して起動しておけば、シェルの上のプロセスは自動的にプロキシ経由の通信になる、という大技を紹介している記事を発見。

やってみたら確かにそうなる。

# マシンAで実行
$ ssh -R 1080 ユーザB@サーバB

# サーバBで実行
$ proxychains4 bash
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/local/lib/libproxychains4.so
$ curl ifconfig.me
217.178.XXX.YYY

$ sudo proxychains4 bash