まれによくある次のような構成。
+-----+
| gw |
+--+--+
|
+---+---+ | +-------+ +-------+
| hostA |--+--| hostB |----| hostC |
+-------+ +-------+ +-------+
- hostA からは直接インターネットに出れる
- hostC からは直接インターネットには出られない
- hostA から hostC には hostB を経由しなければアクセスできない
この状況で hostC で yum する方法。
ProxyCommand
hostA から hostC へは ProxyCommand を使えば簡単に接続できます。ググるといろいろ情報は出てきます。
$ ssh -o "ProxyCommand ssh hostB nc -w 60 %h %p" hostC
あるいは、
$ ssh -o "ProxyCommand ssh hostB -W %h:%p" hostC
普通は ~/.ssh/config
に書いておくのでしょうね。
この hostA → hostC の接続を使って hostC から hostA を経由して yum します。
SOCKS Proxy
hostC の libcurl が比較的新しいバージョンであれば ALL_PROXY
環境変数で SOCKS プロキシが指定できるので簡単です。
まずは hostA に SOCKS プロキシを立てます。
$ ssh -D 1080 localhost
次に ssh の -R
で「hostC → hostA」の方向でポートフォワードしつつ hostC にログインします。
$ ssh -R 1080:localhost:1080 -o "ProxyCommand ssh hostB -W %h:%p" hostC
hostC の 1080 ポートが hostA の 1080 ポートに転送されているので ALL_PROXY
環境変数で SOCKS プロキシとして指定しつつ yum します。
$ ALL_PROXY=socks5h://localhost:1080 yum list
socks5://
と指定すると名前解決が hostC で行なわれます。socks5h://
と指定すれば名前解決も SOCKS プロキシ(つまり hostA)で行われます。
HTTP Proxy
CentOS 6 だと libcurl が微妙に古いようで yum の中の curl に SOCKS プロキシを指定する簡単な方法がわかりませんでした。curl そのものは SOCKS プロキシに対応しているようなのですが・・・
なので、hostA で HTTP プロキシを立てることにします。
プロキシサーバなら Squid とか Apache とかでも出来ますが、これだけの用途なら node.js で作るのが簡単かもしれません。
$ npm install http-proxy@0.9
$ cat <<EOS> fproxy.js
var net = require('net');
var url = require('url');
var server = require('http').createServer();
var httpProxy = require('http-proxy');
var proxy = new httpProxy.RoutingProxy();
server.on('request', function(req, res) {
var uri = url.parse(req.url);
proxy.proxyRequest(req, res, {
host: uri.hostname,
port: uri.port || 80
});
});
server.on('connect', function(req, socket, head) {
var arr = req.url.split(':', 2);
var conn = net.connect(arr[1], arr[0], function() {
socket.write("HTTP/1.1 200 OK\r\n\r\n");
socket.pipe(conn);
conn.pipe(socket);
});
});
server.listen(8080, '127.0.0.1');
EOS
プロキシサーバを実行します。
$ node fproxy.js &
-R
でポートフォワードしつつ hostC にログインします。
$ ssh -R 8080:localhost:8080 -o "ProxyCommand ssh hostB -W %h:%p" hostC
hostC の 8080 ポートが hostA の 8080 ポートに転送されているので ALL_PROXY
環境変数でプロキシとして指定しつつ yum します。
$ ALL_PROXY=http://localhost:8080 yum list