LANの内壁を抜けて外へ通信させる ~SSHとproxychains-ng~
経路的にSSHできるなら戻れるのでは?
インターネットへのアクセスがFirewallの設定で遮断されているLAN内のサーバへ、リモートからSSHログインし、そのサーバ上でインターネットのリソースを使いたい、という状況はよくある。
そんな状況に相当する、OS・導入パッケージの更新作業apt update && apt upgrade
や新しいモジュールの導入作業pip install
を、必要なファイルをscpでコピーしてから行う、“オフラインインストール”で実施することは不可能ではない。が、オンラインインストールよりも手間と時間を費やさねばならず、億劫なことになりがちだ。
しかし考えてみると、手元のマシンからサーバへSSHログインはできているのだから、逆向きの経路を作って、サーバからインターネットへアクセスしようとする通信をスマートにその経路へ流すことはできないだろうか? もしこれが可能なら、手元のマシンをインターネットアクセス時の踏み台にできるぞ。
そう当たりをつけて調べてみると、やはり予想通り、SSHトンネリングと組み合わせての便利なツールがこの世に存在していたのであった。
proxychains-ngというwrapper
今回見つけたツールは、次のproxychains-ng (proxychains4)
というもの。
末尾の-ng
はNew Generationの意味で、元々あるツールproxychains
の後継とのこと。
このツールは、OSのライブラリ環境をハックし、ネットワークを利用する各種コマンドにwrapperとしてかますだけの簡単操作で、コマンドでの通信がSOCKS/HTTPプロキシを経由するように仕向けてくれるもの (Torのtorsocksと同様かな)。DNSアクセスもうまく処理してくれるそうだ。
想定環境
次の図のような環境において、「サーバBからインターネットを使う」動作を、proxychains-ng
とOpenSSHを併用することで実現する。
[マシンA] --> (インターネット) --> [Firewall] --> [踏み台サーバJ] --> [サーバB]
マシンAとサーバBは、次の条件を満たしているものとする。
- お手元のマシンA:
- インターネットへアクセスできる
- 踏み台サーバJなどを経由したSSH多段接続またはSSH直接接続で、LAN内のサーバBにログインできる
- LAN内のサーバB:
- sshdが動作している
- インターネットへのアクセスがFirewallなどで遮断されている
proxychains-ng
を導入可能 (root権限は必須ではない)
proxychains-ngをサーバBへ導入
proxychains-ng
の最新版を、Releases · rofl0r/proxychains-ngから取得してサーバBに転送し、次のコマンドで展開してmakeする。ちなみにmakeは、x86_64の他にaarch64アーキテクチャでも問題なく行えた。
$ tar Jxvf ./proxychains-ng-4.15.tar.xz
$ cd proxychains-ng-4.15
$ ./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では、curl
やapt
などの、インターネットを利用するコマンドの前に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